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 along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #ifdef SUPPORT_OSPF_API
37 #include "sockunion.h" /* for inet_aton() */
40 #include <sys/types.h>
42 #include "ospfd/ospfd.h" /* for "struct thread_master" */
43 #include "ospfd/ospf_interface.h"
44 #include "ospfd/ospf_ism.h"
45 #include "ospfd/ospf_asbr.h"
46 #include "ospfd/ospf_lsa.h"
47 #include "ospfd/ospf_lsdb.h"
48 #include "ospfd/ospf_neighbor.h"
49 #include "ospfd/ospf_nsm.h"
50 #include "ospfd/ospf_flood.h"
51 #include "ospfd/ospf_packet.h"
52 #include "ospfd/ospf_spf.h"
53 #include "ospfd/ospf_dump.h"
54 #include "ospfd/ospf_route.h"
55 #include "ospfd/ospf_ase.h"
56 #include "ospfd/ospf_zebra.h"
58 #include "ospfd/ospf_api.h"
59 #include "ospfd/ospf_apiserver.h"
61 /* This is an implementation of an API to the OSPF daemon that allows
62 * external applications to access the OSPF daemon through socket
63 * connections. The application can use this API to inject its own
64 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
65 * daemons then receive these LSAs and inform applications through the
66 * API by sending a corresponding message. The application can also
67 * register to receive all LSA types (in addition to opaque types) and
68 * use this information to reconstruct the OSPF's LSDB. The OSPF
69 * daemon supports multiple applications concurrently. */
71 /* List of all active connections. */
72 struct list
*apiserver_list
;
74 /* -----------------------------------------------------------
75 * Functions to lookup interfaces
76 * -----------------------------------------------------------
79 struct ospf_interface
*ospf_apiserver_if_lookup_by_addr(struct in_addr address
)
81 struct listnode
*node
, *nnode
;
82 struct ospf_interface
*oi
;
83 struct ospf
*ospf
= NULL
;
85 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
89 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
90 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
91 if (IPV4_ADDR_SAME(&address
, &oi
->address
->u
.prefix4
))
97 struct ospf_interface
*ospf_apiserver_if_lookup_by_ifp(struct interface
*ifp
)
99 struct listnode
*node
, *nnode
;
100 struct ospf_interface
*oi
;
101 struct ospf
*ospf
= NULL
;
103 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
107 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
114 /* -----------------------------------------------------------
116 * -----------------------------------------------------------
119 unsigned short ospf_apiserver_getport(void)
121 struct servent
*sp
= getservbyname("ospfapi", "tcp");
123 return sp
? ntohs(sp
->s_port
) : OSPF_API_SYNC_PORT
;
126 /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
127 int ospf_apiserver_init(void)
132 /* Create new socket for synchronous messages. */
133 fd
= ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET
);
138 /* Schedule new thread that handles accepted connections. */
139 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, fd
, NULL
);
141 /* Initialize list that keeps track of all connections. */
142 apiserver_list
= list_new();
144 /* Register opaque-independent call back functions. These functions
145 are invoked on ISM, NSM changes and LSA update and LSA deletes */
146 rc
= ospf_register_opaque_functab(
147 0 /* all LSAs */, 0 /* all opaque types */,
148 ospf_apiserver_new_if
, ospf_apiserver_del_if
,
149 ospf_apiserver_ism_change
, ospf_apiserver_nsm_change
, NULL
,
150 NULL
, NULL
, NULL
, /* ospf_apiserver_show_info */
151 NULL
, /* originator_func */
152 NULL
, /* ospf_apiserver_lsa_refresher */
153 ospf_apiserver_lsa_update
, ospf_apiserver_lsa_delete
);
156 "ospf_apiserver_init: Failed to register opaque type [0/0]");
165 /* Terminate OSPF API module. */
166 void ospf_apiserver_term(void)
168 struct ospf_apiserver
*apiserv
;
170 /* Unregister wildcard [0/0] type */
171 ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */);
174 * Free all client instances. ospf_apiserver_free removes the node
175 * from the list, so we examine the head of the list anew each time.
177 while (apiserver_list
178 && (apiserv
= listgetdata(listhead(apiserver_list
))) != NULL
)
179 ospf_apiserver_free(apiserv
);
181 /* Free client list itself */
183 list_delete_and_null(&apiserver_list
);
185 /* Free wildcard list */
189 static struct ospf_apiserver
*lookup_apiserver(uint8_t lsa_type
,
192 struct listnode
*n1
, *n2
;
193 struct registered_opaque_type
*r
;
194 struct ospf_apiserver
*apiserv
, *found
= NULL
;
196 /* XXX: this approaches O(n**2) */
197 for (ALL_LIST_ELEMENTS_RO(apiserver_list
, n1
, apiserv
)) {
198 for (ALL_LIST_ELEMENTS_RO(apiserv
->opaque_types
, n2
, r
))
199 if (r
->lsa_type
== lsa_type
200 && r
->opaque_type
== opaque_type
) {
209 static struct ospf_apiserver
*lookup_apiserver_by_lsa(struct ospf_lsa
*lsa
)
211 struct lsa_header
*lsah
= lsa
->data
;
212 struct ospf_apiserver
*found
= NULL
;
214 if (IS_OPAQUE_LSA(lsah
->type
)) {
215 found
= lookup_apiserver(
216 lsah
->type
, GET_OPAQUE_TYPE(ntohl(lsah
->id
.s_addr
)));
221 /* -----------------------------------------------------------
222 * Followings are functions to manage client connections.
223 * -----------------------------------------------------------
225 static int ospf_apiserver_new_lsa_hook(struct ospf_lsa
*lsa
)
227 if (IS_DEBUG_OSPF_EVENT
)
228 zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
229 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
233 static int ospf_apiserver_del_lsa_hook(struct ospf_lsa
*lsa
)
235 if (IS_DEBUG_OSPF_EVENT
)
236 zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
237 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
241 /* Allocate new connection structure. */
242 struct ospf_apiserver
*ospf_apiserver_new(int fd_sync
, int fd_async
)
244 struct ospf_apiserver
*new =
245 XMALLOC(MTYPE_OSPF_APISERVER
, sizeof(struct ospf_apiserver
));
247 new->filter
= XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER
,
248 sizeof(struct lsa_filter_type
));
250 new->fd_sync
= fd_sync
;
251 new->fd_async
= fd_async
;
253 /* list of registered opaque types that application uses */
254 new->opaque_types
= list_new();
256 /* Initialize temporary strage for LSA instances to be refreshed. */
257 memset(&new->reserve
, 0, sizeof(struct ospf_lsdb
));
258 ospf_lsdb_init(&new->reserve
);
260 new->reserve
.new_lsa_hook
= ospf_apiserver_new_lsa_hook
; /* debug */
261 new->reserve
.del_lsa_hook
= ospf_apiserver_del_lsa_hook
; /* debug */
263 new->out_sync_fifo
= msg_fifo_new();
264 new->out_async_fifo
= msg_fifo_new();
265 new->t_sync_read
= NULL
;
266 #ifdef USE_ASYNC_READ
267 new->t_async_read
= NULL
;
268 #endif /* USE_ASYNC_READ */
269 new->t_sync_write
= NULL
;
270 new->t_async_write
= NULL
;
272 new->filter
->typemask
= 0; /* filter all LSAs */
273 new->filter
->origin
= ANY_ORIGIN
;
274 new->filter
->num_areas
= 0;
279 void ospf_apiserver_event(enum event event
, int fd
,
280 struct ospf_apiserver
*apiserv
)
283 case OSPF_APISERVER_ACCEPT
:
284 (void)thread_add_read(master
, ospf_apiserver_accept
, apiserv
,
287 case OSPF_APISERVER_SYNC_READ
:
288 apiserv
->t_sync_read
= NULL
;
289 thread_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
290 &apiserv
->t_sync_read
);
292 #ifdef USE_ASYNC_READ
293 case OSPF_APISERVER_ASYNC_READ
:
294 apiserv
->t_async_read
= NULL
;
295 thread_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
296 &apiserv
->t_async_read
);
298 #endif /* USE_ASYNC_READ */
299 case OSPF_APISERVER_SYNC_WRITE
:
300 thread_add_write(master
, ospf_apiserver_sync_write
, apiserv
, fd
,
301 &apiserv
->t_sync_write
);
303 case OSPF_APISERVER_ASYNC_WRITE
:
304 thread_add_write(master
, ospf_apiserver_async_write
, apiserv
,
305 fd
, &apiserv
->t_async_write
);
310 /* Free instance. First unregister all opaque types used by
311 application, flush opaque LSAs injected by application
312 from network and close connection. */
313 void ospf_apiserver_free(struct ospf_apiserver
*apiserv
)
315 struct listnode
*node
;
317 /* Cancel read and write threads. */
318 if (apiserv
->t_sync_read
) {
319 thread_cancel(apiserv
->t_sync_read
);
321 #ifdef USE_ASYNC_READ
322 if (apiserv
->t_async_read
) {
323 thread_cancel(apiserv
->t_async_read
);
325 #endif /* USE_ASYNC_READ */
326 if (apiserv
->t_sync_write
) {
327 thread_cancel(apiserv
->t_sync_write
);
330 if (apiserv
->t_async_write
) {
331 thread_cancel(apiserv
->t_async_write
);
334 /* Unregister all opaque types that application registered
335 and flush opaque LSAs if still in LSDB. */
337 while ((node
= listhead(apiserv
->opaque_types
)) != NULL
) {
338 struct registered_opaque_type
*regtype
= listgetdata(node
);
340 ospf_apiserver_unregister_opaque_type(
341 apiserv
, regtype
->lsa_type
, regtype
->opaque_type
);
344 /* Close connections to OSPFd. */
345 if (apiserv
->fd_sync
> 0) {
346 close(apiserv
->fd_sync
);
349 if (apiserv
->fd_async
> 0) {
350 close(apiserv
->fd_async
);
354 msg_fifo_free(apiserv
->out_sync_fifo
);
355 msg_fifo_free(apiserv
->out_async_fifo
);
357 /* Clear temporary strage for LSA instances to be refreshed. */
358 ospf_lsdb_delete_all(&apiserv
->reserve
);
359 ospf_lsdb_cleanup(&apiserv
->reserve
);
361 /* Remove from the list of active clients. */
362 listnode_delete(apiserver_list
, apiserv
);
364 if (IS_DEBUG_OSPF_EVENT
)
365 zlog_debug("API: Delete apiserv(%p), total#(%d)",
366 (void *)apiserv
, apiserver_list
->count
);
368 /* And free instance. */
369 XFREE(MTYPE_OSPF_APISERVER
, apiserv
);
372 int ospf_apiserver_read(struct thread
*thread
)
374 struct ospf_apiserver
*apiserv
;
380 apiserv
= THREAD_ARG(thread
);
381 fd
= THREAD_FD(thread
);
383 if (fd
== apiserv
->fd_sync
) {
384 event
= OSPF_APISERVER_SYNC_READ
;
385 apiserv
->t_sync_read
= NULL
;
387 if (IS_DEBUG_OSPF_EVENT
)
388 zlog_debug("API: ospf_apiserver_read: Peer: %s/%u",
389 inet_ntoa(apiserv
->peer_sync
.sin_addr
),
390 ntohs(apiserv
->peer_sync
.sin_port
));
392 #ifdef USE_ASYNC_READ
393 else if (fd
== apiserv
->fd_async
) {
394 event
= OSPF_APISERVER_ASYNC_READ
;
395 apiserv
->t_async_read
= NULL
;
397 if (IS_DEBUG_OSPF_EVENT
)
398 zlog_debug("API: ospf_apiserver_read: Peer: %s/%u",
399 inet_ntoa(apiserv
->peer_async
.sin_addr
),
400 ntohs(apiserv
->peer_async
.sin_port
));
402 #endif /* USE_ASYNC_READ */
404 zlog_warn("ospf_apiserver_read: Unknown fd(%d)", fd
);
405 ospf_apiserver_free(apiserv
);
409 /* Read message from fd. */
413 "ospf_apiserver_read: read failed on fd=%d, closing connection",
416 /* Perform cleanup. */
417 ospf_apiserver_free(apiserv
);
421 if (IS_DEBUG_OSPF_EVENT
)
424 /* Dispatch to corresponding message handler. */
425 rc
= ospf_apiserver_handle_msg(apiserv
, msg
);
427 /* Prepare for next message, add read thread. */
428 ospf_apiserver_event(event
, fd
, apiserv
);
436 int ospf_apiserver_sync_write(struct thread
*thread
)
438 struct ospf_apiserver
*apiserv
;
443 apiserv
= THREAD_ARG(thread
);
445 fd
= THREAD_FD(thread
);
447 apiserv
->t_sync_write
= NULL
;
450 if (fd
!= apiserv
->fd_sync
) {
451 zlog_warn("ospf_apiserver_sync_write: Unknown fd=%d", fd
);
455 if (IS_DEBUG_OSPF_EVENT
)
456 zlog_debug("API: ospf_apiserver_sync_write: Peer: %s/%u",
457 inet_ntoa(apiserv
->peer_sync
.sin_addr
),
458 ntohs(apiserv
->peer_sync
.sin_port
));
460 /* Check whether there is really a message in the fifo. */
461 msg
= msg_fifo_pop(apiserv
->out_sync_fifo
);
464 "API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
468 if (IS_DEBUG_OSPF_EVENT
)
471 rc
= msg_write(fd
, msg
);
473 /* Once a message is dequeued, it should be freed anyway. */
477 zlog_warn("ospf_apiserver_sync_write: write failed on fd=%d",
483 /* If more messages are in sync message fifo, schedule write thread. */
484 if (msg_fifo_head(apiserv
->out_sync_fifo
)) {
485 ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE
,
486 apiserv
->fd_sync
, apiserv
);
492 /* Perform cleanup and disconnect with peer */
493 ospf_apiserver_free(apiserv
);
500 int ospf_apiserver_async_write(struct thread
*thread
)
502 struct ospf_apiserver
*apiserv
;
507 apiserv
= THREAD_ARG(thread
);
509 fd
= THREAD_FD(thread
);
511 apiserv
->t_async_write
= NULL
;
514 if (fd
!= apiserv
->fd_async
) {
515 zlog_warn("ospf_apiserver_async_write: Unknown fd=%d", fd
);
519 if (IS_DEBUG_OSPF_EVENT
)
520 zlog_debug("API: ospf_apiserver_async_write: Peer: %s/%u",
521 inet_ntoa(apiserv
->peer_async
.sin_addr
),
522 ntohs(apiserv
->peer_async
.sin_port
));
524 /* Check whether there is really a message in the fifo. */
525 msg
= msg_fifo_pop(apiserv
->out_async_fifo
);
528 "API: ospf_apiserver_async_write: No message in Async-FIFO?");
532 if (IS_DEBUG_OSPF_EVENT
)
535 rc
= msg_write(fd
, msg
);
537 /* Once a message is dequeued, it should be freed anyway. */
541 zlog_warn("ospf_apiserver_async_write: write failed on fd=%d",
547 /* If more messages are in async message fifo, schedule write thread. */
548 if (msg_fifo_head(apiserv
->out_async_fifo
)) {
549 ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE
,
550 apiserv
->fd_async
, apiserv
);
556 /* Perform cleanup and disconnect with peer */
557 ospf_apiserver_free(apiserv
);
564 int ospf_apiserver_serv_sock_family(unsigned short port
, int family
)
570 memset(&su
, 0, sizeof(union sockunion
));
571 su
.sa
.sa_family
= family
;
573 /* Make new socket */
574 accept_sock
= sockunion_stream_socket(&su
);
578 /* This is a server, so reuse address and port */
579 sockopt_reuseaddr(accept_sock
);
580 sockopt_reuseport(accept_sock
);
582 /* Bind socket to address and given port. */
583 rc
= sockunion_bind(accept_sock
, &su
, port
, NULL
);
585 close(accept_sock
); /* Close socket */
589 /* Listen socket under queue length 3. */
590 rc
= listen(accept_sock
, 3);
592 zlog_warn("ospf_apiserver_serv_sock_family: listen: %s",
593 safe_strerror(errno
));
594 close(accept_sock
); /* Close socket */
601 /* Accept connection request from external applications. For each
602 accepted connection allocate own connection instance. */
603 int ospf_apiserver_accept(struct thread
*thread
)
609 struct ospf_apiserver
*apiserv
;
610 struct sockaddr_in peer_async
;
611 struct sockaddr_in peer_sync
;
612 unsigned int peerlen
;
615 /* THREAD_ARG (thread) is NULL */
616 accept_sock
= THREAD_FD(thread
);
618 /* Keep hearing on socket for further connections. */
619 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
621 memset(&su
, 0, sizeof(union sockunion
));
622 /* Accept connection for synchronous messages */
623 new_sync_sock
= sockunion_accept(accept_sock
, &su
);
624 if (new_sync_sock
< 0) {
625 zlog_warn("ospf_apiserver_accept: accept: %s",
626 safe_strerror(errno
));
630 /* Get port address and port number of peer to make reverse connection.
631 The reverse channel uses the port number of the peer port+1. */
633 memset(&peer_sync
, 0, sizeof(struct sockaddr_in
));
634 peerlen
= sizeof(struct sockaddr_in
);
636 ret
= getpeername(new_sync_sock
, (struct sockaddr
*)&peer_sync
,
639 zlog_warn("ospf_apiserver_accept: getpeername: %s",
640 safe_strerror(errno
));
641 close(new_sync_sock
);
645 if (IS_DEBUG_OSPF_EVENT
)
646 zlog_debug("API: ospf_apiserver_accept: New peer: %s/%u",
647 inet_ntoa(peer_sync
.sin_addr
),
648 ntohs(peer_sync
.sin_port
));
650 /* Create new socket for asynchronous messages. */
651 peer_async
= peer_sync
;
652 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
654 /* Check if remote port number to make reverse connection is valid one.
656 if (ntohs(peer_async
.sin_port
) == ospf_apiserver_getport()) {
658 "API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
659 inet_ntoa(peer_async
.sin_addr
),
660 ntohs(peer_async
.sin_port
));
661 close(new_sync_sock
);
665 new_async_sock
= socket(AF_INET
, SOCK_STREAM
, 0);
666 if (new_async_sock
< 0) {
667 zlog_warn("ospf_apiserver_accept: socket: %s",
668 safe_strerror(errno
));
669 close(new_sync_sock
);
673 ret
= connect(new_async_sock
, (struct sockaddr
*)&peer_async
,
674 sizeof(struct sockaddr_in
));
677 zlog_warn("ospf_apiserver_accept: connect: %s",
678 safe_strerror(errno
));
679 close(new_sync_sock
);
680 close(new_async_sock
);
684 #ifdef USE_ASYNC_READ
685 #else /* USE_ASYNC_READ */
686 /* Make the asynchronous channel write-only. */
687 ret
= shutdown(new_async_sock
, SHUT_RD
);
689 zlog_warn("ospf_apiserver_accept: shutdown: %s",
690 safe_strerror(errno
));
691 close(new_sync_sock
);
692 close(new_async_sock
);
695 #endif /* USE_ASYNC_READ */
697 /* Allocate new server-side connection structure */
698 apiserv
= ospf_apiserver_new(new_sync_sock
, new_async_sock
);
700 /* Add to active connection list */
701 listnode_add(apiserver_list
, apiserv
);
702 apiserv
->peer_sync
= peer_sync
;
703 apiserv
->peer_async
= peer_async
;
705 /* And add read threads for new connection */
706 ospf_apiserver_event(OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
707 #ifdef USE_ASYNC_READ
708 ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ
, new_async_sock
,
710 #endif /* USE_ASYNC_READ */
712 if (IS_DEBUG_OSPF_EVENT
)
713 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv
,
714 apiserver_list
->count
);
720 /* -----------------------------------------------------------
721 * Send reply with return code to client application
722 * -----------------------------------------------------------
725 static int ospf_apiserver_send_msg(struct ospf_apiserver
*apiserv
,
728 struct msg_fifo
*fifo
;
733 switch (msg
->hdr
.msgtype
) {
735 fifo
= apiserv
->out_sync_fifo
;
736 fd
= apiserv
->fd_sync
;
737 event
= OSPF_APISERVER_SYNC_WRITE
;
739 case MSG_READY_NOTIFY
:
740 case MSG_LSA_UPDATE_NOTIFY
:
741 case MSG_LSA_DELETE_NOTIFY
:
746 fifo
= apiserv
->out_async_fifo
;
747 fd
= apiserv
->fd_async
;
748 event
= OSPF_APISERVER_ASYNC_WRITE
;
751 zlog_warn("ospf_apiserver_send_msg: Unknown message type %d",
756 /* Make a copy of the message and put in the fifo. Once the fifo
757 gets drained by the write thread, the message will be freed. */
758 /* NB: Given "msg" is untouched in this function. */
761 /* Enqueue message into corresponding fifo queue */
762 msg_fifo_push(fifo
, msg2
);
764 /* Schedule write thread */
765 ospf_apiserver_event(event
, fd
, apiserv
);
769 int ospf_apiserver_send_reply(struct ospf_apiserver
*apiserv
, uint32_t seqnr
,
772 struct msg
*msg
= new_msg_reply(seqnr
, rc
);
776 zlog_warn("ospf_apiserver_send_reply: msg_new failed");
778 /* Cannot allocate new message. What should we do? */
779 ospf_apiserver_free(apiserv
);
784 ret
= ospf_apiserver_send_msg(apiserv
, msg
);
790 /* -----------------------------------------------------------
791 * Generic message dispatching handler function
792 * -----------------------------------------------------------
795 int ospf_apiserver_handle_msg(struct ospf_apiserver
*apiserv
, struct msg
*msg
)
799 /* Call corresponding message handler function. */
800 switch (msg
->hdr
.msgtype
) {
801 case MSG_REGISTER_OPAQUETYPE
:
802 rc
= ospf_apiserver_handle_register_opaque_type(apiserv
, msg
);
804 case MSG_UNREGISTER_OPAQUETYPE
:
805 rc
= ospf_apiserver_handle_unregister_opaque_type(apiserv
, msg
);
807 case MSG_REGISTER_EVENT
:
808 rc
= ospf_apiserver_handle_register_event(apiserv
, msg
);
811 rc
= ospf_apiserver_handle_sync_lsdb(apiserv
, msg
);
813 case MSG_ORIGINATE_REQUEST
:
814 rc
= ospf_apiserver_handle_originate_request(apiserv
, msg
);
816 case MSG_DELETE_REQUEST
:
817 rc
= ospf_apiserver_handle_delete_request(apiserv
, msg
);
820 zlog_warn("ospf_apiserver_handle_msg: Unknown message type: %d",
828 /* -----------------------------------------------------------
829 * Following are functions for opaque type registration
830 * -----------------------------------------------------------
833 int ospf_apiserver_register_opaque_type(struct ospf_apiserver
*apiserv
,
834 uint8_t lsa_type
, uint8_t opaque_type
)
836 struct registered_opaque_type
*regtype
;
837 int (*originator_func
)(void *arg
);
841 case OSPF_OPAQUE_LINK_LSA
:
842 originator_func
= ospf_apiserver_lsa9_originator
;
844 case OSPF_OPAQUE_AREA_LSA
:
845 originator_func
= ospf_apiserver_lsa10_originator
;
847 case OSPF_OPAQUE_AS_LSA
:
848 originator_func
= ospf_apiserver_lsa11_originator
;
851 zlog_warn("ospf_apiserver_register_opaque_type: lsa_type(%d)",
853 return OSPF_API_ILLEGALLSATYPE
;
857 /* Register opaque function table */
858 /* NB: Duplicated registration will be detected inside the function. */
859 rc
= ospf_register_opaque_functab(
860 lsa_type
, opaque_type
, NULL
, /* ospf_apiserver_new_if */
861 NULL
, /* ospf_apiserver_del_if */
862 NULL
, /* ospf_apiserver_ism_change */
863 NULL
, /* ospf_apiserver_nsm_change */
864 NULL
, NULL
, NULL
, ospf_apiserver_show_info
, originator_func
,
865 ospf_apiserver_lsa_refresher
,
866 NULL
, /* ospf_apiserver_lsa_update */
867 NULL
/* ospf_apiserver_lsa_delete */);
870 zlog_warn("Failed to register opaque type [%d/%d]", lsa_type
,
872 return OSPF_API_OPAQUETYPEINUSE
;
875 /* Remember the opaque type that application registers so when
876 connection shuts down, we can flush all LSAs of this opaque
879 regtype
= XCALLOC(MTYPE_OSPF_APISERVER
,
880 sizeof(struct registered_opaque_type
));
881 regtype
->lsa_type
= lsa_type
;
882 regtype
->opaque_type
= opaque_type
;
884 /* Add to list of registered opaque types */
885 listnode_add(apiserv
->opaque_types
, regtype
);
887 if (IS_DEBUG_OSPF_EVENT
)
889 "API: Add LSA-type(%d)/Opaque-type(%d) into"
890 " apiserv(%p), total#(%d)",
891 lsa_type
, opaque_type
, (void *)apiserv
,
892 listcount(apiserv
->opaque_types
));
897 int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
898 uint8_t lsa_type
, uint8_t opaque_type
)
900 struct listnode
*node
, *nnode
;
901 struct registered_opaque_type
*regtype
;
903 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
904 /* Check if we really registered this opaque type */
905 if (regtype
->lsa_type
== lsa_type
906 && regtype
->opaque_type
== opaque_type
) {
908 /* Yes, we registered this opaque type. Flush
909 all existing opaque LSAs of this type */
911 ospf_apiserver_flush_opaque_lsa(apiserv
, lsa_type
,
913 ospf_delete_opaque_functab(lsa_type
, opaque_type
);
915 /* Remove from list of registered opaque types */
916 listnode_delete(apiserv
->opaque_types
, regtype
);
918 if (IS_DEBUG_OSPF_EVENT
)
920 "API: Del LSA-type(%d)/Opaque-type(%d)"
921 " from apiserv(%p), total#(%d)",
922 lsa_type
, opaque_type
, (void *)apiserv
,
923 listcount(apiserv
->opaque_types
));
929 /* Opaque type is not registered */
930 zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type
,
932 return OSPF_API_OPAQUETYPENOTREGISTERED
;
936 static int apiserver_is_opaque_type_registered(struct ospf_apiserver
*apiserv
,
940 struct listnode
*node
, *nnode
;
941 struct registered_opaque_type
*regtype
;
943 /* XXX: how many types are there? if few, why not just a bitmap? */
944 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
945 /* Check if we really registered this opaque type */
946 if (regtype
->lsa_type
== lsa_type
947 && regtype
->opaque_type
== opaque_type
) {
956 int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver
*apiserv
,
959 struct msg_register_opaque_type
*rmsg
;
964 /* Extract parameters from register opaque type message */
965 rmsg
= (struct msg_register_opaque_type
*)STREAM_DATA(msg
->s
);
967 lsa_type
= rmsg
->lsatype
;
968 opaque_type
= rmsg
->opaquetype
;
970 rc
= ospf_apiserver_register_opaque_type(apiserv
, lsa_type
,
973 /* Send a reply back to client including return code */
974 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
978 /* Now inform application about opaque types that are ready */
980 case OSPF_OPAQUE_LINK_LSA
:
981 ospf_apiserver_notify_ready_type9(apiserv
);
983 case OSPF_OPAQUE_AREA_LSA
:
984 ospf_apiserver_notify_ready_type10(apiserv
);
986 case OSPF_OPAQUE_AS_LSA
:
987 ospf_apiserver_notify_ready_type11(apiserv
);
995 /* Notify specific client about all opaque types 9 that are ready. */
996 void ospf_apiserver_notify_ready_type9(struct ospf_apiserver
*apiserv
)
998 struct listnode
*node
, *nnode
;
999 struct listnode
*node2
, *nnode2
;
1001 struct ospf_interface
*oi
;
1002 struct registered_opaque_type
*r
;
1004 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1006 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
)) {
1007 /* Check if this interface is indeed ready for type 9 */
1008 if (!ospf_apiserver_is_ready_type9(oi
))
1011 /* Check for registered opaque type 9 types */
1012 /* XXX: loop-de-loop - optimise me */
1013 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
1017 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
1019 /* Yes, this opaque type is ready */
1020 msg
= new_msg_ready_notify(
1021 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
1022 oi
->address
->u
.prefix4
);
1025 "apiserver_notify_ready_type9: msg_new failed");
1027 /* Cannot allocate new message. What
1029 ospf_apiserver_free(apiserv
);
1033 ospf_apiserver_send_msg(apiserv
, msg
);
1044 /* Notify specific client about all opaque types 10 that are ready. */
1045 void ospf_apiserver_notify_ready_type10(struct ospf_apiserver
*apiserv
)
1047 struct listnode
*node
, *nnode
;
1048 struct listnode
*node2
, *nnode2
;
1050 struct ospf_area
*area
;
1052 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1054 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1055 struct registered_opaque_type
*r
;
1057 if (!ospf_apiserver_is_ready_type10(area
)) {
1061 /* Check for registered opaque type 10 types */
1062 /* XXX: loop in loop - optimise me */
1063 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
1067 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
1068 /* Yes, this opaque type is ready */
1069 msg
= new_msg_ready_notify(
1070 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
1074 "apiserver_notify_ready_type10: msg_new failed");
1076 /* Cannot allocate new message. What
1078 ospf_apiserver_free(apiserv
);
1082 ospf_apiserver_send_msg(apiserv
, msg
);
1092 /* Notify specific client about all opaque types 11 that are ready */
1093 void ospf_apiserver_notify_ready_type11(struct ospf_apiserver
*apiserv
)
1095 struct listnode
*node
, *nnode
;
1097 struct registered_opaque_type
*r
;
1099 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1101 /* Can type 11 be originated? */
1102 if (!ospf_apiserver_is_ready_type11(ospf
))
1105 /* Check for registered opaque type 11 types */
1106 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, r
)) {
1108 struct in_addr noarea_id
= {.s_addr
= 0L};
1110 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
1111 /* Yes, this opaque type is ready */
1112 msg
= new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA
,
1113 r
->opaque_type
, noarea_id
);
1117 "apiserver_notify_ready_type11: msg_new failed");
1119 /* Cannot allocate new message. What should we
1121 ospf_apiserver_free(apiserv
);
1125 ospf_apiserver_send_msg(apiserv
, msg
);
1134 int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
1137 struct msg_unregister_opaque_type
*umsg
;
1142 /* Extract parameters from unregister opaque type message */
1143 umsg
= (struct msg_unregister_opaque_type
*)STREAM_DATA(msg
->s
);
1145 ltype
= umsg
->lsatype
;
1146 otype
= umsg
->opaquetype
;
1148 rc
= ospf_apiserver_unregister_opaque_type(apiserv
, ltype
, otype
);
1150 /* Send a reply back to client including return code */
1151 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1157 /* -----------------------------------------------------------
1158 * Following are functions for event (filter) registration.
1159 * -----------------------------------------------------------
1161 int ospf_apiserver_handle_register_event(struct ospf_apiserver
*apiserv
,
1164 struct msg_register_event
*rmsg
;
1168 rmsg
= (struct msg_register_event
*)STREAM_DATA(msg
->s
);
1170 /* Get request sequence number */
1171 seqnum
= msg_get_seq(msg
);
1173 /* Free existing filter in apiserv. */
1174 XFREE(MTYPE_OSPF_APISERVER_MSGFILTER
, apiserv
->filter
);
1175 /* Alloc new space for filter. */
1178 XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER
, ntohs(msg
->hdr
.msglen
));
1179 if (apiserv
->filter
) {
1181 memcpy(apiserv
->filter
, &rmsg
->filter
, ntohs(msg
->hdr
.msglen
));
1184 rc
= OSPF_API_NOMEMORY
;
1186 /* Send a reply back to client with return code */
1187 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1192 /* -----------------------------------------------------------
1193 * Followings are functions for LSDB synchronization.
1194 * -----------------------------------------------------------
1197 static int apiserver_sync_callback(struct ospf_lsa
*lsa
, void *p_arg
,
1200 struct ospf_apiserver
*apiserv
;
1204 struct ospf_apiserver
*apiserv
;
1205 struct lsa_filter_type
*filter
;
1213 param
= (struct param_t
*)p_arg
;
1214 apiserv
= param
->apiserv
;
1215 seqnum
= (uint32_t)int_arg
;
1217 /* Check origin in filter. */
1218 if ((param
->filter
->origin
== ANY_ORIGIN
)
1219 || (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
))) {
1221 /* Default area for AS-External and Opaque11 LSAs */
1222 struct in_addr area_id
= {.s_addr
= 0L};
1224 /* Default interface for non Opaque9 LSAs */
1225 struct in_addr ifaddr
= {.s_addr
= 0L};
1228 area_id
= lsa
->area
->area_id
;
1230 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
1231 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1234 msg
= new_msg_lsa_change_notify(
1235 MSG_LSA_UPDATE_NOTIFY
, seqnum
, ifaddr
, area_id
,
1236 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1239 "apiserver_sync_callback: new_msg_update failed");
1241 /* Cannot allocate new message. What should we do? */
1242 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1250 ospf_apiserver_send_msg(apiserv
, msg
);
1259 int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver
*apiserv
,
1262 struct listnode
*node
, *nnode
;
1265 struct msg_sync_lsdb
*smsg
;
1266 struct ospf_apiserver_param_t
{
1267 struct ospf_apiserver
*apiserv
;
1268 struct lsa_filter_type
*filter
;
1271 struct route_node
*rn
;
1272 struct ospf_lsa
*lsa
;
1274 struct ospf_area
*area
;
1276 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1278 /* Get request sequence number */
1279 seqnum
= msg_get_seq(msg
);
1281 smsg
= (struct msg_sync_lsdb
*)STREAM_DATA(msg
->s
);
1283 /* Set parameter struct. */
1284 param
.apiserv
= apiserv
;
1285 param
.filter
= &smsg
->filter
;
1287 /* Remember mask. */
1288 mask
= ntohs(smsg
->filter
.typemask
);
1290 /* Iterate over all areas. */
1291 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1293 uint32_t *area_id
= NULL
;
1295 /* Compare area_id with area_ids in sync request. */
1296 if ((i
= smsg
->filter
.num_areas
) > 0) {
1297 /* Let area_id point to the list of area IDs,
1298 * which is at the end of smsg->filter. */
1299 area_id
= (uint32_t *)(&smsg
->filter
+ 1);
1301 if (*area_id
== area
->area_id
.s_addr
) {
1311 /* If area was found, then i>0 here. */
1313 /* Check msg type. */
1314 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1315 LSDB_LOOP (ROUTER_LSDB(area
), rn
, lsa
)
1316 apiserver_sync_callback(
1317 lsa
, (void *)¶m
, seqnum
);
1318 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1319 LSDB_LOOP (NETWORK_LSDB(area
), rn
, lsa
)
1320 apiserver_sync_callback(
1321 lsa
, (void *)¶m
, seqnum
);
1322 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1323 LSDB_LOOP (SUMMARY_LSDB(area
), rn
, lsa
)
1324 apiserver_sync_callback(
1325 lsa
, (void *)¶m
, seqnum
);
1326 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1327 LSDB_LOOP (ASBR_SUMMARY_LSDB(area
), rn
, lsa
)
1328 apiserver_sync_callback(
1329 lsa
, (void *)¶m
, seqnum
);
1330 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1331 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1332 apiserver_sync_callback(
1333 lsa
, (void *)¶m
, seqnum
);
1334 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1335 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1336 apiserver_sync_callback(
1337 lsa
, (void *)¶m
, seqnum
);
1341 /* For AS-external LSAs */
1343 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1344 LSDB_LOOP (EXTERNAL_LSDB(ospf
), rn
, lsa
)
1345 apiserver_sync_callback(lsa
, (void *)¶m
,
1349 /* For AS-external opaque LSAs */
1351 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1352 LSDB_LOOP (OPAQUE_AS_LSDB(ospf
), rn
, lsa
)
1353 apiserver_sync_callback(lsa
, (void *)¶m
,
1357 /* Send a reply back to client with return code */
1358 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1363 /* -----------------------------------------------------------
1364 * Followings are functions to originate or update LSA
1365 * from an application.
1366 * -----------------------------------------------------------
1369 /* Create a new internal opaque LSA by taking prototype and filling in
1370 missing fields such as age, sequence number, advertising router,
1371 checksum and so on. The interface parameter is used for type 9
1372 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1375 struct ospf_lsa
*ospf_apiserver_opaque_lsa_new(struct ospf_area
*area
,
1376 struct ospf_interface
*oi
,
1377 struct lsa_header
*protolsa
)
1380 struct lsa_header
*newlsa
;
1381 struct ospf_lsa
*new = NULL
;
1382 uint8_t options
= 0x0;
1390 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1394 /* Create a stream for internal opaque LSA */
1395 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
1396 zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
1400 newlsa
= (struct lsa_header
*)STREAM_DATA(s
);
1402 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1403 have to set options? */
1406 options
= LSA_OPTIONS_GET(area
);
1407 options
|= LSA_OPTIONS_NSSA_GET(area
);
1410 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1412 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1413 zlog_debug("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1414 protolsa
->type
, inet_ntoa(protolsa
->id
));
1417 /* Set opaque-LSA header fields. */
1418 lsa_header_set(s
, options
, protolsa
->type
, protolsa
->id
,
1421 /* Set opaque-LSA body fields. */
1422 stream_put(s
, ((uint8_t *)protolsa
) + sizeof(struct lsa_header
),
1423 ntohs(protolsa
->length
) - sizeof(struct lsa_header
));
1425 /* Determine length of LSA. */
1426 length
= stream_get_endp(s
);
1427 newlsa
->length
= htons(length
);
1429 /* Create OSPF LSA. */
1430 if ((new = ospf_lsa_new()) == NULL
) {
1431 zlog_warn("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1436 if ((new->data
= ospf_lsa_data_new(length
)) == NULL
) {
1438 "ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1439 ospf_lsa_unlock(&new);
1446 new->vrf_id
= ospf
->vrf_id
;
1448 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1449 memcpy(new->data
, newlsa
, length
);
1456 int ospf_apiserver_is_ready_type9(struct ospf_interface
*oi
)
1458 /* Type 9 opaque LSA can be originated if there is at least one
1459 active opaque-capable neighbor attached to the outgoing
1462 return (ospf_nbr_count_opaque_capable(oi
) > 0);
1465 int ospf_apiserver_is_ready_type10(struct ospf_area
*area
)
1467 /* Type 10 opaque LSA can be originated if there is at least one
1468 interface belonging to the area that has an active opaque-capable
1470 struct listnode
*node
, *nnode
;
1471 struct ospf_interface
*oi
;
1473 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
))
1474 /* Is there an active neighbor attached to this interface? */
1475 if (ospf_apiserver_is_ready_type9(oi
))
1478 /* No active neighbor in area */
1482 int ospf_apiserver_is_ready_type11(struct ospf
*ospf
)
1484 /* Type 11 opaque LSA can be originated if there is at least one
1486 that has an active opaque-capable neighbor. */
1487 struct listnode
*node
, *nnode
;
1488 struct ospf_interface
*oi
;
1490 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
1491 /* Is there an active neighbor attached to this interface? */
1492 if (ospf_apiserver_is_ready_type9(oi
))
1495 /* No active neighbor at all */
1500 int ospf_apiserver_handle_originate_request(struct ospf_apiserver
*apiserv
,
1503 struct msg_originate_request
*omsg
;
1504 struct lsa_header
*data
;
1505 struct ospf_lsa
*new;
1506 struct ospf_lsa
*old
;
1507 struct ospf_area
*area
= NULL
;
1508 struct ospf_interface
*oi
= NULL
;
1509 struct ospf_lsdb
*lsdb
= NULL
;
1511 int lsa_type
, opaque_type
;
1515 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1517 /* Extract opaque LSA data from message */
1518 omsg
= (struct msg_originate_request
*)STREAM_DATA(msg
->s
);
1521 /* Determine interface for type9 or area for type10 LSAs. */
1522 switch (data
->type
) {
1523 case OSPF_OPAQUE_LINK_LSA
:
1524 oi
= ospf_apiserver_if_lookup_by_addr(omsg
->ifaddr
);
1526 zlog_warn("apiserver_originate: unknown interface %s",
1527 inet_ntoa(omsg
->ifaddr
));
1528 rc
= OSPF_API_NOSUCHINTERFACE
;
1534 case OSPF_OPAQUE_AREA_LSA
:
1535 area
= ospf_area_lookup_by_area_id(ospf
, omsg
->area_id
);
1537 zlog_warn("apiserver_originate: unknown area %s",
1538 inet_ntoa(omsg
->area_id
));
1539 rc
= OSPF_API_NOSUCHAREA
;
1544 case OSPF_OPAQUE_AS_LSA
:
1548 /* We can only handle opaque types here */
1550 "apiserver_originate: Cannot originate non-opaque LSA type %d",
1552 rc
= OSPF_API_ILLEGALLSATYPE
;
1556 /* Check if we registered this opaque type */
1557 lsa_type
= data
->type
;
1558 opaque_type
= GET_OPAQUE_TYPE(ntohl(data
->id
.s_addr
));
1560 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1563 "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered",
1564 lsa_type
, opaque_type
);
1565 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1569 /* Make sure that the neighbors are ready before we can originate */
1570 switch (data
->type
) {
1571 case OSPF_OPAQUE_LINK_LSA
:
1572 ready
= ospf_apiserver_is_ready_type9(oi
);
1574 case OSPF_OPAQUE_AREA_LSA
:
1575 ready
= ospf_apiserver_is_ready_type10(area
);
1577 case OSPF_OPAQUE_AS_LSA
:
1578 ready
= ospf_apiserver_is_ready_type11(ospf
);
1585 zlog_warn("Neighbors not ready to originate type %d",
1587 rc
= OSPF_API_NOTREADY
;
1591 /* Create OSPF's internal opaque LSA representation */
1592 new = ospf_apiserver_opaque_lsa_new(area
, oi
, data
);
1594 rc
= OSPF_API_NOMEMORY
; /* XXX */
1598 /* Determine if LSA is new or an update for an existing one. */
1599 old
= ospf_lsdb_lookup(lsdb
, new);
1602 /* New LSA install in LSDB. */
1603 rc
= ospf_apiserver_originate1(new);
1606 * Keep the new LSA instance in the "waiting place" until the
1608 * refresh timing. If several LSA update requests for the same
1610 * have issued by peer, the last one takes effect.
1612 new->lsdb
= &apiserv
->reserve
;
1613 ospf_lsdb_add(&apiserv
->reserve
, new);
1615 /* Kick the scheduler function. */
1616 ospf_opaque_lsa_refresh_schedule(old
);
1621 /* Send a reply back to client with return code */
1622 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1627 /* -----------------------------------------------------------
1628 * Flood an LSA within its flooding scope.
1629 * -----------------------------------------------------------
1632 /* XXX We can probably use ospf_flood_through instead of this function
1633 but then we need the neighbor parameter. If we set nbr to
1634 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1636 void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa
*lsa
)
1640 switch (lsa
->data
->type
) {
1641 case OSPF_OPAQUE_LINK_LSA
:
1642 /* Increment counters? XXX */
1644 /* Flood LSA through local network. */
1645 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1647 case OSPF_OPAQUE_AREA_LSA
:
1648 /* Update LSA origination count. */
1650 lsa
->area
->ospf
->lsa_originate_count
++;
1652 /* Flood LSA through area. */
1653 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1655 case OSPF_OPAQUE_AS_LSA
: {
1658 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1661 /* Increment counters? XXX */
1663 /* Flood LSA through AS. */
1664 ospf_flood_through_as(ospf
, NULL
/*nbr */, lsa
);
1670 int ospf_apiserver_originate1(struct ospf_lsa
*lsa
)
1674 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1677 /* Install this LSA into LSDB. */
1678 if (ospf_lsa_install(ospf
, lsa
->oi
, lsa
) == NULL
) {
1679 zlog_warn("ospf_apiserver_originate1: ospf_lsa_install failed");
1683 /* Flood LSA within scope */
1687 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1688 * parameter, and thus it does not cause SIGSEGV error.
1690 ospf_flood_through(NULL
/*nbr */, lsa
);
1693 ospf_apiserver_flood_opaque_lsa(lsa
);
1700 /* Opaque LSAs of type 9 on a specific interface can now be
1701 originated. Tell clients that registered type 9. */
1702 int ospf_apiserver_lsa9_originator(void *arg
)
1704 struct ospf_interface
*oi
;
1706 oi
= (struct ospf_interface
*)arg
;
1707 if (listcount(apiserver_list
) > 0) {
1708 ospf_apiserver_clients_notify_ready_type9(oi
);
1713 int ospf_apiserver_lsa10_originator(void *arg
)
1715 struct ospf_area
*area
;
1717 area
= (struct ospf_area
*)arg
;
1718 if (listcount(apiserver_list
) > 0) {
1719 ospf_apiserver_clients_notify_ready_type10(area
);
1724 int ospf_apiserver_lsa11_originator(void *arg
)
1728 ospf
= (struct ospf
*)arg
;
1729 if (listcount(apiserver_list
) > 0) {
1730 ospf_apiserver_clients_notify_ready_type11(ospf
);
1736 /* Periodically refresh opaque LSAs so that they do not expire in
1738 struct ospf_lsa
*ospf_apiserver_lsa_refresher(struct ospf_lsa
*lsa
)
1740 struct ospf_apiserver
*apiserv
;
1741 struct ospf_lsa
*new = NULL
;
1744 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1747 apiserv
= lookup_apiserver_by_lsa(lsa
);
1750 "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
1753 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1756 if (IS_LSA_MAXAGE(lsa
)) {
1757 ospf_opaque_lsa_flush_schedule(lsa
);
1761 /* Check if updated version of LSA instance has already prepared. */
1762 new = ospf_lsdb_lookup(&apiserv
->reserve
, lsa
);
1764 /* This is a periodic refresh, driven by core OSPF mechanism. */
1765 new = ospf_apiserver_opaque_lsa_new(lsa
->area
, lsa
->oi
,
1769 "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1773 /* This is a forcible refresh, requested by OSPF-API client. */
1774 ospf_lsdb_delete(&apiserv
->reserve
, new);
1778 /* Increment sequence number */
1779 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1781 /* New LSA is in same area. */
1782 new->area
= lsa
->area
;
1783 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1785 /* Install LSA into LSDB. */
1786 if (ospf_lsa_install(ospf
, new->oi
, new) == NULL
) {
1788 "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1789 ospf_lsa_unlock(&new);
1793 /* Flood updated LSA through interface, area or AS */
1796 ospf_flood_through(NULL
/*nbr */, new);
1798 ospf_apiserver_flood_opaque_lsa(new);
1800 /* Debug logging. */
1801 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1802 zlog_debug("LSA[Type%d:%s]: Refresh Opaque LSA",
1803 new->data
->type
, inet_ntoa(new->data
->id
));
1804 ospf_lsa_header_dump(new->data
);
1812 /* -----------------------------------------------------------
1813 * Followings are functions to delete LSAs
1814 * -----------------------------------------------------------
1817 int ospf_apiserver_handle_delete_request(struct ospf_apiserver
*apiserv
,
1820 struct msg_delete_request
*dmsg
;
1821 struct ospf_lsa
*old
;
1822 struct ospf_area
*area
= NULL
;
1824 int lsa_type
, opaque_type
;
1828 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1831 /* Extract opaque LSA from message */
1832 dmsg
= (struct msg_delete_request
*)STREAM_DATA(msg
->s
);
1834 /* Lookup area for link-local and area-local opaque LSAs */
1835 switch (dmsg
->lsa_type
) {
1836 case OSPF_OPAQUE_LINK_LSA
:
1837 case OSPF_OPAQUE_AREA_LSA
:
1838 area
= ospf_area_lookup_by_area_id(ospf
, dmsg
->area_id
);
1840 zlog_warn("ospf_apiserver_lsa_delete: unknown area %s",
1841 inet_ntoa(dmsg
->area_id
));
1842 rc
= OSPF_API_NOSUCHAREA
;
1846 case OSPF_OPAQUE_AS_LSA
:
1847 /* AS-external opaque LSAs have no designated area */
1852 "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1854 rc
= OSPF_API_ILLEGALLSATYPE
;
1858 /* Check if we registered this opaque type */
1859 lsa_type
= dmsg
->lsa_type
;
1860 opaque_type
= dmsg
->opaque_type
;
1862 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1865 "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
1866 lsa_type
, opaque_type
);
1867 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1871 /* opaque_id is in network byte order */
1873 SET_OPAQUE_LSID(dmsg
->opaque_type
, ntohl(dmsg
->opaque_id
)));
1876 * Even if the target LSA has once scheduled to flush, it remains in
1877 * the LSDB until it is finally handled by the maxage remover thread.
1878 * Therefore, the lookup function below may return non-NULL result.
1880 old
= ospf_lsa_lookup(ospf
, area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1883 "ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1884 dmsg
->lsa_type
, inet_ntoa(id
));
1885 rc
= OSPF_API_NOSUCHLSA
;
1889 /* Schedule flushing of LSA from LSDB */
1890 /* NB: Multiple scheduling will produce a warning message, but harmless.
1892 ospf_opaque_lsa_flush_schedule(old
);
1896 /* Send reply back to client including return code */
1897 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1901 /* Flush self-originated opaque LSA */
1902 static int apiserver_flush_opaque_type_callback(struct ospf_lsa
*lsa
,
1903 void *p_arg
, int int_arg
)
1906 struct ospf_apiserver
*apiserv
;
1908 uint8_t opaque_type
;
1914 param
= (struct param_t
*)p_arg
;
1916 /* If LSA matches type and opaque type then delete it */
1917 if (IS_LSA_SELF(lsa
) && lsa
->data
->type
== param
->lsa_type
1918 && GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1919 == param
->opaque_type
) {
1920 ospf_opaque_lsa_flush_schedule(lsa
);
1925 /* Delete self-originated opaque LSAs of a given opaque type. This
1926 function is called when an application unregisters a given opaque
1927 type or a connection to an application closes and all those opaque
1928 LSAs need to be flushed the LSDB. */
1929 void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver
*apiserv
,
1930 uint8_t lsa_type
, uint8_t opaque_type
)
1933 struct ospf_apiserver
*apiserv
;
1935 uint8_t opaque_type
;
1937 struct listnode
*node
, *nnode
;
1939 struct ospf_area
*area
;
1941 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1944 /* Set parameter struct. */
1945 param
.apiserv
= apiserv
;
1946 param
.lsa_type
= lsa_type
;
1947 param
.opaque_type
= opaque_type
;
1950 struct route_node
*rn
;
1951 struct ospf_lsa
*lsa
;
1953 case OSPF_OPAQUE_LINK_LSA
:
1954 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
1955 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1956 apiserver_flush_opaque_type_callback(
1957 lsa
, (void *)¶m
, 0);
1959 case OSPF_OPAQUE_AREA_LSA
:
1960 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
1961 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1962 apiserver_flush_opaque_type_callback(
1963 lsa
, (void *)¶m
, 0);
1965 case OSPF_OPAQUE_AS_LSA
:
1966 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf
), rn
, lsa
)
1967 apiserver_flush_opaque_type_callback(lsa
,
1977 /* -----------------------------------------------------------
1978 * Followings are callback functions to handle opaque types
1979 * -----------------------------------------------------------
1982 int ospf_apiserver_new_if(struct interface
*ifp
)
1984 struct ospf_interface
*oi
;
1986 /* For some strange reason it seems possible that we are invoked
1987 with an interface that has no name. This seems to happen during
1988 initialization. Return if this happens */
1990 if (ifp
->name
[0] == '\0') {
1991 /* interface has empty name */
1992 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1996 /* zlog_warn for debugging */
1997 zlog_warn("ospf_apiserver_new_if");
1998 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2001 if (ifp
->name
[0] == '\0') {
2002 /* interface has empty name */
2003 zlog_warn("ospf_apiserver_new_if: interface has no name?");
2007 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2010 /* This interface is known to Zebra but not to OSPF daemon yet.
2013 "ospf_apiserver_new_if: interface %s not known to OSPFd?",
2020 /* New interface added to OSPF, tell clients about it */
2021 if (listcount(apiserver_list
) > 0) {
2022 ospf_apiserver_clients_notify_new_if(oi
);
2027 int ospf_apiserver_del_if(struct interface
*ifp
)
2029 struct ospf_interface
*oi
;
2031 /* zlog_warn for debugging */
2032 zlog_warn("ospf_apiserver_del_if");
2033 zlog_warn("ifp name=%s status=%d index=%d\n", ifp
->name
, ifp
->status
,
2036 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2039 /* This interface is known to Zebra but not to OSPF daemon
2040 anymore. No need to tell clients about it */
2044 /* Interface deleted, tell clients about it */
2045 if (listcount(apiserver_list
) > 0) {
2046 ospf_apiserver_clients_notify_del_if(oi
);
2051 void ospf_apiserver_ism_change(struct ospf_interface
*oi
, int old_state
)
2053 /* Tell clients about interface change */
2055 /* zlog_warn for debugging */
2056 zlog_warn("ospf_apiserver_ism_change");
2057 if (listcount(apiserver_list
) > 0) {
2058 ospf_apiserver_clients_notify_ism_change(oi
);
2061 zlog_warn("oi->ifp->name=%s", oi
->ifp
->name
);
2062 zlog_warn("old_state=%d", old_state
);
2063 zlog_warn("oi->state=%d", oi
->state
);
2066 void ospf_apiserver_nsm_change(struct ospf_neighbor
*nbr
, int old_status
)
2068 /* Neighbor status changed, tell clients about it */
2069 zlog_warn("ospf_apiserver_nsm_change");
2070 if (listcount(apiserver_list
) > 0) {
2071 ospf_apiserver_clients_notify_nsm_change(nbr
);
2075 void ospf_apiserver_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
2078 struct lsa_header header
;
2079 uint8_t data
[1]; /* opaque data have variable length. This is
2083 struct opaque_lsa
*olsa
;
2086 olsa
= (struct opaque_lsa
*)lsa
->data
;
2088 if (VALID_OPAQUE_INFO_LEN(lsa
->data
))
2089 opaquelen
= ntohs(lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2093 /* Output information about opaque LSAs */
2097 " Added using OSPF API: %u octets of opaque data %s\n",
2099 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2100 : "(Invalid length?)");
2101 vty_out(vty
, " Opaque data: ");
2103 for (i
= 0; i
< opaquelen
; i
++) {
2104 vty_out(vty
, "0x%x ", olsa
->data
[i
]);
2110 " Added using OSPF API: %u octets of opaque data %s",
2112 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2113 : "(Invalid length?)");
2114 zlog_debug(" Opaque data: ");
2116 for (i
= 0; i
< opaquelen
; i
++) {
2117 zlog_debug("0x%x ", olsa
->data
[i
]);
2124 /* -----------------------------------------------------------
2125 * Followings are functions to notify clients about events
2126 * -----------------------------------------------------------
2129 /* Send a message to all clients. This is useful for messages
2130 that need to be notified to all clients (such as interface
2133 void ospf_apiserver_clients_notify_all(struct msg
*msg
)
2135 struct listnode
*node
, *nnode
;
2136 struct ospf_apiserver
*apiserv
;
2138 /* Send message to all clients */
2139 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
))
2140 ospf_apiserver_send_msg(apiserv
, msg
);
2143 /* An interface is now ready to accept opaque LSAs. Notify all
2144 clients that registered to use this opaque type */
2145 void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface
*oi
)
2147 struct listnode
*node
, *nnode
;
2149 struct ospf_apiserver
*apiserv
;
2153 zlog_warn("Interface has no address?");
2157 if (!ospf_apiserver_is_ready_type9(oi
)) {
2158 zlog_warn("Interface not ready for type 9?");
2162 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2163 struct listnode
*node2
, *nnode2
;
2164 struct registered_opaque_type
*r
;
2166 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2168 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
2169 msg
= new_msg_ready_notify(
2170 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
2171 oi
->address
->u
.prefix4
);
2174 "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2176 /* Cannot allocate new message. What
2178 ospf_apiserver_free(apiserv
);
2183 ospf_apiserver_send_msg(apiserv
, msg
);
2193 void ospf_apiserver_clients_notify_ready_type10(struct ospf_area
*area
)
2195 struct listnode
*node
, *nnode
;
2197 struct ospf_apiserver
*apiserv
;
2201 if (!ospf_apiserver_is_ready_type10(area
)) {
2202 zlog_warn("Area not ready for type 10?");
2206 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2207 struct listnode
*node2
, *nnode2
;
2208 struct registered_opaque_type
*r
;
2210 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2212 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
2213 msg
= new_msg_ready_notify(
2214 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
2218 "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2220 /* Cannot allocate new message. What
2222 ospf_apiserver_free(apiserv
);
2227 ospf_apiserver_send_msg(apiserv
, msg
);
2238 void ospf_apiserver_clients_notify_ready_type11(struct ospf
*top
)
2240 struct listnode
*node
, *nnode
;
2242 struct in_addr id_null
= {.s_addr
= 0L};
2243 struct ospf_apiserver
*apiserv
;
2247 if (!ospf_apiserver_is_ready_type11(top
)) {
2248 zlog_warn("AS not ready for type 11?");
2252 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2253 struct listnode
*node2
, *nnode2
;
2254 struct registered_opaque_type
*r
;
2256 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2258 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
2259 msg
= new_msg_ready_notify(
2260 0, OSPF_OPAQUE_AS_LSA
, r
->opaque_type
,
2264 "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2266 /* Cannot allocate new message. What
2268 ospf_apiserver_free(apiserv
);
2273 ospf_apiserver_send_msg(apiserv
, msg
);
2283 void ospf_apiserver_clients_notify_new_if(struct ospf_interface
*oi
)
2287 msg
= new_msg_new_if(0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2289 ospf_apiserver_clients_notify_all(msg
);
2294 void ospf_apiserver_clients_notify_del_if(struct ospf_interface
*oi
)
2298 msg
= new_msg_del_if(0, oi
->address
->u
.prefix4
);
2300 ospf_apiserver_clients_notify_all(msg
);
2305 void ospf_apiserver_clients_notify_ism_change(struct ospf_interface
*oi
)
2308 struct in_addr ifaddr
= {.s_addr
= 0L};
2309 struct in_addr area_id
= {.s_addr
= 0L};
2315 ifaddr
= oi
->address
->u
.prefix4
;
2318 area_id
= oi
->area
->area_id
;
2321 msg
= new_msg_ism_change(0, ifaddr
, area_id
, oi
->state
);
2324 "apiserver_clients_notify_ism_change: msg_new failed");
2328 ospf_apiserver_clients_notify_all(msg
);
2332 void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor
*nbr
)
2335 struct in_addr ifaddr
= {.s_addr
= 0L};
2336 struct in_addr nbraddr
;
2341 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2344 nbraddr
= nbr
->address
.u
.prefix4
;
2346 msg
= new_msg_nsm_change(0, ifaddr
, nbraddr
, nbr
->router_id
,
2350 "apiserver_clients_notify_nsm_change: msg_new failed");
2354 ospf_apiserver_clients_notify_all(msg
);
2358 static void apiserver_clients_lsa_change_notify(uint8_t msgtype
,
2359 struct ospf_lsa
*lsa
)
2362 struct listnode
*node
, *nnode
;
2363 struct ospf_apiserver
*apiserv
;
2365 /* Default area for AS-External and Opaque11 LSAs */
2366 struct in_addr area_id
= {.s_addr
= 0L};
2368 /* Default interface for non Opaque9 LSAs */
2369 struct in_addr ifaddr
= {.s_addr
= 0L};
2372 area_id
= lsa
->area
->area_id
;
2374 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2376 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2379 /* Prepare message that can be sent to clients that have a matching
2381 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2383 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2386 "apiserver_clients_lsa_change_notify: msg_new failed");
2390 /* Now send message to all clients with a matching filter */
2391 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2392 struct lsa_filter_type
*filter
;
2397 /* Check filter for this client. */
2398 filter
= apiserv
->filter
;
2400 /* Check area IDs in case of non AS-E LSAs.
2401 * If filter has areas (num_areas > 0),
2402 * then one of the areas must match the area ID of this LSA. */
2404 i
= filter
->num_areas
;
2405 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)
2406 || (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
)) {
2411 area
= (uint32_t *)(filter
+ 1);
2413 if (*area
== area_id
.s_addr
) {
2424 /* Area match. Check LSA type. */
2425 mask
= ntohs(filter
->typemask
);
2427 if (mask
& Power2
[lsa
->data
->type
]) {
2428 /* Type also matches. Check origin. */
2429 if ((filter
->origin
== ANY_ORIGIN
)
2430 || (filter
->origin
== IS_LSA_SELF(lsa
))) {
2431 ospf_apiserver_send_msg(apiserv
, msg
);
2436 /* Free message since it is not used anymore */
2441 /* -------------------------------------------------------------
2442 * Followings are hooks invoked when LSAs are updated or deleted
2443 * -------------------------------------------------------------
2447 static int apiserver_notify_clients_lsa(uint8_t msgtype
, struct ospf_lsa
*lsa
)
2450 /* default area for AS-External and Opaque11 LSAs */
2451 struct in_addr area_id
= {.s_addr
= 0L};
2453 /* default interface for non Opaque9 LSAs */
2454 struct in_addr ifaddr
= {.s_addr
= 0L};
2456 /* Only notify this update if the LSA's age is smaller than
2457 MAXAGE. Otherwise clients would see LSA updates with max age just
2458 before they are deleted from the LSDB. LSA delete messages have
2459 MAXAGE too but should not be filtered. */
2460 if (IS_LSA_MAXAGE(lsa
) && (msgtype
== MSG_LSA_UPDATE_NOTIFY
)) {
2465 area_id
= lsa
->area
->area_id
;
2467 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2468 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2470 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2472 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2474 zlog_warn("notify_clients_lsa: msg_new failed");
2477 /* Notify all clients that new LSA is added/updated */
2478 apiserver_clients_lsa_change_notify(msgtype
, lsa
);
2480 /* Clients made their own copies of msg so we can free msg here */
2486 int ospf_apiserver_lsa_update(struct ospf_lsa
*lsa
)
2488 return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY
, lsa
);
2491 int ospf_apiserver_lsa_delete(struct ospf_lsa
*lsa
)
2493 return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY
, lsa
);
2496 #endif /* SUPPORT_OSPF_API */