1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Server side of OSPF API.
4 * Copyright (C) 2001, 2002 Ralph Keller
5 * Copyright (c) 2022, LabN Consulting, L.L.C.
10 #ifdef SUPPORT_OSPF_API
23 #include "sockunion.h" /* for inet_aton() */
26 #include <sys/types.h>
28 #include "ospfd/ospfd.h" /* for "struct event_loop" */
29 #include "ospfd/ospf_interface.h"
30 #include "ospfd/ospf_ism.h"
31 #include "ospfd/ospf_asbr.h"
32 #include "ospfd/ospf_lsa.h"
33 #include "ospfd/ospf_lsdb.h"
34 #include "ospfd/ospf_neighbor.h"
35 #include "ospfd/ospf_nsm.h"
36 #include "ospfd/ospf_flood.h"
37 #include "ospfd/ospf_packet.h"
38 #include "ospfd/ospf_spf.h"
39 #include "ospfd/ospf_dump.h"
40 #include "ospfd/ospf_route.h"
41 #include "ospfd/ospf_ase.h"
42 #include "ospfd/ospf_zebra.h"
43 #include "ospfd/ospf_errors.h"
44 #include "ospfd/ospf_memory.h"
46 #include "ospfd/ospf_api.h"
47 #include "ospfd/ospf_apiserver.h"
49 DEFINE_MTYPE_STATIC(OSPFD
, APISERVER
, "API Server");
50 DEFINE_MTYPE_STATIC(OSPFD
, APISERVER_MSGFILTER
, "API Server Message Filter");
52 /* This is an implementation of an API to the OSPF daemon that allows
53 * external applications to access the OSPF daemon through socket
54 * connections. The application can use this API to inject its own
55 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
56 * daemons then receive these LSAs and inform applications through the
57 * API by sending a corresponding message. The application can also
58 * register to receive all LSA types (in addition to opaque types) and
59 * use this information to reconstruct the OSPF's LSDB. The OSPF
60 * daemon supports multiple applications concurrently. */
62 /* List of all active connections. */
63 struct list
*apiserver_list
;
65 /* -----------------------------------------------------------
66 * Functions to lookup interfaces
67 * -----------------------------------------------------------
70 struct ospf_interface
*ospf_apiserver_if_lookup_by_addr(struct in_addr address
)
72 struct listnode
*node
, *nnode
;
73 struct ospf_interface
*oi
;
74 struct ospf
*ospf
= NULL
;
76 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
80 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
81 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
82 if (IPV4_ADDR_SAME(&address
, &oi
->address
->u
.prefix4
))
88 struct ospf_interface
*ospf_apiserver_if_lookup_by_ifp(struct interface
*ifp
)
90 struct listnode
*node
, *nnode
;
91 struct ospf_interface
*oi
;
92 struct ospf
*ospf
= NULL
;
94 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
98 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
105 /* -----------------------------------------------------------
107 * -----------------------------------------------------------
110 unsigned short ospf_apiserver_getport(void)
112 struct servent
*sp
= getservbyname("ospfapi", "tcp");
114 return sp
? ntohs(sp
->s_port
) : OSPF_API_SYNC_PORT
;
117 /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
118 int ospf_apiserver_init(void)
123 /* Create new socket for synchronous messages. */
124 fd
= ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET
);
129 /* Schedule new thread that handles accepted connections. */
130 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, fd
, NULL
);
132 /* Initialize list that keeps track of all connections. */
133 apiserver_list
= list_new();
135 /* Register opaque-independent call back functions. These functions
136 are invoked on ISM, NSM changes and LSA update and LSA deletes */
137 rc
= ospf_register_opaque_functab(
138 0 /* all LSAs */, 0 /* all opaque types */,
139 ospf_apiserver_new_if
, ospf_apiserver_del_if
,
140 ospf_apiserver_ism_change
, ospf_apiserver_nsm_change
, NULL
,
141 NULL
, NULL
, NULL
, /* ospf_apiserver_show_info */
142 NULL
, /* originator_func */
143 NULL
, /* ospf_apiserver_lsa_refresher */
144 ospf_apiserver_lsa_update
, ospf_apiserver_lsa_delete
);
147 EC_OSPF_OPAQUE_REGISTRATION
,
148 "ospf_apiserver_init: Failed to register opaque type [0/0]");
157 /* Terminate OSPF API module. */
158 void ospf_apiserver_term(void)
160 struct ospf_apiserver
*apiserv
;
162 /* Unregister wildcard [0/0] type */
163 ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */);
166 * Free all client instances. ospf_apiserver_free removes the node
167 * from the list, so we examine the head of the list anew each time.
172 while (listcount(apiserver_list
)) {
173 apiserv
= listgetdata(listhead(apiserver_list
));
175 ospf_apiserver_free(apiserv
);
178 /* Free client list itself */
180 list_delete(&apiserver_list
);
182 /* Free wildcard list */
186 static struct ospf_apiserver
*lookup_apiserver(uint8_t lsa_type
,
189 struct listnode
*n1
, *n2
;
190 struct registered_opaque_type
*r
;
191 struct ospf_apiserver
*apiserv
, *found
= NULL
;
193 /* XXX: this approaches O(n**2) */
194 for (ALL_LIST_ELEMENTS_RO(apiserver_list
, n1
, apiserv
)) {
195 for (ALL_LIST_ELEMENTS_RO(apiserv
->opaque_types
, n2
, r
))
196 if (r
->lsa_type
== lsa_type
197 && r
->opaque_type
== opaque_type
) {
206 static struct ospf_apiserver
*lookup_apiserver_by_lsa(struct ospf_lsa
*lsa
)
208 struct lsa_header
*lsah
= lsa
->data
;
209 struct ospf_apiserver
*found
= NULL
;
211 if (IS_OPAQUE_LSA(lsah
->type
)) {
212 found
= lookup_apiserver(
213 lsah
->type
, GET_OPAQUE_TYPE(ntohl(lsah
->id
.s_addr
)));
218 /* -----------------------------------------------------------
219 * Following are functions to manage client connections.
220 * -----------------------------------------------------------
222 static int ospf_apiserver_new_lsa_hook(struct ospf_lsa
*lsa
)
224 if (IS_DEBUG_OSPF_EVENT
)
225 zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
226 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
230 static int ospf_apiserver_del_lsa_hook(struct ospf_lsa
*lsa
)
232 if (IS_DEBUG_OSPF_EVENT
)
233 zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
234 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
238 /* Allocate new connection structure. */
239 struct ospf_apiserver
*ospf_apiserver_new(int fd_sync
, int fd_async
)
241 struct ospf_apiserver
*new =
242 XMALLOC(MTYPE_APISERVER
, sizeof(struct ospf_apiserver
));
244 new->filter
= XMALLOC(MTYPE_APISERVER_MSGFILTER
,
245 sizeof(struct lsa_filter_type
));
247 new->fd_sync
= fd_sync
;
248 new->fd_async
= fd_async
;
250 /* list of registered opaque types that application uses */
251 new->opaque_types
= list_new();
253 /* Initialize temporary strage for LSA instances to be refreshed. */
254 memset(&new->reserve
, 0, sizeof(struct ospf_lsdb
));
255 ospf_lsdb_init(&new->reserve
);
257 new->reserve
.new_lsa_hook
= ospf_apiserver_new_lsa_hook
; /* debug */
258 new->reserve
.del_lsa_hook
= ospf_apiserver_del_lsa_hook
; /* debug */
260 new->out_sync_fifo
= msg_fifo_new();
261 new->out_async_fifo
= msg_fifo_new();
262 new->t_sync_read
= NULL
;
263 #ifdef USE_ASYNC_READ
264 new->t_async_read
= NULL
;
265 #endif /* USE_ASYNC_READ */
266 new->t_sync_write
= NULL
;
267 new->t_async_write
= NULL
;
269 new->filter
->typemask
= 0; /* filter all LSAs */
270 new->filter
->origin
= ANY_ORIGIN
;
271 new->filter
->num_areas
= 0;
276 void ospf_apiserver_event(enum ospf_apiserver_event event
, int fd
,
277 struct ospf_apiserver
*apiserv
)
280 case OSPF_APISERVER_ACCEPT
:
281 (void)event_add_read(master
, ospf_apiserver_accept
, apiserv
, fd
,
284 case OSPF_APISERVER_SYNC_READ
:
285 apiserv
->t_sync_read
= NULL
;
286 event_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
287 &apiserv
->t_sync_read
);
289 #ifdef USE_ASYNC_READ
290 case OSPF_APISERVER_ASYNC_READ
:
291 apiserv
->t_async_read
= NULL
;
292 event_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
293 &apiserv
->t_async_read
);
295 #endif /* USE_ASYNC_READ */
296 case OSPF_APISERVER_SYNC_WRITE
:
297 event_add_write(master
, ospf_apiserver_sync_write
, apiserv
, fd
,
298 &apiserv
->t_sync_write
);
300 case OSPF_APISERVER_ASYNC_WRITE
:
301 event_add_write(master
, ospf_apiserver_async_write
, apiserv
, fd
,
302 &apiserv
->t_async_write
);
307 /* Free instance. First unregister all opaque types used by
308 application, flush opaque LSAs injected by application
309 from network and close connection. */
310 void ospf_apiserver_free(struct ospf_apiserver
*apiserv
)
312 struct listnode
*node
;
314 /* Cancel read and write threads. */
315 EVENT_OFF(apiserv
->t_sync_read
);
316 #ifdef USE_ASYNC_READ
317 EVENT_OFF(apiserv
->t_async_read
);
318 #endif /* USE_ASYNC_READ */
319 EVENT_OFF(apiserv
->t_sync_write
);
320 EVENT_OFF(apiserv
->t_async_write
);
322 /* Unregister all opaque types that application registered
323 and flush opaque LSAs if still in LSDB. */
325 while ((node
= listhead(apiserv
->opaque_types
)) != NULL
) {
326 struct registered_opaque_type
*regtype
= listgetdata(node
);
328 ospf_apiserver_unregister_opaque_type(
329 apiserv
, regtype
->lsa_type
, regtype
->opaque_type
);
331 list_delete(&apiserv
->opaque_types
);
333 /* Close connections to OSPFd. */
334 if (apiserv
->fd_sync
> 0) {
335 close(apiserv
->fd_sync
);
338 if (apiserv
->fd_async
> 0) {
339 close(apiserv
->fd_async
);
343 msg_fifo_free(apiserv
->out_sync_fifo
);
344 msg_fifo_free(apiserv
->out_async_fifo
);
346 /* Clear temporary strage for LSA instances to be refreshed. */
347 ospf_lsdb_delete_all(&apiserv
->reserve
);
348 ospf_lsdb_cleanup(&apiserv
->reserve
);
350 /* Remove from the list of active clients. */
351 listnode_delete(apiserver_list
, apiserv
);
353 XFREE(MTYPE_APISERVER_MSGFILTER
, apiserv
->filter
);
355 if (IS_DEBUG_OSPF_EVENT
)
356 zlog_debug("API: Delete apiserv(%p), total#(%d)",
357 (void *)apiserv
, apiserver_list
->count
);
359 /* And free instance. */
360 XFREE(MTYPE_APISERVER
, apiserv
);
363 void ospf_apiserver_read(struct event
*thread
)
365 struct ospf_apiserver
*apiserv
;
368 enum ospf_apiserver_event event
;
370 apiserv
= EVENT_ARG(thread
);
371 fd
= EVENT_FD(thread
);
373 if (fd
== apiserv
->fd_sync
) {
374 event
= OSPF_APISERVER_SYNC_READ
;
375 apiserv
->t_sync_read
= NULL
;
377 if (IS_DEBUG_OSPF_EVENT
)
378 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
379 &apiserv
->peer_sync
.sin_addr
,
380 ntohs(apiserv
->peer_sync
.sin_port
));
382 #ifdef USE_ASYNC_READ
383 else if (fd
== apiserv
->fd_async
) {
384 event
= OSPF_APISERVER_ASYNC_READ
;
385 apiserv
->t_async_read
= NULL
;
387 if (IS_DEBUG_OSPF_EVENT
)
388 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
389 &apiserv
->peer_async
.sin_addr
,
390 ntohs(apiserv
->peer_async
.sin_port
));
392 #endif /* USE_ASYNC_READ */
394 zlog_warn("%s: Unknown fd(%d)", __func__
, fd
);
395 ospf_apiserver_free(apiserv
);
399 /* Read message from fd. */
402 zlog_warn("%s: read failed on fd=%d, closing connection",
405 /* Perform cleanup. */
406 ospf_apiserver_free(apiserv
);
410 if (IS_DEBUG_OSPF_EVENT
)
413 /* Dispatch to corresponding message handler. */
414 ospf_apiserver_handle_msg(apiserv
, msg
);
416 /* Prepare for next message, add read thread. */
417 ospf_apiserver_event(event
, fd
, apiserv
);
422 void ospf_apiserver_sync_write(struct event
*thread
)
424 struct ospf_apiserver
*apiserv
;
429 apiserv
= EVENT_ARG(thread
);
431 fd
= EVENT_FD(thread
);
433 apiserv
->t_sync_write
= NULL
;
436 if (fd
!= apiserv
->fd_sync
) {
437 zlog_warn("%s: Unknown fd=%d", __func__
, fd
);
441 if (IS_DEBUG_OSPF_EVENT
)
442 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
443 &apiserv
->peer_sync
.sin_addr
,
444 ntohs(apiserv
->peer_sync
.sin_port
));
446 /* Check whether there is really a message in the fifo. */
447 msg
= msg_fifo_pop(apiserv
->out_sync_fifo
);
449 zlog_warn("API: %s: No message in Sync-FIFO?", __func__
);
453 if (IS_DEBUG_OSPF_EVENT
)
456 rc
= msg_write(fd
, msg
);
458 /* Once a message is dequeued, it should be freed anyway. */
462 zlog_warn("%s: write failed on fd=%d", __func__
, fd
);
467 /* If more messages are in sync message fifo, schedule write thread. */
468 if (msg_fifo_head(apiserv
->out_sync_fifo
)) {
469 ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE
,
470 apiserv
->fd_sync
, apiserv
);
476 /* Perform cleanup and disconnect with peer */
477 ospf_apiserver_free(apiserv
);
482 void ospf_apiserver_async_write(struct event
*thread
)
484 struct ospf_apiserver
*apiserv
;
489 apiserv
= EVENT_ARG(thread
);
491 fd
= EVENT_FD(thread
);
493 apiserv
->t_async_write
= NULL
;
496 if (fd
!= apiserv
->fd_async
) {
497 zlog_warn("%s: Unknown fd=%d", __func__
, fd
);
501 if (IS_DEBUG_OSPF_EVENT
)
502 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
503 &apiserv
->peer_async
.sin_addr
,
504 ntohs(apiserv
->peer_async
.sin_port
));
506 /* Check whether there is really a message in the fifo. */
507 msg
= msg_fifo_pop(apiserv
->out_async_fifo
);
509 zlog_warn("API: %s: No message in Async-FIFO?", __func__
);
513 if (IS_DEBUG_OSPF_EVENT
)
516 rc
= msg_write(fd
, msg
);
518 /* Once a message is dequeued, it should be freed anyway. */
522 zlog_warn("%s: write failed on fd=%d", __func__
, fd
);
527 /* If more messages are in async message fifo, schedule write thread. */
528 if (msg_fifo_head(apiserv
->out_async_fifo
)) {
529 ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE
,
530 apiserv
->fd_async
, apiserv
);
536 /* Perform cleanup and disconnect with peer */
537 ospf_apiserver_free(apiserv
);
542 int ospf_apiserver_serv_sock_family(unsigned short port
, int family
)
548 memset(&su
, 0, sizeof(union sockunion
));
549 su
.sa
.sa_family
= family
;
551 /* Make new socket */
552 accept_sock
= sockunion_stream_socket(&su
);
556 /* This is a server, so reuse address and port */
557 sockopt_reuseaddr(accept_sock
);
558 sockopt_reuseport(accept_sock
);
560 /* Bind socket to address and given port. */
561 rc
= sockunion_bind(accept_sock
, &su
, port
, NULL
);
563 close(accept_sock
); /* Close socket */
567 /* Listen socket under queue length 3. */
568 rc
= listen(accept_sock
, 3);
570 zlog_warn("%s: listen: %s", __func__
, safe_strerror(errno
));
571 close(accept_sock
); /* Close socket */
578 /* Accept connection request from external applications. For each
579 accepted connection allocate own connection instance. */
580 void ospf_apiserver_accept(struct event
*thread
)
586 struct ospf_apiserver
*apiserv
;
587 struct sockaddr_in peer_async
;
588 struct sockaddr_in peer_sync
;
589 unsigned int peerlen
;
592 /* EVENT_ARG (thread) is NULL */
593 accept_sock
= EVENT_FD(thread
);
595 /* Keep hearing on socket for further connections. */
596 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
598 memset(&su
, 0, sizeof(union sockunion
));
599 /* Accept connection for synchronous messages */
600 new_sync_sock
= sockunion_accept(accept_sock
, &su
);
601 if (new_sync_sock
< 0) {
602 zlog_warn("%s: accept: %s", __func__
, safe_strerror(errno
));
606 /* Get port address and port number of peer to make reverse connection.
607 The reverse channel uses the port number of the peer port+1. */
609 memset(&peer_sync
, 0, sizeof(peer_sync
));
610 peerlen
= sizeof(struct sockaddr_in
);
612 ret
= getpeername(new_sync_sock
, (struct sockaddr
*)&peer_sync
,
615 zlog_warn("%s: getpeername: %s", __func__
,
616 safe_strerror(errno
));
617 close(new_sync_sock
);
621 if (IS_DEBUG_OSPF_EVENT
)
622 zlog_debug("API: %s: New peer: %pI4/%u", __func__
,
623 &peer_sync
.sin_addr
, ntohs(peer_sync
.sin_port
));
625 /* Create new socket for asynchronous messages. */
626 peer_async
= peer_sync
;
627 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
629 /* Check if remote port number to make reverse connection is valid one.
631 if (ntohs(peer_async
.sin_port
) == ospf_apiserver_getport()) {
632 zlog_warn("API: %s: Peer(%pI4/%u): Invalid async port number?",
633 __func__
, &peer_async
.sin_addr
,
634 ntohs(peer_async
.sin_port
));
635 close(new_sync_sock
);
639 new_async_sock
= socket(AF_INET
, SOCK_STREAM
, 0);
640 if (new_async_sock
< 0) {
641 zlog_warn("%s: socket: %s", __func__
, safe_strerror(errno
));
642 close(new_sync_sock
);
646 ret
= connect(new_async_sock
, (struct sockaddr
*)&peer_async
,
647 sizeof(struct sockaddr_in
));
650 zlog_warn("%s: connect: %s", __func__
, safe_strerror(errno
));
651 close(new_sync_sock
);
652 close(new_async_sock
);
656 #ifdef USE_ASYNC_READ
657 #else /* USE_ASYNC_READ */
658 /* Make the asynchronous channel write-only. */
659 ret
= shutdown(new_async_sock
, SHUT_RD
);
661 zlog_warn("%s: shutdown: %s", __func__
, safe_strerror(errno
));
662 close(new_sync_sock
);
663 close(new_async_sock
);
666 #endif /* USE_ASYNC_READ */
668 /* Allocate new server-side connection structure */
669 apiserv
= ospf_apiserver_new(new_sync_sock
, new_async_sock
);
671 /* Add to active connection list */
672 listnode_add(apiserver_list
, apiserv
);
673 apiserv
->peer_sync
= peer_sync
;
674 apiserv
->peer_async
= peer_async
;
676 /* And add read threads for new connection */
677 ospf_apiserver_event(OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
678 #ifdef USE_ASYNC_READ
679 ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ
, new_async_sock
,
681 #endif /* USE_ASYNC_READ */
683 if (IS_DEBUG_OSPF_EVENT
)
684 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv
,
685 apiserver_list
->count
);
689 /* -----------------------------------------------------------
690 * Send reply with return code to client application
691 * -----------------------------------------------------------
694 static int ospf_apiserver_send_msg(struct ospf_apiserver
*apiserv
,
697 struct msg_fifo
*fifo
;
699 enum ospf_apiserver_event event
;
702 switch (msg
->hdr
.msgtype
) {
704 fifo
= apiserv
->out_sync_fifo
;
705 fd
= apiserv
->fd_sync
;
706 event
= OSPF_APISERVER_SYNC_WRITE
;
708 case MSG_READY_NOTIFY
:
709 case MSG_LSA_UPDATE_NOTIFY
:
710 case MSG_LSA_DELETE_NOTIFY
:
715 case MSG_REACHABLE_CHANGE
:
716 case MSG_ROUTER_ID_CHANGE
:
717 fifo
= apiserv
->out_async_fifo
;
718 fd
= apiserv
->fd_async
;
719 event
= OSPF_APISERVER_ASYNC_WRITE
;
722 zlog_warn("%s: Unknown message type %d", __func__
,
727 /* Make a copy of the message and put in the fifo. Once the fifo
728 gets drained by the write thread, the message will be freed. */
729 /* NB: Given "msg" is untouched in this function. */
732 /* Enqueue message into corresponding fifo queue */
733 msg_fifo_push(fifo
, msg2
);
735 /* Schedule write thread */
736 ospf_apiserver_event(event
, fd
, apiserv
);
740 int ospf_apiserver_send_reply(struct ospf_apiserver
*apiserv
, uint32_t seqnr
,
743 struct msg
*msg
= new_msg_reply(seqnr
, rc
);
747 zlog_warn("%s: msg_new failed", __func__
);
749 /* Cannot allocate new message. What should we do? */
750 ospf_apiserver_free(apiserv
);
755 ret
= ospf_apiserver_send_msg(apiserv
, msg
);
761 /* -----------------------------------------------------------
762 * Generic message dispatching handler function
763 * -----------------------------------------------------------
766 int ospf_apiserver_handle_msg(struct ospf_apiserver
*apiserv
, struct msg
*msg
)
770 /* Call corresponding message handler function. */
771 switch (msg
->hdr
.msgtype
) {
772 case MSG_REGISTER_OPAQUETYPE
:
773 rc
= ospf_apiserver_handle_register_opaque_type(apiserv
, msg
);
775 case MSG_UNREGISTER_OPAQUETYPE
:
776 rc
= ospf_apiserver_handle_unregister_opaque_type(apiserv
, msg
);
778 case MSG_REGISTER_EVENT
:
779 rc
= ospf_apiserver_handle_register_event(apiserv
, msg
);
782 rc
= ospf_apiserver_handle_sync_lsdb(apiserv
, msg
);
784 case MSG_ORIGINATE_REQUEST
:
785 rc
= ospf_apiserver_handle_originate_request(apiserv
, msg
);
787 case MSG_DELETE_REQUEST
:
788 rc
= ospf_apiserver_handle_delete_request(apiserv
, msg
);
790 case MSG_SYNC_REACHABLE
:
791 rc
= ospf_apiserver_handle_sync_reachable(apiserv
, msg
);
794 rc
= ospf_apiserver_handle_sync_ism(apiserv
, msg
);
797 rc
= ospf_apiserver_handle_sync_nsm(apiserv
, msg
);
799 case MSG_SYNC_ROUTER_ID
:
800 rc
= ospf_apiserver_handle_sync_router_id(apiserv
, msg
);
803 zlog_warn("%s: Unknown message type: %d", __func__
,
811 /* -----------------------------------------------------------
812 * Following are functions for opaque type registration
813 * -----------------------------------------------------------
816 int ospf_apiserver_register_opaque_type(struct ospf_apiserver
*apiserv
,
817 uint8_t lsa_type
, uint8_t opaque_type
)
819 struct registered_opaque_type
*regtype
;
820 int (*originator_func
)(void *arg
);
824 case OSPF_OPAQUE_LINK_LSA
:
825 originator_func
= ospf_apiserver_lsa9_originator
;
827 case OSPF_OPAQUE_AREA_LSA
:
828 originator_func
= ospf_apiserver_lsa10_originator
;
830 case OSPF_OPAQUE_AS_LSA
:
831 originator_func
= ospf_apiserver_lsa11_originator
;
834 zlog_warn("%s: lsa_type(%d)", __func__
, lsa_type
);
835 return OSPF_API_ILLEGALLSATYPE
;
839 /* Register opaque function table */
840 /* NB: Duplicated registration will be detected inside the function. */
841 rc
= ospf_register_opaque_functab(
842 lsa_type
, opaque_type
, NULL
, /* ospf_apiserver_new_if */
843 NULL
, /* ospf_apiserver_del_if */
844 NULL
, /* ospf_apiserver_ism_change */
845 NULL
, /* ospf_apiserver_nsm_change */
846 NULL
, NULL
, NULL
, ospf_apiserver_show_info
, originator_func
,
847 ospf_apiserver_lsa_refresher
,
848 NULL
, /* ospf_apiserver_lsa_update */
849 NULL
/* ospf_apiserver_lsa_delete */);
852 flog_warn(EC_OSPF_OPAQUE_REGISTRATION
,
853 "Failed to register opaque type [%d/%d]", lsa_type
,
855 return OSPF_API_OPAQUETYPEINUSE
;
858 /* Remember the opaque type that application registers so when
859 connection shuts down, we can flush all LSAs of this opaque
863 XCALLOC(MTYPE_APISERVER
, sizeof(struct registered_opaque_type
));
864 regtype
->lsa_type
= lsa_type
;
865 regtype
->opaque_type
= opaque_type
;
867 /* Add to list of registered opaque types */
868 listnode_add(apiserv
->opaque_types
, regtype
);
870 if (IS_DEBUG_OSPF_EVENT
)
872 "API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)",
873 lsa_type
, opaque_type
, (void *)apiserv
,
874 listcount(apiserv
->opaque_types
));
879 int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
880 uint8_t lsa_type
, uint8_t opaque_type
)
882 struct listnode
*node
, *nnode
;
883 struct registered_opaque_type
*regtype
;
885 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
886 /* Check if we really registered this opaque type */
887 if (regtype
->lsa_type
== lsa_type
888 && regtype
->opaque_type
== opaque_type
) {
890 /* Yes, we registered this opaque type. Flush
891 all existing opaque LSAs of this type */
893 ospf_apiserver_flush_opaque_lsa(apiserv
, lsa_type
,
895 ospf_delete_opaque_functab(lsa_type
, opaque_type
);
897 /* Remove from list of registered opaque types */
898 listnode_delete(apiserv
->opaque_types
, regtype
);
900 XFREE(MTYPE_APISERVER
, regtype
);
901 if (IS_DEBUG_OSPF_EVENT
)
903 "API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)",
904 lsa_type
, opaque_type
, (void *)apiserv
,
905 listcount(apiserv
->opaque_types
));
911 /* Opaque type is not registered */
912 zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type
,
914 return OSPF_API_OPAQUETYPENOTREGISTERED
;
918 static int apiserver_is_opaque_type_registered(struct ospf_apiserver
*apiserv
,
922 struct listnode
*node
, *nnode
;
923 struct registered_opaque_type
*regtype
;
925 /* XXX: how many types are there? if few, why not just a bitmap? */
926 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
927 /* Check if we really registered this opaque type */
928 if (regtype
->lsa_type
== lsa_type
929 && regtype
->opaque_type
== opaque_type
) {
938 int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver
*apiserv
,
941 struct msg_register_opaque_type
*rmsg
;
946 /* Extract parameters from register opaque type message */
947 rmsg
= (struct msg_register_opaque_type
*)STREAM_DATA(msg
->s
);
949 lsa_type
= rmsg
->lsatype
;
950 opaque_type
= rmsg
->opaquetype
;
952 rc
= ospf_apiserver_register_opaque_type(apiserv
, lsa_type
,
955 /* Send a reply back to client including return code */
956 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
960 /* Now inform application about opaque types that are ready */
962 case OSPF_OPAQUE_LINK_LSA
:
963 ospf_apiserver_notify_ready_type9(apiserv
);
965 case OSPF_OPAQUE_AREA_LSA
:
966 ospf_apiserver_notify_ready_type10(apiserv
);
968 case OSPF_OPAQUE_AS_LSA
:
969 ospf_apiserver_notify_ready_type11(apiserv
);
977 /* Notify specific client about all opaque types 9 that are ready. */
978 void ospf_apiserver_notify_ready_type9(struct ospf_apiserver
*apiserv
)
980 struct listnode
*node
, *nnode
;
981 struct listnode
*node2
, *nnode2
;
983 struct ospf_interface
*oi
;
984 struct registered_opaque_type
*r
;
986 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
988 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
)) {
989 /* Check if this interface is indeed ready for type 9 */
990 if (!ospf_apiserver_is_ready_type9(oi
))
993 /* Check for registered opaque type 9 types */
994 /* XXX: loop-de-loop - optimise me */
995 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
999 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
1001 /* Yes, this opaque type is ready */
1002 msg
= new_msg_ready_notify(
1003 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
1004 oi
->address
->u
.prefix4
);
1006 zlog_warn("%s: msg_new failed",
1009 /* Cannot allocate new message. What
1011 ospf_apiserver_free(apiserv
);
1015 ospf_apiserver_send_msg(apiserv
, msg
);
1026 /* Notify specific client about all opaque types 10 that are ready. */
1027 void ospf_apiserver_notify_ready_type10(struct ospf_apiserver
*apiserv
)
1029 struct listnode
*node
, *nnode
;
1030 struct listnode
*node2
, *nnode2
;
1032 struct ospf_area
*area
;
1034 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1036 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1037 struct registered_opaque_type
*r
;
1039 if (!ospf_apiserver_is_ready_type10(area
)) {
1043 /* Check for registered opaque type 10 types */
1044 /* XXX: loop in loop - optimise me */
1045 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
1049 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
1050 /* Yes, this opaque type is ready */
1051 msg
= new_msg_ready_notify(
1052 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
1055 zlog_warn("%s: msg_new failed",
1058 /* Cannot allocate new message. What
1060 ospf_apiserver_free(apiserv
);
1064 ospf_apiserver_send_msg(apiserv
, msg
);
1074 /* Notify specific client about all opaque types 11 that are ready */
1075 void ospf_apiserver_notify_ready_type11(struct ospf_apiserver
*apiserv
)
1077 struct listnode
*node
, *nnode
;
1079 struct registered_opaque_type
*r
;
1081 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1083 /* Can type 11 be originated? */
1084 if (!ospf_apiserver_is_ready_type11(ospf
))
1087 /* Check for registered opaque type 11 types */
1088 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, r
)) {
1090 struct in_addr noarea_id
= {.s_addr
= 0L};
1092 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
1093 /* Yes, this opaque type is ready */
1094 msg
= new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA
,
1095 r
->opaque_type
, noarea_id
);
1098 zlog_warn("%s: msg_new failed", __func__
);
1100 /* Cannot allocate new message. What should we
1102 ospf_apiserver_free(apiserv
);
1106 ospf_apiserver_send_msg(apiserv
, msg
);
1115 int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
1118 struct msg_unregister_opaque_type
*umsg
;
1123 /* Extract parameters from unregister opaque type message */
1124 umsg
= (struct msg_unregister_opaque_type
*)STREAM_DATA(msg
->s
);
1126 ltype
= umsg
->lsatype
;
1127 otype
= umsg
->opaquetype
;
1129 rc
= ospf_apiserver_unregister_opaque_type(apiserv
, ltype
, otype
);
1131 /* Send a reply back to client including return code */
1132 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1138 /* -----------------------------------------------------------
1139 * Following are functions for event (filter) registration.
1140 * -----------------------------------------------------------
1142 int ospf_apiserver_handle_register_event(struct ospf_apiserver
*apiserv
,
1145 struct msg_register_event
*rmsg
;
1150 rmsg
= (struct msg_register_event
*)STREAM_DATA(msg
->s
);
1152 /* Get request sequence number */
1153 seqnum
= msg_get_seq(msg
);
1155 /* Free existing filter in apiserv. */
1156 XFREE(MTYPE_APISERVER_MSGFILTER
, apiserv
->filter
);
1157 /* Alloc new space for filter. */
1158 size
= ntohs(msg
->hdr
.msglen
);
1159 if (size
< OSPF_MAX_LSA_SIZE
) {
1161 apiserv
->filter
= XMALLOC(MTYPE_APISERVER_MSGFILTER
, size
);
1164 memcpy(apiserv
->filter
, &rmsg
->filter
, size
);
1167 rc
= OSPF_API_NOMEMORY
;
1169 /* Send a reply back to client with return code */
1170 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1175 /* -----------------------------------------------------------
1176 * Following are functions for LSDB synchronization.
1177 * -----------------------------------------------------------
1180 static int apiserver_sync_callback(struct ospf_lsa
*lsa
, void *p_arg
,
1183 struct ospf_apiserver
*apiserv
;
1187 struct ospf_apiserver
*apiserv
;
1188 struct lsa_filter_type
*filter
;
1196 param
= (struct param_t
*)p_arg
;
1197 apiserv
= param
->apiserv
;
1198 seqnum
= (uint32_t)int_arg
;
1200 /* Check origin in filter. */
1201 if ((param
->filter
->origin
== ANY_ORIGIN
)
1202 || (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
))) {
1204 /* Default area for AS-External and Opaque11 LSAs */
1205 struct in_addr area_id
= {.s_addr
= 0L};
1207 /* Default interface for non Opaque9 LSAs */
1208 struct in_addr ifaddr
= {.s_addr
= 0L};
1211 area_id
= lsa
->area
->area_id
;
1213 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
1214 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1217 msg
= new_msg_lsa_change_notify(
1218 MSG_LSA_UPDATE_NOTIFY
, seqnum
, ifaddr
, area_id
,
1219 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1221 zlog_warn("%s: new_msg_update failed", __func__
);
1223 /* Cannot allocate new message. What should we do? */
1224 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1232 ospf_apiserver_send_msg(apiserv
, msg
);
1241 int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver
*apiserv
,
1244 struct listnode
*node
, *nnode
;
1247 struct msg_sync_lsdb
*smsg
;
1248 struct ospf_apiserver_param_t
{
1249 struct ospf_apiserver
*apiserv
;
1250 struct lsa_filter_type
*filter
;
1253 struct route_node
*rn
;
1254 struct ospf_lsa
*lsa
;
1256 struct ospf_area
*area
;
1258 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1260 /* Get request sequence number */
1261 seqnum
= msg_get_seq(msg
);
1263 smsg
= (struct msg_sync_lsdb
*)STREAM_DATA(msg
->s
);
1265 /* Set parameter struct. */
1266 param
.apiserv
= apiserv
;
1267 param
.filter
= &smsg
->filter
;
1269 /* Remember mask. */
1270 mask
= ntohs(smsg
->filter
.typemask
);
1272 /* Iterate over all areas. */
1273 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1275 uint32_t *area_id
= NULL
;
1277 /* Compare area_id with area_ids in sync request. */
1278 if ((i
= smsg
->filter
.num_areas
) > 0) {
1279 /* Let area_id point to the list of area IDs,
1280 * which is at the end of smsg->filter. */
1281 area_id
= (uint32_t *)(&smsg
->filter
+ 1);
1283 if (*area_id
== area
->area_id
.s_addr
) {
1293 /* If area was found, then i>0 here. */
1295 /* Check msg type. */
1296 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1297 LSDB_LOOP (ROUTER_LSDB(area
), rn
, lsa
)
1298 apiserver_sync_callback(
1299 lsa
, (void *)¶m
, seqnum
);
1300 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1301 LSDB_LOOP (NETWORK_LSDB(area
), rn
, lsa
)
1302 apiserver_sync_callback(
1303 lsa
, (void *)¶m
, seqnum
);
1304 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1305 LSDB_LOOP (SUMMARY_LSDB(area
), rn
, lsa
)
1306 apiserver_sync_callback(
1307 lsa
, (void *)¶m
, seqnum
);
1308 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1309 LSDB_LOOP (ASBR_SUMMARY_LSDB(area
), rn
, lsa
)
1310 apiserver_sync_callback(
1311 lsa
, (void *)¶m
, seqnum
);
1312 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1313 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1314 apiserver_sync_callback(
1315 lsa
, (void *)¶m
, seqnum
);
1316 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1317 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1318 apiserver_sync_callback(
1319 lsa
, (void *)¶m
, seqnum
);
1323 /* For AS-external LSAs */
1325 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1326 LSDB_LOOP (EXTERNAL_LSDB(ospf
), rn
, lsa
)
1327 apiserver_sync_callback(lsa
, (void *)¶m
,
1331 /* For AS-external opaque LSAs */
1333 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1334 LSDB_LOOP (OPAQUE_AS_LSDB(ospf
), rn
, lsa
)
1335 apiserver_sync_callback(lsa
, (void *)¶m
,
1339 /* Send a reply back to client with return code */
1340 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1345 * -----------------------------------------------------------
1346 * Followings are functions for synchronization.
1347 * -----------------------------------------------------------
1350 int ospf_apiserver_handle_sync_reachable(struct ospf_apiserver
*apiserv
,
1353 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1354 struct route_table
*rt
= ospf
->all_rtrs
;
1355 uint32_t seqnum
= msg_get_seq(msg
);
1356 struct in_addr
*a
, *abuf
;
1357 struct msg_reachable_change
*areach
;
1365 /* send all adds based on current reachable routers */
1366 a
= abuf
= XCALLOC(MTYPE_APISERVER
, sizeof(struct in_addr
) * rt
->count
);
1367 for (struct route_node
*rn
= route_top(rt
); rn
; rn
= route_next(rn
))
1368 if (listhead((struct list
*)rn
->info
))
1369 *a
++ = rn
->p
.u
.prefix4
;
1371 assert((a
- abuf
) <= (long)rt
->count
);
1375 while (count
&& !rc
) {
1376 amsg
= new_msg_reachable_change(seqnum
, count
, a
, 0, NULL
);
1377 areach
= (struct msg_reachable_change
*)STREAM_DATA(amsg
->s
);
1378 mcount
= ntohs(areach
->nadd
) + ntohs(areach
->nremove
);
1379 assert(mcount
<= count
);
1382 rc
= ospf_apiserver_send_msg(apiserv
, amsg
);
1385 XFREE(MTYPE_APISERVER
, abuf
);
1388 /* Send a reply back to client with return code */
1389 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1391 apiserv
->reachable_sync
= !rc
;
1395 int ospf_apiserver_handle_sync_ism(struct ospf_apiserver
*apiserv
,
1398 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1399 struct listnode
*anode
, *inode
;
1400 struct ospf_area
*area
;
1401 struct ospf_interface
*oi
;
1403 uint32_t seqnum
= msg_get_seq(msg
);
1406 /* walk all areas */
1407 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, anode
, area
)) {
1408 /* walk all interfaces */
1409 for (ALL_LIST_ELEMENTS_RO(area
->oiflist
, inode
, oi
)) {
1410 m
= new_msg_ism_change(seqnum
, oi
->address
->u
.prefix4
,
1411 area
->area_id
, oi
->state
);
1412 rc
= ospf_apiserver_send_msg(apiserv
, m
);
1420 /* Send a reply back to client with return code */
1421 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1422 return rc
? rc
: _rc
;
1426 int ospf_apiserver_handle_sync_nsm(struct ospf_apiserver
*apiserv
,
1429 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1430 struct listnode
*anode
, *inode
;
1431 struct ospf_area
*area
;
1432 struct ospf_interface
*oi
;
1433 struct ospf_neighbor
*nbr
;
1434 struct route_node
*rn
;
1436 uint32_t seqnum
= msg_get_seq(msg
);
1439 /* walk all areas */
1440 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, anode
, area
)) {
1441 /* walk all interfaces */
1442 for (ALL_LIST_ELEMENTS_RO(area
->oiflist
, inode
, oi
)) {
1443 /* walk all neighbors */
1444 for (rn
= route_top(oi
->nbrs
); rn
;
1445 rn
= route_next(rn
)) {
1449 m
= new_msg_nsm_change(
1450 seqnum
, oi
->address
->u
.prefix4
,
1451 nbr
->src
, nbr
->router_id
, nbr
->state
);
1452 rc
= ospf_apiserver_send_msg(apiserv
, m
);
1463 /* Send a reply back to client with return code */
1464 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1465 return rc
? rc
: _rc
;
1469 int ospf_apiserver_handle_sync_router_id(struct ospf_apiserver
*apiserv
,
1472 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1473 uint32_t seqnum
= msg_get_seq(msg
);
1477 m
= new_msg_router_id_change(seqnum
, ospf
->router_id
);
1478 rc
= ospf_apiserver_send_msg(apiserv
, m
);
1481 /* Send a reply back to client with return code */
1482 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1483 return rc
? rc
: _rc
;
1486 /* -----------------------------------------------------------
1487 * Following are functions to originate or update LSA
1488 * from an application.
1489 * -----------------------------------------------------------
1492 /* Create a new internal opaque LSA by taking prototype and filling in
1493 missing fields such as age, sequence number, advertising router,
1494 checksum and so on. The interface parameter is used for type 9
1495 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1498 struct ospf_lsa
*ospf_apiserver_opaque_lsa_new(struct ospf_area
*area
,
1499 struct ospf_interface
*oi
,
1500 struct lsa_header
*protolsa
)
1503 struct lsa_header
*newlsa
;
1504 struct ospf_lsa
*new = NULL
;
1505 uint8_t options
= 0x0;
1513 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1517 /* Create a stream for internal opaque LSA */
1518 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
1519 zlog_warn("%s: stream_new failed", __func__
);
1523 newlsa
= (struct lsa_header
*)STREAM_DATA(s
);
1525 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1526 have to set options? */
1529 options
= LSA_OPTIONS_GET(area
);
1530 options
|= LSA_OPTIONS_NSSA_GET(area
);
1533 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1535 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1536 zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
1537 protolsa
->type
, &protolsa
->id
);
1540 /* Set opaque-LSA header fields. */
1541 lsa_header_set(s
, options
, protolsa
->type
, protolsa
->id
,
1544 /* Set opaque-LSA body fields. */
1545 stream_put(s
, ((uint8_t *)protolsa
) + sizeof(struct lsa_header
),
1546 ntohs(protolsa
->length
) - sizeof(struct lsa_header
));
1548 /* Determine length of LSA. */
1549 length
= stream_get_endp(s
);
1550 newlsa
->length
= htons(length
);
1552 /* Create OSPF LSA. */
1553 new = ospf_lsa_new_and_data(length
);
1557 new->vrf_id
= ospf
->vrf_id
;
1559 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1560 memcpy(new->data
, newlsa
, length
);
1567 int ospf_apiserver_is_ready_type9(struct ospf_interface
*oi
)
1569 /* We can always handle getting opaque's even if we can't flood them */
1573 int ospf_apiserver_is_ready_type10(struct ospf_area
*area
)
1575 /* We can always handle getting opaque's even if we can't flood them */
1579 int ospf_apiserver_is_ready_type11(struct ospf
*ospf
)
1581 /* We can always handle getting opaque's even if we can't flood them */
1586 int ospf_apiserver_handle_originate_request(struct ospf_apiserver
*apiserv
,
1589 struct msg_originate_request
*omsg
;
1590 struct lsa_header
*data
;
1591 struct ospf_lsa
*new;
1592 struct ospf_lsa
*old
;
1593 struct ospf_area
*area
= NULL
;
1594 struct ospf_interface
*oi
= NULL
;
1595 struct ospf_lsdb
*lsdb
= NULL
;
1597 int lsa_type
, opaque_type
;
1601 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1603 /* Extract opaque LSA data from message */
1604 omsg
= (struct msg_originate_request
*)STREAM_DATA(msg
->s
);
1607 /* Determine interface for type9 or area for type10 LSAs. */
1608 switch (data
->type
) {
1609 case OSPF_OPAQUE_LINK_LSA
:
1610 oi
= ospf_apiserver_if_lookup_by_addr(omsg
->ifaddr
);
1612 zlog_warn("%s: unknown interface %pI4", __func__
,
1614 rc
= OSPF_API_NOSUCHINTERFACE
;
1620 case OSPF_OPAQUE_AREA_LSA
:
1621 area
= ospf_area_lookup_by_area_id(ospf
, omsg
->area_id
);
1623 zlog_warn("%s: unknown area %pI4", __func__
,
1625 rc
= OSPF_API_NOSUCHAREA
;
1630 case OSPF_OPAQUE_AS_LSA
:
1634 /* We can only handle opaque types here */
1635 zlog_warn("%s: Cannot originate non-opaque LSA type %d",
1636 __func__
, data
->type
);
1637 rc
= OSPF_API_ILLEGALLSATYPE
;
1641 /* Check if we registered this opaque type */
1642 lsa_type
= data
->type
;
1643 opaque_type
= GET_OPAQUE_TYPE(ntohl(data
->id
.s_addr
));
1645 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1647 zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
1648 __func__
, lsa_type
, opaque_type
);
1649 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1653 /* Make sure that the neighbors are ready before we can originate */
1654 switch (data
->type
) {
1655 case OSPF_OPAQUE_LINK_LSA
:
1656 ready
= ospf_apiserver_is_ready_type9(oi
);
1658 case OSPF_OPAQUE_AREA_LSA
:
1659 ready
= ospf_apiserver_is_ready_type10(area
);
1661 case OSPF_OPAQUE_AS_LSA
:
1662 ready
= ospf_apiserver_is_ready_type11(ospf
);
1669 zlog_warn("Neighbors not ready to originate type %d",
1671 rc
= OSPF_API_NOTREADY
;
1675 /* Create OSPF's internal opaque LSA representation */
1676 new = ospf_apiserver_opaque_lsa_new(area
, oi
, data
);
1678 rc
= OSPF_API_NOMEMORY
; /* XXX */
1682 /* Determine if LSA is new or an update for an existing one. */
1683 old
= ospf_lsdb_lookup(lsdb
, new);
1685 if (!old
|| !ospf_opaque_is_owned(old
)) {
1686 /* New LSA install in LSDB. */
1687 rc
= ospf_apiserver_originate1(new, old
);
1690 * Keep the new LSA instance in the "waiting place" until the
1692 * refresh timing. If several LSA update requests for the same
1694 * have issued by peer, the last one takes effect.
1696 new->lsdb
= &apiserv
->reserve
;
1697 ospf_lsdb_add(&apiserv
->reserve
, new);
1699 /* Kick the scheduler function. */
1700 ospf_opaque_lsa_refresh_schedule(old
);
1705 /* Send a reply back to client with return code */
1706 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1711 /* -----------------------------------------------------------
1712 * Flood an LSA within its flooding scope.
1713 * -----------------------------------------------------------
1716 /* XXX We can probably use ospf_flood_through instead of this function
1717 but then we need the neighbor parameter. If we set nbr to
1718 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1720 void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa
*lsa
)
1724 switch (lsa
->data
->type
) {
1725 case OSPF_OPAQUE_LINK_LSA
:
1726 /* Increment counters? XXX */
1728 /* Flood LSA through local network. */
1729 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1731 case OSPF_OPAQUE_AREA_LSA
:
1732 /* Update LSA origination count. */
1734 lsa
->area
->ospf
->lsa_originate_count
++;
1736 /* Flood LSA through area. */
1737 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1739 case OSPF_OPAQUE_AS_LSA
: {
1742 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1745 /* Increment counters? XXX */
1747 /* Flood LSA through AS. */
1748 ospf_flood_through_as(ospf
, NULL
/*nbr */, lsa
);
1754 int ospf_apiserver_originate1(struct ospf_lsa
*lsa
, struct ospf_lsa
*old
)
1758 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1763 * An old LSA exists that we didn't originate it in this
1764 * session. Dump it, but increment past it's seqnum.
1766 assert(!ospf_opaque_is_owned(old
));
1767 if (IS_LSA_MAX_SEQ(old
)) {
1768 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1769 "%s: old LSA at maxseq", __func__
);
1772 lsa
->data
->ls_seqnum
= lsa_seqnum_increment(old
);
1773 ospf_discard_from_db(ospf
, old
->lsdb
, old
);
1776 /* Install this LSA into LSDB. */
1777 if (ospf_lsa_install(ospf
, lsa
->oi
, lsa
) == NULL
) {
1778 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1779 "%s: ospf_lsa_install failed", __func__
);
1783 /* Flood LSA within scope */
1787 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1788 * parameter, and thus it does not cause SIGSEGV error.
1790 ospf_flood_through(NULL
/*nbr */, lsa
);
1793 ospf_apiserver_flood_opaque_lsa(lsa
);
1800 /* Opaque LSAs of type 9 on a specific interface can now be
1801 originated. Tell clients that registered type 9. */
1802 int ospf_apiserver_lsa9_originator(void *arg
)
1804 struct ospf_interface
*oi
;
1806 oi
= (struct ospf_interface
*)arg
;
1807 if (listcount(apiserver_list
) > 0) {
1808 ospf_apiserver_clients_notify_ready_type9(oi
);
1813 int ospf_apiserver_lsa10_originator(void *arg
)
1815 struct ospf_area
*area
;
1817 area
= (struct ospf_area
*)arg
;
1818 if (listcount(apiserver_list
) > 0) {
1819 ospf_apiserver_clients_notify_ready_type10(area
);
1824 int ospf_apiserver_lsa11_originator(void *arg
)
1828 ospf
= (struct ospf
*)arg
;
1829 if (listcount(apiserver_list
) > 0) {
1830 ospf_apiserver_clients_notify_ready_type11(ospf
);
1836 /* Periodically refresh opaque LSAs so that they do not expire in
1838 struct ospf_lsa
*ospf_apiserver_lsa_refresher(struct ospf_lsa
*lsa
)
1840 struct ospf_apiserver
*apiserv
;
1841 struct ospf_lsa
*new = NULL
;
1846 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1849 apiserv
= lookup_apiserver_by_lsa(lsa
);
1851 zlog_warn("%s: LSA[%s]: No apiserver?", __func__
,
1854 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1858 if (IS_LSA_MAXAGE(lsa
)) {
1859 ospf_opaque_lsa_flush_schedule(lsa
);
1863 /* Check if updated version of LSA instance has already prepared. */
1864 new = ospf_lsdb_lookup(&apiserv
->reserve
, lsa
);
1866 /* This is a periodic refresh, driven by core OSPF mechanism. */
1867 new = ospf_apiserver_opaque_lsa_new(lsa
->area
, lsa
->oi
,
1870 zlog_warn("%s: Cannot create a new LSA?", __func__
);
1874 /* This is a forcible refresh, requested by OSPF-API client. */
1875 ospf_lsdb_delete(&apiserv
->reserve
, new);
1879 /* Increment sequence number */
1880 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1882 /* New LSA is in same area. */
1883 new->area
= lsa
->area
;
1884 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1886 /* Install LSA into LSDB. */
1887 if (ospf_lsa_install(ospf
, new->oi
, new) == NULL
) {
1888 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1889 "%s: ospf_lsa_install failed", __func__
);
1890 ospf_lsa_unlock(&new);
1894 /* Flood updated LSA through interface, area or AS */
1897 ospf_flood_through(NULL
/*nbr */, new);
1899 ospf_apiserver_flood_opaque_lsa(new);
1901 /* Debug logging. */
1902 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1903 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
1904 new->data
->type
, &new->data
->id
);
1905 ospf_lsa_header_dump(new->data
);
1913 /* -----------------------------------------------------------
1914 * Following are functions to delete LSAs
1915 * -----------------------------------------------------------
1918 int ospf_apiserver_handle_delete_request(struct ospf_apiserver
*apiserv
,
1921 struct msg_delete_request
*dmsg
;
1922 struct ospf_lsa
*old
;
1923 struct ospf_area
*area
= NULL
;
1924 struct ospf_interface
*oi
= NULL
;
1926 int lsa_type
, opaque_type
;
1930 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1933 /* Extract opaque LSA from message */
1934 dmsg
= (struct msg_delete_request
*)STREAM_DATA(msg
->s
);
1936 /* Lookup area for link-local and area-local opaque LSAs */
1937 switch (dmsg
->lsa_type
) {
1938 case OSPF_OPAQUE_LINK_LSA
:
1939 oi
= ospf_apiserver_if_lookup_by_addr(dmsg
->addr
);
1941 zlog_warn("%s: unknown interface %pI4", __func__
,
1943 rc
= OSPF_API_NOSUCHINTERFACE
;
1948 case OSPF_OPAQUE_AREA_LSA
:
1949 area
= ospf_area_lookup_by_area_id(ospf
, dmsg
->addr
);
1951 zlog_warn("%s: unknown area %pI4", __func__
,
1953 rc
= OSPF_API_NOSUCHAREA
;
1957 case OSPF_OPAQUE_AS_LSA
:
1958 /* AS-external opaque LSAs have no designated area */
1962 zlog_warn("%s: Cannot delete non-opaque LSA type %d", __func__
,
1964 rc
= OSPF_API_ILLEGALLSATYPE
;
1968 /* Check if we registered this opaque type */
1969 lsa_type
= dmsg
->lsa_type
;
1970 opaque_type
= dmsg
->opaque_type
;
1972 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1974 zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
1975 __func__
, lsa_type
, opaque_type
);
1976 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1980 /* opaque_id is in network byte order */
1982 SET_OPAQUE_LSID(dmsg
->opaque_type
, ntohl(dmsg
->opaque_id
)));
1985 * Even if the target LSA has once scheduled to flush, it remains in
1986 * the LSDB until it is finally handled by the maxage remover thread.
1987 * Therefore, the lookup function below may return non-NULL result.
1989 old
= ospf_lsa_lookup(ospf
, area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1991 zlog_warn("%s: LSA[Type%d:%pI4] not in LSDB", __func__
,
1992 dmsg
->lsa_type
, &id
);
1993 rc
= OSPF_API_NOSUCHLSA
;
1997 if (IS_DEL_ZERO_LEN_LSA(dmsg
)) {
1998 /* minimize the size of the withdrawal: */
1999 old
->opaque_zero_len_delete
= 1;
2002 /* Schedule flushing of LSA from LSDB */
2003 /* NB: Multiple scheduling will produce a warning message, but harmless.
2005 ospf_opaque_lsa_flush_schedule(old
);
2009 /* Send reply back to client including return code */
2010 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
2014 /* Flush self-originated opaque LSA */
2015 static int apiserver_flush_opaque_type_callback(struct ospf_lsa
*lsa
,
2016 void *p_arg
, int int_arg
)
2019 struct ospf_apiserver
*apiserv
;
2021 uint8_t opaque_type
;
2027 param
= (struct param_t
*)p_arg
;
2029 /* If LSA matches type and opaque type then delete it */
2030 if (IS_LSA_SELF(lsa
) && lsa
->data
->type
== param
->lsa_type
2031 && GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
2032 == param
->opaque_type
) {
2033 ospf_opaque_lsa_flush_schedule(lsa
);
2038 /* Delete self-originated opaque LSAs of a given opaque type. This
2039 function is called when an application unregisters a given opaque
2040 type or a connection to an application closes and all those opaque
2041 LSAs need to be flushed the LSDB. */
2042 void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver
*apiserv
,
2043 uint8_t lsa_type
, uint8_t opaque_type
)
2046 struct ospf_apiserver
*apiserv
;
2048 uint8_t opaque_type
;
2050 struct listnode
*node
, *nnode
;
2052 struct ospf_area
*area
;
2054 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
2057 /* Set parameter struct. */
2058 param
.apiserv
= apiserv
;
2059 param
.lsa_type
= lsa_type
;
2060 param
.opaque_type
= opaque_type
;
2063 struct route_node
*rn
;
2064 struct ospf_lsa
*lsa
;
2066 case OSPF_OPAQUE_LINK_LSA
:
2067 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
2068 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
2069 apiserver_flush_opaque_type_callback(
2070 lsa
, (void *)¶m
, 0);
2072 case OSPF_OPAQUE_AREA_LSA
:
2073 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
2074 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
2075 apiserver_flush_opaque_type_callback(
2076 lsa
, (void *)¶m
, 0);
2078 case OSPF_OPAQUE_AS_LSA
:
2079 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf
), rn
, lsa
)
2080 apiserver_flush_opaque_type_callback(lsa
,
2090 /* -----------------------------------------------------------
2091 * Following are callback functions to handle opaque types
2092 * -----------------------------------------------------------
2095 int ospf_apiserver_new_if(struct interface
*ifp
)
2097 struct ospf_interface
*oi
;
2099 /* For some strange reason it seems possible that we are invoked
2100 with an interface that has no name. This seems to happen during
2101 initialization. Return if this happens */
2103 if (ifp
->name
[0] == '\0') {
2104 /* interface has empty name */
2105 zlog_warn("%s: interface has no name?", __func__
);
2109 /* zlog_warn for debugging */
2110 zlog_warn("ospf_apiserver_new_if");
2111 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2114 if (ifp
->name
[0] == '\0') {
2115 /* interface has empty name */
2116 zlog_warn("%s: interface has no name?", __func__
);
2120 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2123 /* This interface is known to Zebra but not to OSPF daemon yet.
2125 zlog_warn("%s: interface %s not known to OSPFd?", __func__
,
2132 /* New interface added to OSPF, tell clients about it */
2133 if (listcount(apiserver_list
) > 0) {
2134 ospf_apiserver_clients_notify_new_if(oi
);
2139 int ospf_apiserver_del_if(struct interface
*ifp
)
2141 struct ospf_interface
*oi
;
2143 /* zlog_warn for debugging */
2144 zlog_warn("%s ifp name=%s status=%d index=%d", __func__
, ifp
->name
,
2145 ifp
->status
, ifp
->ifindex
);
2147 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2150 /* This interface is known to Zebra but not to OSPF daemon
2151 anymore. No need to tell clients about it */
2152 zlog_warn("ifp name=%s not known to OSPFd", ifp
->name
);
2156 /* Interface deleted, tell clients about it */
2157 if (listcount(apiserver_list
) > 0) {
2158 ospf_apiserver_clients_notify_del_if(oi
);
2163 void ospf_apiserver_ism_change(struct ospf_interface
*oi
, int old_state
)
2165 /* Tell clients about interface change */
2167 /* zlog_warn for debugging */
2168 zlog_warn("%s", __func__
);
2169 if (listcount(apiserver_list
) > 0) {
2170 ospf_apiserver_clients_notify_ism_change(oi
);
2173 zlog_warn("%s oi->ifp->name=%s old_state=%d oi->state=%d", __func__
,
2174 oi
->ifp
->name
, old_state
, oi
->state
);
2177 void ospf_apiserver_nsm_change(struct ospf_neighbor
*nbr
, int old_status
)
2179 /* Neighbor status changed, tell clients about it */
2180 zlog_warn("%s", __func__
);
2181 if (listcount(apiserver_list
) > 0) {
2182 ospf_apiserver_clients_notify_nsm_change(nbr
);
2186 void ospf_apiserver_show_info(struct vty
*vty
, struct json_object
*json
,
2187 struct ospf_lsa
*lsa
)
2190 struct lsa_header header
;
2191 uint8_t data
[1]; /* opaque data have variable length. This is
2195 struct opaque_lsa
*olsa
;
2198 olsa
= (struct opaque_lsa
*)lsa
->data
;
2200 if (VALID_OPAQUE_INFO_LEN(lsa
->data
))
2201 opaquelen
= ntohs(lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2205 /* Output information about opaque LSAs */
2207 json_object_string_addf(json
, "opaqueData", "%*pHXn",
2208 (int)opaquelen
, olsa
->data
);
2209 else if (vty
!= NULL
) {
2212 " Added using OSPF API: %u octets of opaque data %s\n",
2214 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2215 : "(Invalid length?)");
2216 vty_out(vty
, " Opaque data: ");
2218 for (i
= 0; i
< opaquelen
; i
++) {
2219 vty_out(vty
, "0x%x ", olsa
->data
[i
]);
2225 " Added using OSPF API: %u octets of opaque data %s",
2227 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2228 : "(Invalid length?)");
2229 zlog_debug(" Opaque data: ");
2231 for (i
= 0; i
< opaquelen
; i
++) {
2232 zlog_debug("0x%x ", olsa
->data
[i
]);
2238 /* -----------------------------------------------------------
2239 * Following are functions to notify clients about events
2240 * -----------------------------------------------------------
2243 /* Send a message to all clients. This is useful for messages
2244 that need to be notified to all clients (such as interface
2247 void ospf_apiserver_clients_notify_all(struct msg
*msg
)
2249 struct listnode
*node
, *nnode
;
2250 struct ospf_apiserver
*apiserv
;
2252 /* Send message to all clients */
2253 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
))
2254 ospf_apiserver_send_msg(apiserv
, msg
);
2257 /* An interface is now ready to accept opaque LSAs. Notify all
2258 clients that registered to use this opaque type */
2259 void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface
*oi
)
2261 struct listnode
*node
, *nnode
;
2263 struct ospf_apiserver
*apiserv
;
2267 zlog_warn("Interface has no address?");
2271 if (!ospf_apiserver_is_ready_type9(oi
)) {
2272 zlog_warn("Interface not ready for type 9?");
2276 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2277 struct listnode
*node2
, *nnode2
;
2278 struct registered_opaque_type
*r
;
2280 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2282 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
2283 msg
= new_msg_ready_notify(
2284 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
2285 oi
->address
->u
.prefix4
);
2288 "%s: new_msg_ready_notify failed",
2291 /* Cannot allocate new message. What
2293 ospf_apiserver_free(apiserv
);
2298 ospf_apiserver_send_msg(apiserv
, msg
);
2308 void 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
)) {
2317 zlog_warn("Area not ready for type 10?");
2321 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2322 struct listnode
*node2
, *nnode2
;
2323 struct registered_opaque_type
*r
;
2325 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2327 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
2328 msg
= new_msg_ready_notify(
2329 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
2333 "%s: new_msg_ready_nofity failed",
2336 /* Cannot allocate new message. What
2338 ospf_apiserver_free(apiserv
);
2343 ospf_apiserver_send_msg(apiserv
, msg
);
2354 void ospf_apiserver_clients_notify_ready_type11(struct ospf
*top
)
2356 struct listnode
*node
, *nnode
;
2358 struct in_addr id_null
= {.s_addr
= 0L};
2359 struct ospf_apiserver
*apiserv
;
2363 if (!ospf_apiserver_is_ready_type11(top
)) {
2364 zlog_warn("AS not ready for type 11?");
2368 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2369 struct listnode
*node2
, *nnode2
;
2370 struct registered_opaque_type
*r
;
2372 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2374 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
2375 msg
= new_msg_ready_notify(
2376 0, OSPF_OPAQUE_AS_LSA
, r
->opaque_type
,
2380 "%s: new_msg_ready_notify failed",
2383 /* Cannot allocate new message. What
2385 ospf_apiserver_free(apiserv
);
2390 ospf_apiserver_send_msg(apiserv
, msg
);
2400 void ospf_apiserver_clients_notify_new_if(struct ospf_interface
*oi
)
2404 msg
= new_msg_new_if(0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2406 ospf_apiserver_clients_notify_all(msg
);
2411 void ospf_apiserver_clients_notify_del_if(struct ospf_interface
*oi
)
2415 msg
= new_msg_del_if(0, oi
->address
->u
.prefix4
);
2417 ospf_apiserver_clients_notify_all(msg
);
2422 void ospf_apiserver_clients_notify_ism_change(struct ospf_interface
*oi
)
2425 struct in_addr ifaddr
= {.s_addr
= 0L};
2426 struct in_addr area_id
= {.s_addr
= 0L};
2432 ifaddr
= oi
->address
->u
.prefix4
;
2435 area_id
= oi
->area
->area_id
;
2438 msg
= new_msg_ism_change(0, ifaddr
, area_id
, oi
->state
);
2440 zlog_warn("%s: msg_new failed", __func__
);
2444 ospf_apiserver_clients_notify_all(msg
);
2448 void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor
*nbr
)
2451 struct in_addr ifaddr
;
2452 struct in_addr nbraddr
;
2456 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2458 nbraddr
= nbr
->address
.u
.prefix4
;
2460 msg
= new_msg_nsm_change(0, ifaddr
, nbraddr
, nbr
->router_id
,
2463 zlog_warn("%s: msg_new failed", __func__
);
2467 ospf_apiserver_clients_notify_all(msg
);
2471 static int apiserver_clients_lsa_change_notify(uint8_t msgtype
,
2472 struct ospf_lsa
*lsa
)
2475 struct listnode
*node
, *nnode
;
2476 struct ospf_apiserver
*apiserv
;
2478 /* Default area for AS-External and Opaque11 LSAs */
2479 struct in_addr area_id
= {.s_addr
= 0L};
2481 /* Default interface for non Opaque9 LSAs */
2482 struct in_addr ifaddr
= {.s_addr
= 0L};
2485 area_id
= lsa
->area
->area_id
;
2487 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2489 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2492 /* Prepare message that can be sent to clients that have a matching
2494 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2496 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2498 zlog_warn("%s: msg_new failed", __func__
);
2502 /* Now send message to all clients with a matching filter */
2503 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2504 struct lsa_filter_type
*filter
;
2509 /* Check filter for this client. */
2510 filter
= apiserv
->filter
;
2512 /* Check area IDs in case of non AS-E LSAs.
2513 * If filter has areas (num_areas > 0),
2514 * then one of the areas must match the area ID of this LSA. */
2516 i
= filter
->num_areas
;
2517 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)
2518 || (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
)) {
2523 area
= (uint32_t *)(filter
+ 1);
2525 if (*area
== area_id
.s_addr
) {
2536 /* Area match. Check LSA type. */
2537 mask
= ntohs(filter
->typemask
);
2539 if (mask
& Power2
[lsa
->data
->type
]) {
2540 /* Type also matches. Check origin. */
2541 if ((filter
->origin
== ANY_ORIGIN
)
2542 || (filter
->origin
== IS_LSA_SELF(lsa
))) {
2543 ospf_apiserver_send_msg(apiserv
, msg
);
2548 /* Free message since it is not used anymore */
2555 /* -------------------------------------------------------------
2556 * Following are hooks invoked when LSAs are updated or deleted
2557 * -------------------------------------------------------------
2561 int ospf_apiserver_lsa_update(struct ospf_lsa
*lsa
)
2564 /* Only notify this update if the LSA's age is smaller than
2565 MAXAGE. Otherwise clients would see LSA updates with max age just
2566 before they are deleted from the LSDB. LSA delete messages have
2567 MAXAGE too but should not be filtered. */
2568 if (IS_LSA_MAXAGE(lsa
))
2570 return apiserver_clients_lsa_change_notify(MSG_LSA_UPDATE_NOTIFY
, lsa
);
2573 int ospf_apiserver_lsa_delete(struct ospf_lsa
*lsa
)
2575 return apiserver_clients_lsa_change_notify(MSG_LSA_DELETE_NOTIFY
, lsa
);
2578 /* -------------------------------------------------------------
2579 * Reachable functions
2580 * -------------------------------------------------------------
2583 static inline int cmp_route_nodes(struct route_node
*orn
,
2584 struct route_node
*nrn
)
2591 uint32_t opn
= ntohl(orn
->p
.u
.prefix4
.s_addr
);
2592 uint32_t npn
= ntohl(nrn
->p
.u
.prefix4
.s_addr
);
2601 void ospf_apiserver_notify_reachable(struct route_table
*ort
,
2602 struct route_table
*nrt
)
2605 struct msg_reachable_change
*areach
;
2606 struct route_node
*orn
, *nrn
;
2607 const uint insz
= sizeof(struct in_addr
);
2608 struct in_addr
*abuf
= NULL
, *dbuf
= NULL
;
2609 struct in_addr
*a
= NULL
, *d
= NULL
;
2614 if (IS_DEBUG_OSPF_CLIENT_API
)
2615 zlog_debug("%s: no routing tables", __func__
);
2618 if (nrt
&& nrt
->count
)
2619 a
= abuf
= XCALLOC(MTYPE_APISERVER
, insz
* nrt
->count
);
2620 if (ort
&& ort
->count
)
2621 d
= dbuf
= XCALLOC(MTYPE_APISERVER
, insz
* ort
->count
);
2623 /* walk both tables */
2624 orn
= ort
? route_top(ort
) : NULL
;
2625 nrn
= nrt
? route_top(nrt
) : NULL
;
2626 while (orn
|| nrn
) {
2627 if (orn
&& !listhead((struct list
*)orn
->info
)) {
2628 orn
= route_next(orn
);
2631 if (nrn
&& !listhead((struct list
*)nrn
->info
)) {
2632 nrn
= route_next(nrn
);
2635 cmp
= cmp_route_nodes(orn
, nrn
);
2637 /* if old == new advance old and new */
2638 if (IS_DEBUG_OSPF_CLIENT_API
)
2639 zlog_debug("keeping router id: %pI4",
2641 orn
= route_next(orn
);
2642 nrn
= route_next(nrn
);
2643 } else if (cmp
< 0) {
2644 assert(d
!= NULL
); /* Silence SA warning */
2646 /* if old < new, delete old, advance old */
2647 *d
++ = orn
->p
.u
.prefix4
;
2648 if (IS_DEBUG_OSPF_CLIENT_API
)
2649 zlog_debug("removing router id: %pI4",
2651 orn
= route_next(orn
);
2653 assert(a
!= NULL
); /* Silence SA warning */
2655 /* if new < old, add new, advance new */
2656 *a
++ = nrn
->p
.u
.prefix4
;
2657 if (IS_DEBUG_OSPF_CLIENT_API
)
2658 zlog_debug("adding router id: %pI4",
2660 nrn
= route_next(nrn
);
2664 nadd
= abuf
? (a
- abuf
) : 0;
2665 nremove
= dbuf
? (d
- dbuf
) : 0;
2669 while (nadd
+ nremove
) {
2670 msg
= new_msg_reachable_change(0, nadd
, a
, nremove
, d
);
2671 areach
= (struct msg_reachable_change
*)STREAM_DATA(msg
->s
);
2673 a
+= ntohs(areach
->nadd
);
2674 nadd
= nadd
- ntohs(areach
->nadd
);
2676 d
+= ntohs(areach
->nremove
);
2677 nremove
= nremove
- ntohs(areach
->nremove
);
2679 if (IS_DEBUG_OSPF_CLIENT_API
)
2680 zlog_debug("%s: adding %d removing %d", __func__
,
2681 ntohs(areach
->nadd
), ntohs(areach
->nremove
));
2682 ospf_apiserver_clients_notify_all(msg
);
2686 XFREE(MTYPE_APISERVER
, abuf
);
2688 XFREE(MTYPE_APISERVER
, dbuf
);
2692 void ospf_apiserver_clients_notify_router_id_change(struct in_addr router_id
)
2696 msg
= new_msg_router_id_change(0, router_id
);
2698 zlog_warn("%s: new_msg_router_id_change failed", __func__
);
2702 ospf_apiserver_clients_notify_all(msg
);
2707 #endif /* SUPPORT_OSPF_API */