2 * Server side of OSPF API.
3 * Copyright (C) 2001, 2002 Ralph Keller
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 #ifdef SUPPORT_OSPF_API
26 #ifndef HAVE_OPAQUE_LSA
27 #error "Core Opaque-LSA module must be configured."
28 #endif /* HAVE_OPAQUE_LSA */
41 #include "sockunion.h" /* for inet_aton() */
44 #include <sys/types.h>
46 #include "ospfd/ospfd.h" /* for "struct thread_master" */
47 #include "ospfd/ospf_interface.h"
48 #include "ospfd/ospf_ism.h"
49 #include "ospfd/ospf_asbr.h"
50 #include "ospfd/ospf_lsa.h"
51 #include "ospfd/ospf_lsdb.h"
52 #include "ospfd/ospf_neighbor.h"
53 #include "ospfd/ospf_nsm.h"
54 #include "ospfd/ospf_flood.h"
55 #include "ospfd/ospf_packet.h"
56 #include "ospfd/ospf_spf.h"
57 #include "ospfd/ospf_dump.h"
58 #include "ospfd/ospf_route.h"
59 #include "ospfd/ospf_ase.h"
60 #include "ospfd/ospf_zebra.h"
62 #include "ospfd/ospf_api.h"
63 #include "ospfd/ospf_apiserver.h"
65 /* This is an implementation of an API to the OSPF daemon that allows
66 * external applications to access the OSPF daemon through socket
67 * connections. The application can use this API to inject its own
68 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
69 * daemons then receive these LSAs and inform applications through the
70 * API by sending a corresponding message. The application can also
71 * register to receive all LSA types (in addition to opaque types) and
72 * use this information to reconstruct the OSPF's LSDB. The OSPF
73 * daemon supports multiple applications concurrently. */
75 /* List of all active connections. */
76 struct list
*apiserver_list
;
78 /* -----------------------------------------------------------
79 * Functions to lookup interfaces
80 * -----------------------------------------------------------
83 struct ospf_interface
*
84 ospf_apiserver_if_lookup_by_addr (struct in_addr address
)
86 struct listnode
*node
, *nnode
;
87 struct ospf_interface
*oi
;
90 if (!(ospf
= ospf_lookup ()))
93 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
94 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
95 if (IPV4_ADDR_SAME (&address
, &oi
->address
->u
.prefix4
))
101 struct ospf_interface
*
102 ospf_apiserver_if_lookup_by_ifp (struct interface
*ifp
)
104 struct listnode
*node
, *nnode
;
105 struct ospf_interface
*oi
;
108 if (!(ospf
= ospf_lookup ()));
111 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
118 /* -----------------------------------------------------------
120 * -----------------------------------------------------------
124 ospf_apiserver_getport (void)
126 struct servent
*sp
= getservbyname ("ospfapi", "tcp");
128 return sp
? ntohs (sp
->s_port
) : OSPF_API_SYNC_PORT
;
131 /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
133 ospf_apiserver_init (void)
138 /* Create new socket for synchronous messages. */
139 fd
= ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET
);
144 /* Schedule new thread that handles accepted connections. */
145 ospf_apiserver_event (OSPF_APISERVER_ACCEPT
, fd
, NULL
);
147 /* Initialize list that keeps track of all connections. */
148 apiserver_list
= list_new ();
150 /* Register opaque-independent call back functions. These functions
151 are invoked on ISM, NSM changes and LSA update and LSA deletes */
153 ospf_register_opaque_functab (0 /* all LSAs */,
154 0 /* all opaque types */,
155 ospf_apiserver_new_if
,
156 ospf_apiserver_del_if
,
157 ospf_apiserver_ism_change
,
158 ospf_apiserver_nsm_change
,
162 NULL
, /* ospf_apiserver_show_info */
163 NULL
, /* originator_func */
164 NULL
, /* ospf_apiserver_lsa_refresher */
165 ospf_apiserver_lsa_update
,
166 ospf_apiserver_lsa_delete
);
169 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
178 /* Terminate OSPF API module. */
180 ospf_apiserver_term (void)
182 struct ospf_apiserver
*apiserv
;
184 /* Unregister wildcard [0/0] type */
185 ospf_delete_opaque_functab (0 /* all LSAs */,
186 0 /* all opaque types */);
189 * Free all client instances. ospf_apiserver_free removes the node
190 * from the list, so we examine the head of the list anew each time.
192 while ( apiserver_list
&&
193 (apiserv
= listgetdata (listhead (apiserver_list
))) != NULL
)
194 ospf_apiserver_free (apiserv
);
196 /* Free client list itself */
198 list_delete (apiserver_list
);
200 /* Free wildcard list */
204 static struct ospf_apiserver
*
205 lookup_apiserver (u_char lsa_type
, u_char opaque_type
)
207 struct listnode
*n1
, *n2
;
208 struct registered_opaque_type
*r
;
209 struct ospf_apiserver
*apiserv
, *found
= NULL
;
211 /* XXX: this approaches O(n**2) */
212 for (ALL_LIST_ELEMENTS_RO (apiserver_list
, n1
, apiserv
))
214 for (ALL_LIST_ELEMENTS_RO (apiserv
->opaque_types
, n2
, r
))
215 if (r
->lsa_type
== lsa_type
&& r
->opaque_type
== opaque_type
)
225 static struct ospf_apiserver
*
226 lookup_apiserver_by_lsa (struct ospf_lsa
*lsa
)
228 struct lsa_header
*lsah
= lsa
->data
;
229 struct ospf_apiserver
*found
= NULL
;
231 if (IS_OPAQUE_LSA (lsah
->type
))
233 found
= lookup_apiserver (lsah
->type
,
234 GET_OPAQUE_TYPE (ntohl (lsah
->id
.s_addr
)));
239 /* -----------------------------------------------------------
240 * Followings are functions to manage client connections.
241 * -----------------------------------------------------------
244 ospf_apiserver_new_lsa_hook (struct ospf_lsa
*lsa
)
246 if (IS_DEBUG_OSPF_EVENT
)
247 zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa
, dump_lsa_key (lsa
), lsa
->lsdb
->total
);
252 ospf_apiserver_del_lsa_hook (struct ospf_lsa
*lsa
)
254 if (IS_DEBUG_OSPF_EVENT
)
255 zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa
, dump_lsa_key (lsa
), lsa
->lsdb
->total
);
259 /* Allocate new connection structure. */
260 struct ospf_apiserver
*
261 ospf_apiserver_new (int fd_sync
, int fd_async
)
263 struct ospf_apiserver
*new =
264 XMALLOC (MTYPE_OSPF_APISERVER
, sizeof (struct ospf_apiserver
));
267 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER
, sizeof (struct lsa_filter_type
));
269 new->fd_sync
= fd_sync
;
270 new->fd_async
= fd_async
;
272 /* list of registered opaque types that application uses */
273 new->opaque_types
= list_new ();
275 /* Initialize temporary strage for LSA instances to be refreshed. */
276 memset (&new->reserve
, 0, sizeof (struct ospf_lsdb
));
277 ospf_lsdb_init (&new->reserve
);
279 new->reserve
.new_lsa_hook
= ospf_apiserver_new_lsa_hook
; /* debug */
280 new->reserve
.del_lsa_hook
= ospf_apiserver_del_lsa_hook
; /* debug */
282 new->out_sync_fifo
= msg_fifo_new ();
283 new->out_async_fifo
= msg_fifo_new ();
284 new->t_sync_read
= NULL
;
285 #ifdef USE_ASYNC_READ
286 new->t_async_read
= NULL
;
287 #endif /* USE_ASYNC_READ */
288 new->t_sync_write
= NULL
;
289 new->t_async_write
= NULL
;
291 new->filter
->typemask
= 0; /* filter all LSAs */
292 new->filter
->origin
= ANY_ORIGIN
;
293 new->filter
->num_areas
= 0;
299 ospf_apiserver_event (enum event event
, int fd
,
300 struct ospf_apiserver
*apiserv
)
302 struct thread
*apiserver_serv_thread
;
306 case OSPF_APISERVER_ACCEPT
:
307 apiserver_serv_thread
=
308 thread_add_read (master
, ospf_apiserver_accept
, apiserv
, fd
);
310 case OSPF_APISERVER_SYNC_READ
:
311 apiserv
->t_sync_read
=
312 thread_add_read (master
, ospf_apiserver_read
, apiserv
, fd
);
314 #ifdef USE_ASYNC_READ
315 case OSPF_APISERVER_ASYNC_READ
:
316 apiserv
->t_async_read
=
317 thread_add_read (master
, ospf_apiserver_read
, apiserv
, fd
);
319 #endif /* USE_ASYNC_READ */
320 case OSPF_APISERVER_SYNC_WRITE
:
321 if (!apiserv
->t_sync_write
)
323 apiserv
->t_sync_write
=
324 thread_add_write (master
, ospf_apiserver_sync_write
, apiserv
, fd
);
327 case OSPF_APISERVER_ASYNC_WRITE
:
328 if (!apiserv
->t_async_write
)
330 apiserv
->t_async_write
=
331 thread_add_write (master
, ospf_apiserver_async_write
, apiserv
, fd
);
337 /* Free instance. First unregister all opaque types used by
338 application, flush opaque LSAs injected by application
339 from network and close connection. */
341 ospf_apiserver_free (struct ospf_apiserver
*apiserv
)
343 struct listnode
*node
;
345 /* Cancel read and write threads. */
346 if (apiserv
->t_sync_read
)
348 thread_cancel (apiserv
->t_sync_read
);
350 #ifdef USE_ASYNC_READ
351 if (apiserv
->t_async_read
)
353 thread_cancel (apiserv
->t_async_read
);
355 #endif /* USE_ASYNC_READ */
356 if (apiserv
->t_sync_write
)
358 thread_cancel (apiserv
->t_sync_write
);
361 if (apiserv
->t_async_write
)
363 thread_cancel (apiserv
->t_async_write
);
366 /* Unregister all opaque types that application registered
367 and flush opaque LSAs if still in LSDB. */
369 while ((node
= listhead (apiserv
->opaque_types
)) != NULL
)
371 struct registered_opaque_type
*regtype
= listgetdata(node
);
373 ospf_apiserver_unregister_opaque_type (apiserv
, regtype
->lsa_type
,
374 regtype
->opaque_type
);
378 /* Close connections to OSPFd. */
379 if (apiserv
->fd_sync
> 0)
381 close (apiserv
->fd_sync
);
384 if (apiserv
->fd_async
> 0)
386 close (apiserv
->fd_async
);
390 msg_fifo_free (apiserv
->out_sync_fifo
);
391 msg_fifo_free (apiserv
->out_async_fifo
);
393 /* Clear temporary strage for LSA instances to be refreshed. */
394 ospf_lsdb_delete_all (&apiserv
->reserve
);
395 ospf_lsdb_cleanup (&apiserv
->reserve
);
397 /* Remove from the list of active clients. */
398 listnode_delete (apiserver_list
, apiserv
);
400 if (IS_DEBUG_OSPF_EVENT
)
401 zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv
, apiserver_list
->count
);
403 /* And free instance. */
404 XFREE (MTYPE_OSPF_APISERVER
, apiserv
);
408 ospf_apiserver_read (struct thread
*thread
)
410 struct ospf_apiserver
*apiserv
;
416 apiserv
= THREAD_ARG (thread
);
417 fd
= THREAD_FD (thread
);
419 if (fd
== apiserv
->fd_sync
)
421 event
= OSPF_APISERVER_SYNC_READ
;
422 apiserv
->t_sync_read
= NULL
;
424 if (IS_DEBUG_OSPF_EVENT
)
425 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
426 inet_ntoa (apiserv
->peer_sync
.sin_addr
),
427 ntohs (apiserv
->peer_sync
.sin_port
));
429 #ifdef USE_ASYNC_READ
430 else if (fd
== apiserv
->fd_async
)
432 event
= OSPF_APISERVER_ASYNC_READ
;
433 apiserv
->t_async_read
= NULL
;
435 if (IS_DEBUG_OSPF_EVENT
)
436 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
437 inet_ntoa (apiserv
->peer_async
.sin_addr
),
438 ntohs (apiserv
->peer_async
.sin_port
));
440 #endif /* USE_ASYNC_READ */
443 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd
);
444 ospf_apiserver_free (apiserv
);
448 /* Read message from fd. */
453 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd
);
455 /* Perform cleanup. */
456 ospf_apiserver_free (apiserv
);
460 if (IS_DEBUG_OSPF_EVENT
)
463 /* Dispatch to corresponding message handler. */
464 rc
= ospf_apiserver_handle_msg (apiserv
, msg
);
466 /* Prepare for next message, add read thread. */
467 ospf_apiserver_event (event
, fd
, apiserv
);
476 ospf_apiserver_sync_write (struct thread
*thread
)
478 struct ospf_apiserver
*apiserv
;
483 apiserv
= THREAD_ARG (thread
);
485 fd
= THREAD_FD (thread
);
487 apiserv
->t_sync_write
= NULL
;
490 if (fd
!= apiserv
->fd_sync
)
492 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd
);
496 if (IS_DEBUG_OSPF_EVENT
)
497 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
498 inet_ntoa (apiserv
->peer_sync
.sin_addr
),
499 ntohs (apiserv
->peer_sync
.sin_port
));
501 /* Check whether there is really a message in the fifo. */
502 msg
= msg_fifo_pop (apiserv
->out_sync_fifo
);
505 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
509 if (IS_DEBUG_OSPF_EVENT
)
512 rc
= msg_write (fd
, msg
);
514 /* Once a message is dequeued, it should be freed anyway. */
520 ("ospf_apiserver_sync_write: write failed on fd=%d", fd
);
525 /* If more messages are in sync message fifo, schedule write thread. */
526 if (msg_fifo_head (apiserv
->out_sync_fifo
))
528 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE
, apiserv
->fd_sync
,
536 /* Perform cleanup and disconnect with peer */
537 ospf_apiserver_free (apiserv
);
545 ospf_apiserver_async_write (struct thread
*thread
)
547 struct ospf_apiserver
*apiserv
;
552 apiserv
= THREAD_ARG (thread
);
554 fd
= THREAD_FD (thread
);
556 apiserv
->t_async_write
= NULL
;
559 if (fd
!= apiserv
->fd_async
)
561 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd
);
565 if (IS_DEBUG_OSPF_EVENT
)
566 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
567 inet_ntoa (apiserv
->peer_async
.sin_addr
),
568 ntohs (apiserv
->peer_async
.sin_port
));
570 /* Check whether there is really a message in the fifo. */
571 msg
= msg_fifo_pop (apiserv
->out_async_fifo
);
574 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
578 if (IS_DEBUG_OSPF_EVENT
)
581 rc
= msg_write (fd
, msg
);
583 /* Once a message is dequeued, it should be freed anyway. */
589 ("ospf_apiserver_async_write: write failed on fd=%d", fd
);
594 /* If more messages are in async message fifo, schedule write thread. */
595 if (msg_fifo_head (apiserv
->out_async_fifo
))
597 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE
, apiserv
->fd_async
,
605 /* Perform cleanup and disconnect with peer */
606 ospf_apiserver_free (apiserv
);
614 ospf_apiserver_serv_sock_family (unsigned short port
, int family
)
620 memset (&su
, 0, sizeof (union sockunion
));
621 su
.sa
.sa_family
= family
;
623 /* Make new socket */
624 accept_sock
= sockunion_stream_socket (&su
);
628 /* This is a server, so reuse address and port */
629 sockopt_reuseaddr (accept_sock
);
630 sockopt_reuseport (accept_sock
);
632 /* Bind socket to address and given port. */
633 rc
= sockunion_bind (accept_sock
, &su
, port
, NULL
);
636 close (accept_sock
); /* Close socket */
640 /* Listen socket under queue length 3. */
641 rc
= listen (accept_sock
, 3);
644 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
645 safe_strerror (errno
));
646 close (accept_sock
); /* Close socket */
653 /* Accept connection request from external applications. For each
654 accepted connection allocate own connection instance. */
656 ospf_apiserver_accept (struct thread
*thread
)
662 struct ospf_apiserver
*apiserv
;
663 struct sockaddr_in peer_async
;
664 struct sockaddr_in peer_sync
;
665 unsigned int peerlen
;
668 /* THREAD_ARG (thread) is NULL */
669 accept_sock
= THREAD_FD (thread
);
671 /* Keep hearing on socket for further connections. */
672 ospf_apiserver_event (OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
674 memset (&su
, 0, sizeof (union sockunion
));
675 /* Accept connection for synchronous messages */
676 new_sync_sock
= sockunion_accept (accept_sock
, &su
);
677 if (new_sync_sock
< 0)
679 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno
));
683 /* Get port address and port number of peer to make reverse connection.
684 The reverse channel uses the port number of the peer port+1. */
686 memset(&peer_sync
, 0, sizeof(struct sockaddr_in
));
687 peerlen
= sizeof (struct sockaddr_in
);
689 ret
= getpeername (new_sync_sock
, (struct sockaddr
*)&peer_sync
, &peerlen
);
692 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno
));
693 close (new_sync_sock
);
697 if (IS_DEBUG_OSPF_EVENT
)
698 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
699 inet_ntoa (peer_sync
.sin_addr
), ntohs (peer_sync
.sin_port
));
701 /* Create new socket for asynchronous messages. */
702 peer_async
= peer_sync
;
703 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
705 /* Check if remote port number to make reverse connection is valid one. */
706 if (ntohs (peer_async
.sin_port
) == ospf_apiserver_getport ())
708 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
709 inet_ntoa (peer_async
.sin_addr
), ntohs (peer_async
.sin_port
));
710 close (new_sync_sock
);
714 new_async_sock
= socket (AF_INET
, SOCK_STREAM
, 0);
715 if (new_async_sock
< 0)
717 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno
));
718 close (new_sync_sock
);
722 ret
= connect (new_async_sock
, (struct sockaddr
*) &peer_async
,
723 sizeof (struct sockaddr_in
));
727 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno
));
728 close (new_sync_sock
);
729 close (new_async_sock
);
733 #ifdef USE_ASYNC_READ
734 #else /* USE_ASYNC_READ */
735 /* Make the asynchronous channel write-only. */
736 ret
= shutdown (new_async_sock
, SHUT_RD
);
739 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno
));
740 close (new_sync_sock
);
741 close (new_async_sock
);
744 #endif /* USE_ASYNC_READ */
746 /* Allocate new server-side connection structure */
747 apiserv
= ospf_apiserver_new (new_sync_sock
, new_async_sock
);
749 /* Add to active connection list */
750 listnode_add (apiserver_list
, apiserv
);
751 apiserv
->peer_sync
= peer_sync
;
752 apiserv
->peer_async
= peer_async
;
754 /* And add read threads for new connection */
755 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
756 #ifdef USE_ASYNC_READ
757 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ
, new_async_sock
, apiserv
);
758 #endif /* USE_ASYNC_READ */
760 if (IS_DEBUG_OSPF_EVENT
)
761 zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv
, apiserver_list
->count
);
767 /* -----------------------------------------------------------
768 * Send reply with return code to client application
769 * -----------------------------------------------------------
773 ospf_apiserver_send_msg (struct ospf_apiserver
*apiserv
, struct msg
*msg
)
775 struct msg_fifo
*fifo
;
780 switch (msg
->hdr
.msgtype
)
783 fifo
= apiserv
->out_sync_fifo
;
784 fd
= apiserv
->fd_sync
;
785 event
= OSPF_APISERVER_SYNC_WRITE
;
787 case MSG_READY_NOTIFY
:
788 case MSG_LSA_UPDATE_NOTIFY
:
789 case MSG_LSA_DELETE_NOTIFY
:
794 fifo
= apiserv
->out_async_fifo
;
795 fd
= apiserv
->fd_async
;
796 event
= OSPF_APISERVER_ASYNC_WRITE
;
799 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
804 /* Make a copy of the message and put in the fifo. Once the fifo
805 gets drained by the write thread, the message will be freed. */
806 /* NB: Given "msg" is untouched in this function. */
807 msg2
= msg_dup (msg
);
809 /* Enqueue message into corresponding fifo queue */
810 msg_fifo_push (fifo
, msg2
);
812 /* Schedule write thread */
813 ospf_apiserver_event (event
, fd
, apiserv
);
818 ospf_apiserver_send_reply (struct ospf_apiserver
*apiserv
, u_int32_t seqnr
,
821 struct msg
*msg
= new_msg_reply (seqnr
, rc
);
826 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
828 /* Cannot allocate new message. What should we do? */
829 ospf_apiserver_free (apiserv
);
834 ret
= ospf_apiserver_send_msg (apiserv
, msg
);
840 /* -----------------------------------------------------------
841 * Generic message dispatching handler function
842 * -----------------------------------------------------------
846 ospf_apiserver_handle_msg (struct ospf_apiserver
*apiserv
, struct msg
*msg
)
850 /* Call corresponding message handler function. */
851 switch (msg
->hdr
.msgtype
)
853 case MSG_REGISTER_OPAQUETYPE
:
854 rc
= ospf_apiserver_handle_register_opaque_type (apiserv
, msg
);
856 case MSG_UNREGISTER_OPAQUETYPE
:
857 rc
= ospf_apiserver_handle_unregister_opaque_type (apiserv
, msg
);
859 case MSG_REGISTER_EVENT
:
860 rc
= ospf_apiserver_handle_register_event (apiserv
, msg
);
863 rc
= ospf_apiserver_handle_sync_lsdb (apiserv
, msg
);
865 case MSG_ORIGINATE_REQUEST
:
866 rc
= ospf_apiserver_handle_originate_request (apiserv
, msg
);
868 case MSG_DELETE_REQUEST
:
869 rc
= ospf_apiserver_handle_delete_request (apiserv
, msg
);
872 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
880 /* -----------------------------------------------------------
881 * Following are functions for opaque type registration
882 * -----------------------------------------------------------
886 ospf_apiserver_register_opaque_type (struct ospf_apiserver
*apiserv
,
887 u_char lsa_type
, u_char opaque_type
)
889 struct registered_opaque_type
*regtype
;
890 int (*originator_func
) (void *arg
);
895 case OSPF_OPAQUE_LINK_LSA
:
896 originator_func
= ospf_apiserver_lsa9_originator
;
898 case OSPF_OPAQUE_AREA_LSA
:
899 originator_func
= ospf_apiserver_lsa10_originator
;
901 case OSPF_OPAQUE_AS_LSA
:
902 originator_func
= ospf_apiserver_lsa11_originator
;
905 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
907 return OSPF_API_ILLEGALLSATYPE
;
911 /* Register opaque function table */
912 /* NB: Duplicated registration will be detected inside the function. */
914 ospf_register_opaque_functab (lsa_type
, opaque_type
,
915 NULL
, /* ospf_apiserver_new_if */
916 NULL
, /* ospf_apiserver_del_if */
917 NULL
, /* ospf_apiserver_ism_change */
918 NULL
, /* ospf_apiserver_nsm_change */
922 ospf_apiserver_show_info
,
924 ospf_apiserver_lsa_refresher
,
925 NULL
, /* ospf_apiserver_lsa_update */
926 NULL
/* ospf_apiserver_lsa_delete */);
930 zlog_warn ("Failed to register opaque type [%d/%d]",
931 lsa_type
, opaque_type
);
932 return OSPF_API_OPAQUETYPEINUSE
;
935 /* Remember the opaque type that application registers so when
936 connection shuts down, we can flush all LSAs of this opaque
940 XCALLOC (MTYPE_OSPF_APISERVER
, sizeof (struct registered_opaque_type
));
941 regtype
->lsa_type
= lsa_type
;
942 regtype
->opaque_type
= opaque_type
;
944 /* Add to list of registered opaque types */
945 listnode_add (apiserv
->opaque_types
, regtype
);
947 if (IS_DEBUG_OSPF_EVENT
)
948 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
949 " apiserv(%p), total#(%d)",
950 lsa_type
, opaque_type
, apiserv
,
951 listcount (apiserv
->opaque_types
));
957 ospf_apiserver_unregister_opaque_type (struct ospf_apiserver
*apiserv
,
958 u_char lsa_type
, u_char opaque_type
)
960 struct listnode
*node
, *nnode
;
961 struct registered_opaque_type
*regtype
;
963 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node
, nnode
, regtype
))
965 /* Check if we really registered this opaque type */
966 if (regtype
->lsa_type
== lsa_type
&&
967 regtype
->opaque_type
== opaque_type
)
970 /* Yes, we registered this opaque type. Flush
971 all existing opaque LSAs of this type */
973 ospf_apiserver_flush_opaque_lsa (apiserv
, lsa_type
, opaque_type
);
974 ospf_delete_opaque_functab (lsa_type
, opaque_type
);
976 /* Remove from list of registered opaque types */
977 listnode_delete (apiserv
->opaque_types
, regtype
);
979 if (IS_DEBUG_OSPF_EVENT
)
980 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
981 " from apiserv(%p), total#(%d)",
982 lsa_type
, opaque_type
, apiserv
,
983 listcount (apiserv
->opaque_types
));
989 /* Opaque type is not registered */
990 zlog_warn ("Failed to unregister opaque type [%d/%d]",
991 lsa_type
, opaque_type
);
992 return OSPF_API_OPAQUETYPENOTREGISTERED
;
997 apiserver_is_opaque_type_registered (struct ospf_apiserver
*apiserv
,
998 u_char lsa_type
, u_char opaque_type
)
1000 struct listnode
*node
, *nnode
;
1001 struct registered_opaque_type
*regtype
;
1003 /* XXX: how many types are there? if few, why not just a bitmap? */
1004 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node
, nnode
, regtype
))
1006 /* Check if we really registered this opaque type */
1007 if (regtype
->lsa_type
== lsa_type
&&
1008 regtype
->opaque_type
== opaque_type
)
1010 /* Yes registered */
1014 /* Not registered */
1019 ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver
*apiserv
,
1022 struct msg_register_opaque_type
*rmsg
;
1027 /* Extract parameters from register opaque type message */
1028 rmsg
= (struct msg_register_opaque_type
*) STREAM_DATA (msg
->s
);
1030 lsa_type
= rmsg
->lsatype
;
1031 opaque_type
= rmsg
->opaquetype
;
1033 rc
= ospf_apiserver_register_opaque_type (apiserv
, lsa_type
, opaque_type
);
1035 /* Send a reply back to client including return code */
1036 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1040 /* Now inform application about opaque types that are ready */
1043 case OSPF_OPAQUE_LINK_LSA
:
1044 ospf_apiserver_notify_ready_type9 (apiserv
);
1046 case OSPF_OPAQUE_AREA_LSA
:
1047 ospf_apiserver_notify_ready_type10 (apiserv
);
1049 case OSPF_OPAQUE_AS_LSA
:
1050 ospf_apiserver_notify_ready_type11 (apiserv
);
1058 /* Notify specific client about all opaque types 9 that are ready. */
1060 ospf_apiserver_notify_ready_type9 (struct ospf_apiserver
*apiserv
)
1062 struct listnode
*node
, *nnode
;
1063 struct listnode
*node2
, *nnode2
;
1065 struct ospf_interface
*oi
;
1066 struct registered_opaque_type
*r
;
1068 ospf
= ospf_lookup ();
1070 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
1072 /* Check if this interface is indeed ready for type 9 */
1073 if (!ospf_apiserver_is_ready_type9 (oi
))
1076 /* Check for registered opaque type 9 types */
1077 /* XXX: loop-de-loop - optimise me */
1078 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
1082 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
)
1085 /* Yes, this opaque type is ready */
1086 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA
,
1088 oi
->address
->u
.prefix4
);
1091 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1093 /* Cannot allocate new message. What should we do? */
1094 ospf_apiserver_free (apiserv
);
1098 ospf_apiserver_send_msg (apiserv
, msg
);
1109 /* Notify specific client about all opaque types 10 that are ready. */
1111 ospf_apiserver_notify_ready_type10 (struct ospf_apiserver
*apiserv
)
1113 struct listnode
*node
, *nnode
;
1114 struct listnode
*node2
, *nnode2
;
1116 struct ospf_area
*area
;
1118 ospf
= ospf_lookup ();
1120 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
1122 struct registered_opaque_type
*r
;
1124 if (!ospf_apiserver_is_ready_type10 (area
))
1129 /* Check for registered opaque type 10 types */
1130 /* XXX: loop in loop - optimise me */
1131 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
1135 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
)
1137 /* Yes, this opaque type is ready */
1139 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA
,
1140 r
->opaque_type
, area
->area_id
);
1143 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1145 /* Cannot allocate new message. What should we do? */
1146 ospf_apiserver_free (apiserv
);
1150 ospf_apiserver_send_msg (apiserv
, msg
);
1160 /* Notify specific client about all opaque types 11 that are ready */
1162 ospf_apiserver_notify_ready_type11 (struct ospf_apiserver
*apiserv
)
1164 struct listnode
*node
, *nnode
;
1166 struct registered_opaque_type
*r
;
1168 ospf
= ospf_lookup ();
1170 /* Can type 11 be originated? */
1171 if (!ospf_apiserver_is_ready_type11 (ospf
))
1174 /* Check for registered opaque type 11 types */
1175 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node
, nnode
, r
))
1178 struct in_addr noarea_id
= { .s_addr
= 0L };
1180 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
)
1182 /* Yes, this opaque type is ready */
1183 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA
,
1184 r
->opaque_type
, noarea_id
);
1188 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1190 /* Cannot allocate new message. What should we do? */
1191 ospf_apiserver_free (apiserv
);
1195 ospf_apiserver_send_msg (apiserv
, msg
);
1205 ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver
*apiserv
,
1208 struct msg_unregister_opaque_type
*umsg
;
1213 /* Extract parameters from unregister opaque type message */
1214 umsg
= (struct msg_unregister_opaque_type
*) STREAM_DATA (msg
->s
);
1216 ltype
= umsg
->lsatype
;
1217 otype
= umsg
->opaquetype
;
1219 rc
= ospf_apiserver_unregister_opaque_type (apiserv
, ltype
, otype
);
1221 /* Send a reply back to client including return code */
1222 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1228 /* -----------------------------------------------------------
1229 * Following are functions for event (filter) registration.
1230 * -----------------------------------------------------------
1233 ospf_apiserver_handle_register_event (struct ospf_apiserver
*apiserv
,
1236 struct msg_register_event
*rmsg
;
1240 rmsg
= (struct msg_register_event
*) STREAM_DATA (msg
->s
);
1242 /* Get request sequence number */
1243 seqnum
= msg_get_seq (msg
);
1245 /* Free existing filter in apiserv. */
1246 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER
, apiserv
->filter
);
1247 /* Alloc new space for filter. */
1249 apiserv
->filter
= XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER
,
1250 ntohs (msg
->hdr
.msglen
));
1251 if (apiserv
->filter
)
1254 memcpy (apiserv
->filter
, &rmsg
->filter
, ntohs (msg
->hdr
.msglen
));
1259 rc
= OSPF_API_NOMEMORY
;
1261 /* Send a reply back to client with return code */
1262 rc
= ospf_apiserver_send_reply (apiserv
, seqnum
, rc
);
1267 /* -----------------------------------------------------------
1268 * Followings are functions for LSDB synchronization.
1269 * -----------------------------------------------------------
1273 apiserver_sync_callback (struct ospf_lsa
*lsa
, void *p_arg
, int int_arg
)
1275 struct ospf_apiserver
*apiserv
;
1280 struct ospf_apiserver
*apiserv
;
1281 struct lsa_filter_type
*filter
;
1290 param
= (struct param_t
*) p_arg
;
1291 apiserv
= param
->apiserv
;
1292 seqnum
= (u_int32_t
) int_arg
;
1294 /* Check origin in filter. */
1295 if ((param
->filter
->origin
== ANY_ORIGIN
) ||
1296 (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
)))
1299 /* Default area for AS-External and Opaque11 LSAs */
1300 struct in_addr area_id
= { .s_addr
= 0L };
1302 /* Default interface for non Opaque9 LSAs */
1303 struct in_addr ifaddr
= { .s_addr
= 0L };
1307 area_id
= lsa
->area
->area_id
;
1309 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
)
1311 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1314 msg
= new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY
,
1317 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1320 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1322 /* Cannot allocate new message. What should we do? */
1323 /* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1329 ospf_apiserver_send_msg (apiserv
, msg
);
1339 ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver
*apiserv
,
1342 struct listnode
*node
, *nnode
;
1345 struct msg_sync_lsdb
*smsg
;
1346 struct ospf_apiserver_param_t
1348 struct ospf_apiserver
*apiserv
;
1349 struct lsa_filter_type
*filter
;
1352 struct route_node
*rn
;
1353 struct ospf_lsa
*lsa
;
1355 struct ospf_area
*area
;
1357 ospf
= ospf_lookup ();
1359 /* Get request sequence number */
1360 seqnum
= msg_get_seq (msg
);
1362 smsg
= (struct msg_sync_lsdb
*) STREAM_DATA (msg
->s
);
1364 /* Set parameter struct. */
1365 param
.apiserv
= apiserv
;
1366 param
.filter
= &smsg
->filter
;
1368 /* Remember mask. */
1369 mask
= ntohs (smsg
->filter
.typemask
);
1371 /* Iterate over all areas. */
1372 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
1375 u_int32_t
*area_id
= NULL
;
1377 /* Compare area_id with area_ids in sync request. */
1378 if ((i
= smsg
->filter
.num_areas
) > 0)
1380 /* Let area_id point to the list of area IDs,
1381 * which is at the end of smsg->filter. */
1382 area_id
= (u_int32_t
*) (&smsg
->filter
+ 1);
1385 if (*area_id
== area
->area_id
.s_addr
)
1398 /* If area was found, then i>0 here. */
1401 /* Check msg type. */
1402 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1403 LSDB_LOOP (ROUTER_LSDB (area
), rn
, lsa
)
1404 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1405 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1406 LSDB_LOOP (NETWORK_LSDB (area
), rn
, lsa
)
1407 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1408 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1409 LSDB_LOOP (SUMMARY_LSDB (area
), rn
, lsa
)
1410 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1411 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1412 LSDB_LOOP (ASBR_SUMMARY_LSDB (area
), rn
, lsa
)
1413 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1414 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1415 LSDB_LOOP (OPAQUE_LINK_LSDB (area
), rn
, lsa
)
1416 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1417 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1418 LSDB_LOOP (OPAQUE_AREA_LSDB (area
), rn
, lsa
)
1419 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1423 /* For AS-external LSAs */
1426 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1427 LSDB_LOOP (EXTERNAL_LSDB (ospf
), rn
, lsa
)
1428 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1431 /* For AS-external opaque LSAs */
1434 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1435 LSDB_LOOP (OPAQUE_AS_LSDB (ospf
), rn
, lsa
)
1436 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1439 /* Send a reply back to client with return code */
1440 rc
= ospf_apiserver_send_reply (apiserv
, seqnum
, rc
);
1445 /* -----------------------------------------------------------
1446 * Followings are functions to originate or update LSA
1447 * from an application.
1448 * -----------------------------------------------------------
1451 /* Create a new internal opaque LSA by taking prototype and filling in
1452 missing fields such as age, sequence number, advertising router,
1453 checksum and so on. The interface parameter is used for type 9
1454 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1458 ospf_apiserver_opaque_lsa_new (struct ospf_area
*area
,
1459 struct ospf_interface
*oi
,
1460 struct lsa_header
*protolsa
)
1463 struct lsa_header
*newlsa
;
1464 struct ospf_lsa
*new = NULL
;
1465 u_char options
= 0x0;
1470 ospf
= ospf_lookup();
1473 /* Create a stream for internal opaque LSA */
1474 if ((s
= stream_new (OSPF_MAX_LSA_SIZE
)) == NULL
)
1476 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1480 newlsa
= (struct lsa_header
*) STREAM_DATA (s
);
1482 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1483 have to set options? */
1487 options
= LSA_OPTIONS_GET (area
);
1488 options
|= LSA_OPTIONS_NSSA_GET (area
);
1491 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1493 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1495 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1496 protolsa
->type
, inet_ntoa (protolsa
->id
));
1499 /* Set opaque-LSA header fields. */
1500 lsa_header_set (s
, options
, protolsa
->type
, protolsa
->id
,
1503 /* Set opaque-LSA body fields. */
1504 stream_put (s
, ((u_char
*) protolsa
) + sizeof (struct lsa_header
),
1505 ntohs (protolsa
->length
) - sizeof (struct lsa_header
));
1507 /* Determine length of LSA. */
1508 length
= stream_get_endp (s
);
1509 newlsa
->length
= htons (length
);
1511 /* Create OSPF LSA. */
1512 if ((new = ospf_lsa_new ()) == NULL
)
1514 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1519 if ((new->data
= ospf_lsa_data_new (length
)) == NULL
)
1521 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1522 ospf_lsa_unlock (&new);
1530 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
1531 memcpy (new->data
, newlsa
, length
);
1539 ospf_apiserver_is_ready_type9 (struct ospf_interface
*oi
)
1541 /* Type 9 opaque LSA can be originated if there is at least one
1542 active opaque-capable neighbor attached to the outgoing
1545 return (ospf_nbr_count_opaque_capable (oi
) > 0);
1549 ospf_apiserver_is_ready_type10 (struct ospf_area
*area
)
1551 /* Type 10 opaque LSA can be originated if there is at least one
1552 interface belonging to the area that has an active opaque-capable
1554 struct listnode
*node
, *nnode
;
1555 struct ospf_interface
*oi
;
1557 for (ALL_LIST_ELEMENTS (area
->oiflist
, node
, nnode
, oi
))
1558 /* Is there an active neighbor attached to this interface? */
1559 if (ospf_apiserver_is_ready_type9 (oi
))
1562 /* No active neighbor in area */
1567 ospf_apiserver_is_ready_type11 (struct ospf
*ospf
)
1569 /* Type 11 opaque LSA can be originated if there is at least one interface
1570 that has an active opaque-capable neighbor. */
1571 struct listnode
*node
, *nnode
;
1572 struct ospf_interface
*oi
;
1574 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
1575 /* Is there an active neighbor attached to this interface? */
1576 if (ospf_apiserver_is_ready_type9 (oi
))
1579 /* No active neighbor at all */
1585 ospf_apiserver_handle_originate_request (struct ospf_apiserver
*apiserv
,
1588 struct msg_originate_request
*omsg
;
1589 struct lsa_header
*data
;
1590 struct ospf_lsa
*new;
1591 struct ospf_lsa
*old
;
1592 struct ospf_area
*area
= NULL
;
1593 struct ospf_interface
*oi
= NULL
;
1594 struct ospf_lsdb
*lsdb
= NULL
;
1596 int lsa_type
, opaque_type
;
1600 ospf
= ospf_lookup();
1602 /* Extract opaque LSA data from message */
1603 omsg
= (struct msg_originate_request
*) STREAM_DATA (msg
->s
);
1606 /* Determine interface for type9 or area for type10 LSAs. */
1609 case OSPF_OPAQUE_LINK_LSA
:
1610 oi
= ospf_apiserver_if_lookup_by_addr (omsg
->ifaddr
);
1613 zlog_warn ("apiserver_originate: unknown interface %s",
1614 inet_ntoa (omsg
->ifaddr
));
1615 rc
= OSPF_API_NOSUCHINTERFACE
;
1621 case OSPF_OPAQUE_AREA_LSA
:
1622 area
= ospf_area_lookup_by_area_id (ospf
, omsg
->area_id
);
1625 zlog_warn ("apiserver_originate: unknown area %s",
1626 inet_ntoa (omsg
->area_id
));
1627 rc
= OSPF_API_NOSUCHAREA
;
1632 case OSPF_OPAQUE_AS_LSA
:
1636 /* We can only handle opaque types here */
1637 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1639 rc
= OSPF_API_ILLEGALLSATYPE
;
1643 /* Check if we registered this opaque type */
1644 lsa_type
= data
->type
;
1645 opaque_type
= GET_OPAQUE_TYPE (ntohl (data
->id
.s_addr
));
1647 if (!apiserver_is_opaque_type_registered (apiserv
, lsa_type
, opaque_type
))
1649 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type
, opaque_type
);
1650 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1654 /* Make sure that the neighbors are ready before we can originate */
1657 case OSPF_OPAQUE_LINK_LSA
:
1658 ready
= ospf_apiserver_is_ready_type9 (oi
);
1660 case OSPF_OPAQUE_AREA_LSA
:
1661 ready
= ospf_apiserver_is_ready_type10 (area
);
1663 case OSPF_OPAQUE_AS_LSA
:
1664 ready
= ospf_apiserver_is_ready_type11 (ospf
);
1672 zlog_warn ("Neighbors not ready to originate type %d", data
->type
);
1673 rc
= OSPF_API_NOTREADY
;
1677 /* Create OSPF's internal opaque LSA representation */
1678 new = ospf_apiserver_opaque_lsa_new (area
, oi
, data
);
1681 rc
= OSPF_API_NOMEMORY
; /* XXX */
1685 /* Determine if LSA is new or an update for an existing one. */
1686 old
= ospf_lsdb_lookup (lsdb
, new);
1690 /* New LSA install in LSDB. */
1691 rc
= ospf_apiserver_originate1 (new);
1696 * Keep the new LSA instance in the "waiting place" until the next
1697 * refresh timing. If several LSA update requests for the same LSID
1698 * have issued by peer, the last one takes effect.
1700 new->lsdb
= &apiserv
->reserve
;
1701 ospf_lsdb_add (&apiserv
->reserve
, new);
1703 /* Kick the scheduler function. */
1704 ospf_opaque_lsa_refresh_schedule (old
);
1709 /* Send a reply back to client with return code */
1710 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1715 /* -----------------------------------------------------------
1716 * Flood an LSA within its flooding scope.
1717 * -----------------------------------------------------------
1720 /* XXX We can probably use ospf_flood_through instead of this function
1721 but then we need the neighbor parameter. If we set nbr to
1722 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1725 ospf_apiserver_flood_opaque_lsa (struct ospf_lsa
*lsa
)
1729 switch (lsa
->data
->type
)
1731 case OSPF_OPAQUE_LINK_LSA
:
1732 /* Increment counters? XXX */
1734 /* Flood LSA through local network. */
1735 ospf_flood_through_area (lsa
->area
, NULL
/*nbr */ , lsa
);
1737 case OSPF_OPAQUE_AREA_LSA
:
1738 /* Update LSA origination count. */
1740 lsa
->area
->ospf
->lsa_originate_count
++;
1742 /* Flood LSA through area. */
1743 ospf_flood_through_area (lsa
->area
, NULL
/*nbr */ , lsa
);
1745 case OSPF_OPAQUE_AS_LSA
:
1749 ospf
= ospf_lookup();
1752 /* Increment counters? XXX */
1754 /* Flood LSA through AS. */
1755 ospf_flood_through_as (ospf
, NULL
/*nbr */ , lsa
);
1762 ospf_apiserver_originate1 (struct ospf_lsa
*lsa
)
1766 ospf
= ospf_lookup();
1769 /* Install this LSA into LSDB. */
1770 if (ospf_lsa_install (ospf
, lsa
->oi
, lsa
) == NULL
)
1772 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1776 /* Flood LSA within scope */
1780 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1781 * parameter, and thus it does not cause SIGSEGV error.
1783 ospf_flood_through (NULL
/*nbr */ , lsa
);
1786 ospf_apiserver_flood_opaque_lsa (lsa
);
1793 /* Opaque LSAs of type 9 on a specific interface can now be
1794 originated. Tell clients that registered type 9. */
1796 ospf_apiserver_lsa9_originator (void *arg
)
1798 struct ospf_interface
*oi
;
1800 oi
= (struct ospf_interface
*) arg
;
1801 if (listcount (apiserver_list
) > 0) {
1802 ospf_apiserver_clients_notify_ready_type9 (oi
);
1808 ospf_apiserver_lsa10_originator (void *arg
)
1810 struct ospf_area
*area
;
1812 area
= (struct ospf_area
*) arg
;
1813 if (listcount (apiserver_list
) > 0) {
1814 ospf_apiserver_clients_notify_ready_type10 (area
);
1820 ospf_apiserver_lsa11_originator (void *arg
)
1824 ospf
= (struct ospf
*) arg
;
1825 if (listcount (apiserver_list
) > 0) {
1826 ospf_apiserver_clients_notify_ready_type11 (ospf
);
1832 /* Periodically refresh opaque LSAs so that they do not expire in
1835 ospf_apiserver_lsa_refresher (struct ospf_lsa
*lsa
)
1837 struct ospf_apiserver
*apiserv
;
1838 struct ospf_lsa
*new = NULL
;
1841 ospf
= ospf_lookup();
1844 apiserv
= lookup_apiserver_by_lsa (lsa
);
1847 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa
));
1848 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1851 if (IS_LSA_MAXAGE (lsa
))
1853 ospf_opaque_lsa_flush_schedule (lsa
);
1857 /* Check if updated version of LSA instance has already prepared. */
1858 new = ospf_lsdb_lookup (&apiserv
->reserve
, lsa
);
1861 /* This is a periodic refresh, driven by core OSPF mechanism. */
1862 new = ospf_apiserver_opaque_lsa_new (lsa
->area
, lsa
->oi
, lsa
->data
);
1865 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1871 /* This is a forcible refresh, requested by OSPF-API client. */
1872 ospf_lsdb_delete (&apiserv
->reserve
, new);
1876 /* Increment sequence number */
1877 new->data
->ls_seqnum
= lsa_seqnum_increment (lsa
);
1879 /* New LSA is in same area. */
1880 new->area
= lsa
->area
;
1881 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
1883 /* Install LSA into LSDB. */
1884 if (ospf_lsa_install (ospf
, new->oi
, new) == NULL
)
1886 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1887 ospf_lsa_unlock (&new);
1891 /* Flood updated LSA through interface, area or AS */
1894 ospf_flood_through (NULL
/*nbr */ , new);
1896 ospf_apiserver_flood_opaque_lsa (new);
1898 /* Debug logging. */
1899 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1901 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
1902 new->data
->type
, inet_ntoa (new->data
->id
));
1903 ospf_lsa_header_dump (new->data
);
1911 /* -----------------------------------------------------------
1912 * Followings are functions to delete LSAs
1913 * -----------------------------------------------------------
1917 ospf_apiserver_handle_delete_request (struct ospf_apiserver
*apiserv
,
1920 struct msg_delete_request
*dmsg
;
1921 struct ospf_lsa
*old
;
1922 struct ospf_area
*area
= NULL
;
1924 int lsa_type
, opaque_type
;
1928 ospf
= ospf_lookup();
1931 /* Extract opaque LSA from message */
1932 dmsg
= (struct msg_delete_request
*) STREAM_DATA (msg
->s
);
1934 /* Lookup area for link-local and area-local opaque LSAs */
1935 switch (dmsg
->lsa_type
)
1937 case OSPF_OPAQUE_LINK_LSA
:
1938 case OSPF_OPAQUE_AREA_LSA
:
1939 area
= ospf_area_lookup_by_area_id (ospf
, dmsg
->area_id
);
1942 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1943 inet_ntoa (dmsg
->area_id
));
1944 rc
= OSPF_API_NOSUCHAREA
;
1948 case OSPF_OPAQUE_AS_LSA
:
1949 /* AS-external opaque LSAs have no designated area */
1954 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1956 rc
= OSPF_API_ILLEGALLSATYPE
;
1960 /* Check if we registered this opaque type */
1961 lsa_type
= dmsg
->lsa_type
;
1962 opaque_type
= dmsg
->opaque_type
;
1964 if (!apiserver_is_opaque_type_registered (apiserv
, lsa_type
, opaque_type
))
1966 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type
, opaque_type
);
1967 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1971 /* opaque_id is in network byte order */
1972 id
.s_addr
= htonl (SET_OPAQUE_LSID (dmsg
->opaque_type
,
1973 ntohl (dmsg
->opaque_id
)));
1976 * Even if the target LSA has once scheduled to flush, it remains in
1977 * the LSDB until it is finally handled by the maxage remover thread.
1978 * Therefore, the lookup function below may return non-NULL result.
1980 old
= ospf_lsa_lookup (area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1983 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1984 dmsg
->lsa_type
, inet_ntoa (id
));
1985 rc
= OSPF_API_NOSUCHLSA
;
1989 /* Schedule flushing of LSA from LSDB */
1990 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1991 ospf_opaque_lsa_flush_schedule (old
);
1995 /* Send reply back to client including return code */
1996 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
2000 /* Flush self-originated opaque LSA */
2002 apiserver_flush_opaque_type_callback (struct ospf_lsa
*lsa
,
2003 void *p_arg
, int int_arg
)
2007 struct ospf_apiserver
*apiserv
;
2016 param
= (struct param_t
*) p_arg
;
2018 /* If LSA matches type and opaque type then delete it */
2019 if (IS_LSA_SELF (lsa
) && lsa
->data
->type
== param
->lsa_type
2020 && GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)) == param
->opaque_type
)
2022 ospf_opaque_lsa_flush_schedule (lsa
);
2027 /* Delete self-originated opaque LSAs of a given opaque type. This
2028 function is called when an application unregisters a given opaque
2029 type or a connection to an application closes and all those opaque
2030 LSAs need to be flushed the LSDB. */
2032 ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver
*apiserv
,
2033 u_char lsa_type
, u_char opaque_type
)
2037 struct ospf_apiserver
*apiserv
;
2041 struct listnode
*node
, *nnode
;
2043 struct ospf_area
*area
;
2045 ospf
= ospf_lookup();
2048 /* Set parameter struct. */
2049 param
.apiserv
= apiserv
;
2050 param
.lsa_type
= lsa_type
;
2051 param
.opaque_type
= opaque_type
;
2055 struct route_node
*rn
;
2056 struct ospf_lsa
*lsa
;
2058 case OSPF_OPAQUE_LINK_LSA
:
2059 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
2060 LSDB_LOOP (OPAQUE_LINK_LSDB (area
), rn
, lsa
)
2061 apiserver_flush_opaque_type_callback(lsa
, (void *) ¶m
, 0);
2063 case OSPF_OPAQUE_AREA_LSA
:
2064 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
2065 LSDB_LOOP (OPAQUE_AREA_LSDB (area
), rn
, lsa
)
2066 apiserver_flush_opaque_type_callback(lsa
, (void *) ¶m
, 0);
2068 case OSPF_OPAQUE_AS_LSA
:
2069 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf
), rn
, lsa
)
2070 apiserver_flush_opaque_type_callback(lsa
, (void *) ¶m
, 0);
2079 /* -----------------------------------------------------------
2080 * Followings are callback functions to handle opaque types
2081 * -----------------------------------------------------------
2085 ospf_apiserver_new_if (struct interface
*ifp
)
2087 struct ospf_interface
*oi
;
2089 /* For some strange reason it seems possible that we are invoked
2090 with an interface that has no name. This seems to happen during
2091 initialization. Return if this happens */
2093 if (ifp
->name
[0] == '\0') {
2094 /* interface has empty name */
2095 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2099 /* zlog_warn for debugging */
2100 zlog_warn ("ospf_apiserver_new_if");
2101 zlog_warn ("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2104 if (ifp
->name
[0] == '\0') {
2105 /* interface has empty name */
2106 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2110 oi
= ospf_apiserver_if_lookup_by_ifp (ifp
);
2113 /* This interface is known to Zebra but not to OSPF daemon yet. */
2114 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2121 /* New interface added to OSPF, tell clients about it */
2122 if (listcount (apiserver_list
) > 0) {
2123 ospf_apiserver_clients_notify_new_if (oi
);
2129 ospf_apiserver_del_if (struct interface
*ifp
)
2131 struct ospf_interface
*oi
;
2133 /* zlog_warn for debugging */
2134 zlog_warn ("ospf_apiserver_del_if");
2135 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp
->name
, ifp
->status
,
2138 oi
= ospf_apiserver_if_lookup_by_ifp (ifp
);
2141 /* This interface is known to Zebra but not to OSPF daemon
2142 anymore. No need to tell clients about it */
2146 /* Interface deleted, tell clients about it */
2147 if (listcount (apiserver_list
) > 0) {
2148 ospf_apiserver_clients_notify_del_if (oi
);
2154 ospf_apiserver_ism_change (struct ospf_interface
*oi
, int old_state
)
2156 /* Tell clients about interface change */
2158 /* zlog_warn for debugging */
2159 zlog_warn ("ospf_apiserver_ism_change");
2160 if (listcount (apiserver_list
) > 0) {
2161 ospf_apiserver_clients_notify_ism_change (oi
);
2164 zlog_warn ("oi->ifp->name=%s", oi
->ifp
->name
);
2165 zlog_warn ("old_state=%d", old_state
);
2166 zlog_warn ("oi->state=%d", oi
->state
);
2170 ospf_apiserver_nsm_change (struct ospf_neighbor
*nbr
, int old_status
)
2172 /* Neighbor status changed, tell clients about it */
2173 zlog_warn ("ospf_apiserver_nsm_change");
2174 if (listcount (apiserver_list
) > 0) {
2175 ospf_apiserver_clients_notify_nsm_change (nbr
);
2180 ospf_apiserver_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
)
2184 struct lsa_header header
;
2185 u_char data
[1]; /* opaque data have variable length. This is start
2188 struct opaque_lsa
*olsa
;
2191 olsa
= (struct opaque_lsa
*) lsa
->data
;
2193 if (VALID_OPAQUE_INFO_LEN (lsa
->data
))
2194 opaquelen
= ntohs (lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2198 /* Output information about opaque LSAs */
2202 vty_out (vty
, " Added using OSPF API: %u octets of opaque data %s%s",
2204 VALID_OPAQUE_INFO_LEN (lsa
->data
) ? "" : "(Invalid length?)",
2206 vty_out (vty
, " Opaque data: ");
2208 for (i
= 0; i
< opaquelen
; i
++)
2210 vty_out (vty
, "0x%x ", olsa
->data
[i
]);
2212 vty_out (vty
, "%s", VTY_NEWLINE
);
2217 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
2219 VALID_OPAQUE_INFO_LEN (lsa
->
2220 data
) ? "" : "(Invalid length?)");
2221 zlog_debug (" Opaque data: ");
2223 for (i
= 0; i
< opaquelen
; i
++)
2225 zlog_debug ("0x%x ", olsa
->data
[i
]);
2232 /* -----------------------------------------------------------
2233 * Followings are functions to notify clients about events
2234 * -----------------------------------------------------------
2237 /* Send a message to all clients. This is useful for messages
2238 that need to be notified to all clients (such as interface
2242 ospf_apiserver_clients_notify_all (struct msg
*msg
)
2244 struct listnode
*node
, *nnode
;
2245 struct ospf_apiserver
*apiserv
;
2247 /* Send message to all clients */
2248 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2249 ospf_apiserver_send_msg (apiserv
, msg
);
2252 /* An interface is now ready to accept opaque LSAs. Notify all
2253 clients that registered to use this opaque type */
2255 ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface
*oi
)
2257 struct listnode
*node
, *nnode
;
2259 struct ospf_apiserver
*apiserv
;
2264 zlog_warn ("Interface has no address?");
2268 if (!ospf_apiserver_is_ready_type9 (oi
))
2270 zlog_warn ("Interface not ready for type 9?");
2274 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2276 struct listnode
*node2
, *nnode2
;
2277 struct registered_opaque_type
*r
;
2279 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
2281 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
)
2283 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA
,
2285 oi
->address
->u
.prefix4
);
2289 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2291 /* Cannot allocate new message. What should we do? */
2292 ospf_apiserver_free (apiserv
);
2297 ospf_apiserver_send_msg (apiserv
, msg
);
2308 ospf_apiserver_clients_notify_ready_type10 (struct ospf_area
*area
)
2310 struct listnode
*node
, *nnode
;
2312 struct ospf_apiserver
*apiserv
;
2316 if (!ospf_apiserver_is_ready_type10 (area
))
2318 zlog_warn ("Area not ready for type 10?");
2322 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2324 struct listnode
*node2
, *nnode2
;
2325 struct registered_opaque_type
*r
;
2327 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
2329 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
)
2331 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA
,
2332 r
->opaque_type
, area
->area_id
);
2336 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2338 /* Cannot allocate new message. What should we do? */
2339 ospf_apiserver_free (apiserv
);
2344 ospf_apiserver_send_msg (apiserv
, msg
);
2356 ospf_apiserver_clients_notify_ready_type11 (struct ospf
*top
)
2358 struct listnode
*node
, *nnode
;
2360 struct in_addr id_null
= { .s_addr
= 0L };
2361 struct ospf_apiserver
*apiserv
;
2365 if (!ospf_apiserver_is_ready_type11 (top
))
2367 zlog_warn ("AS not ready for type 11?");
2371 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2373 struct listnode
*node2
, *nnode2
;
2374 struct registered_opaque_type
*r
;
2376 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
2378 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
)
2380 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA
,
2381 r
->opaque_type
, id_null
);
2385 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2387 /* Cannot allocate new message. What should we do? */
2388 ospf_apiserver_free (apiserv
);
2393 ospf_apiserver_send_msg (apiserv
, msg
);
2404 ospf_apiserver_clients_notify_new_if (struct ospf_interface
*oi
)
2408 msg
= new_msg_new_if (0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2411 ospf_apiserver_clients_notify_all (msg
);
2417 ospf_apiserver_clients_notify_del_if (struct ospf_interface
*oi
)
2421 msg
= new_msg_del_if (0, oi
->address
->u
.prefix4
);
2424 ospf_apiserver_clients_notify_all (msg
);
2430 ospf_apiserver_clients_notify_ism_change (struct ospf_interface
*oi
)
2433 struct in_addr ifaddr
= { .s_addr
= 0L };
2434 struct in_addr area_id
= { .s_addr
= 0L };
2441 ifaddr
= oi
->address
->u
.prefix4
;
2445 area_id
= oi
->area
->area_id
;
2448 msg
= new_msg_ism_change (0, ifaddr
, area_id
, oi
->state
);
2451 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2455 ospf_apiserver_clients_notify_all (msg
);
2460 ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor
*nbr
)
2463 struct in_addr ifaddr
= { .s_addr
= 0L };
2464 struct in_addr nbraddr
= { .s_addr
= 0L };
2470 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2473 nbraddr
= nbr
->address
.u
.prefix4
;
2475 msg
= new_msg_nsm_change (0, ifaddr
, nbraddr
, nbr
->router_id
, nbr
->state
);
2478 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2482 ospf_apiserver_clients_notify_all (msg
);
2487 apiserver_clients_lsa_change_notify (u_char msgtype
, struct ospf_lsa
*lsa
)
2490 struct listnode
*node
, *nnode
;
2491 struct ospf_apiserver
*apiserv
;
2493 /* Default area for AS-External and Opaque11 LSAs */
2494 struct in_addr area_id
= { .s_addr
= 0L };
2496 /* Default interface for non Opaque9 LSAs */
2497 struct in_addr ifaddr
= { .s_addr
= 0L };
2501 area_id
= lsa
->area
->area_id
;
2503 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
)
2506 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2509 /* Prepare message that can be sent to clients that have a matching
2511 msg
= new_msg_lsa_change_notify (msgtype
, 0L, /* no sequence number */
2513 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2516 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2520 /* Now send message to all clients with a matching filter */
2521 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2523 struct lsa_filter_type
*filter
;
2528 /* Check filter for this client. */
2529 filter
= apiserv
->filter
;
2531 /* Check area IDs in case of non AS-E LSAs.
2532 * If filter has areas (num_areas > 0),
2533 * then one of the areas must match the area ID of this LSA. */
2535 i
= filter
->num_areas
;
2536 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
) ||
2537 (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
))
2544 area
= (u_int32_t
*) (filter
+ 1);
2547 if (*area
== area_id
.s_addr
)
2562 /* Area match. Check LSA type. */
2563 mask
= ntohs (filter
->typemask
);
2565 if (mask
& Power2
[lsa
->data
->type
])
2567 /* Type also matches. Check origin. */
2568 if ((filter
->origin
== ANY_ORIGIN
) ||
2569 (filter
->origin
== IS_LSA_SELF (lsa
)))
2571 ospf_apiserver_send_msg (apiserv
, msg
);
2576 /* Free message since it is not used anymore */
2581 /* -------------------------------------------------------------
2582 * Followings are hooks invoked when LSAs are updated or deleted
2583 * -------------------------------------------------------------
2588 apiserver_notify_clients_lsa (u_char msgtype
, struct ospf_lsa
*lsa
)
2591 /* default area for AS-External and Opaque11 LSAs */
2592 struct in_addr area_id
= { .s_addr
= 0L };
2594 /* default interface for non Opaque9 LSAs */
2595 struct in_addr ifaddr
= { .s_addr
= 0L };
2597 /* Only notify this update if the LSA's age is smaller than
2598 MAXAGE. Otherwise clients would see LSA updates with max age just
2599 before they are deleted from the LSDB. LSA delete messages have
2600 MAXAGE too but should not be filtered. */
2601 if (IS_LSA_MAXAGE(lsa
) && (msgtype
== MSG_LSA_UPDATE_NOTIFY
)) {
2607 area_id
= lsa
->area
->area_id
;
2609 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
)
2611 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2613 msg
= new_msg_lsa_change_notify (msgtype
, 0L, /* no sequence number */
2615 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2618 zlog_warn ("notify_clients_lsa: msg_new failed");
2621 /* Notify all clients that new LSA is added/updated */
2622 apiserver_clients_lsa_change_notify (msgtype
, lsa
);
2624 /* Clients made their own copies of msg so we can free msg here */
2631 ospf_apiserver_lsa_update (struct ospf_lsa
*lsa
)
2633 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY
, lsa
);
2637 ospf_apiserver_lsa_delete (struct ospf_lsa
*lsa
)
2639 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY
, lsa
);
2642 #endif /* SUPPORT_OSPF_API */