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 thread_master" */
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.
169 while (apiserver_list
170 && (apiserv
= listgetdata(listhead(apiserver_list
))) != NULL
)
171 ospf_apiserver_free(apiserv
);
173 /* Free client list itself */
175 list_delete(&apiserver_list
);
177 /* Free wildcard list */
181 static struct ospf_apiserver
*lookup_apiserver(uint8_t lsa_type
,
184 struct listnode
*n1
, *n2
;
185 struct registered_opaque_type
*r
;
186 struct ospf_apiserver
*apiserv
, *found
= NULL
;
188 /* XXX: this approaches O(n**2) */
189 for (ALL_LIST_ELEMENTS_RO(apiserver_list
, n1
, apiserv
)) {
190 for (ALL_LIST_ELEMENTS_RO(apiserv
->opaque_types
, n2
, r
))
191 if (r
->lsa_type
== lsa_type
192 && r
->opaque_type
== opaque_type
) {
201 static struct ospf_apiserver
*lookup_apiserver_by_lsa(struct ospf_lsa
*lsa
)
203 struct lsa_header
*lsah
= lsa
->data
;
204 struct ospf_apiserver
*found
= NULL
;
206 if (IS_OPAQUE_LSA(lsah
->type
)) {
207 found
= lookup_apiserver(
208 lsah
->type
, GET_OPAQUE_TYPE(ntohl(lsah
->id
.s_addr
)));
213 /* -----------------------------------------------------------
214 * Following are functions to manage client connections.
215 * -----------------------------------------------------------
217 static int ospf_apiserver_new_lsa_hook(struct ospf_lsa
*lsa
)
219 if (IS_DEBUG_OSPF_EVENT
)
220 zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
221 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
225 static int ospf_apiserver_del_lsa_hook(struct ospf_lsa
*lsa
)
227 if (IS_DEBUG_OSPF_EVENT
)
228 zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
229 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
233 /* Allocate new connection structure. */
234 struct ospf_apiserver
*ospf_apiserver_new(int fd_sync
, int fd_async
)
236 struct ospf_apiserver
*new =
237 XMALLOC(MTYPE_APISERVER
, sizeof(struct ospf_apiserver
));
239 new->filter
= XMALLOC(MTYPE_APISERVER_MSGFILTER
,
240 sizeof(struct lsa_filter_type
));
242 new->fd_sync
= fd_sync
;
243 new->fd_async
= fd_async
;
245 /* list of registered opaque types that application uses */
246 new->opaque_types
= list_new();
248 /* Initialize temporary strage for LSA instances to be refreshed. */
249 memset(&new->reserve
, 0, sizeof(struct ospf_lsdb
));
250 ospf_lsdb_init(&new->reserve
);
252 new->reserve
.new_lsa_hook
= ospf_apiserver_new_lsa_hook
; /* debug */
253 new->reserve
.del_lsa_hook
= ospf_apiserver_del_lsa_hook
; /* debug */
255 new->out_sync_fifo
= msg_fifo_new();
256 new->out_async_fifo
= msg_fifo_new();
257 new->t_sync_read
= NULL
;
258 #ifdef USE_ASYNC_READ
259 new->t_async_read
= NULL
;
260 #endif /* USE_ASYNC_READ */
261 new->t_sync_write
= NULL
;
262 new->t_async_write
= NULL
;
264 new->filter
->typemask
= 0; /* filter all LSAs */
265 new->filter
->origin
= ANY_ORIGIN
;
266 new->filter
->num_areas
= 0;
271 void ospf_apiserver_event(enum ospf_apiserver_event event
, int fd
,
272 struct ospf_apiserver
*apiserv
)
275 case OSPF_APISERVER_ACCEPT
:
276 (void)thread_add_read(master
, ospf_apiserver_accept
, apiserv
,
279 case OSPF_APISERVER_SYNC_READ
:
280 apiserv
->t_sync_read
= NULL
;
281 thread_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
282 &apiserv
->t_sync_read
);
284 #ifdef USE_ASYNC_READ
285 case OSPF_APISERVER_ASYNC_READ
:
286 apiserv
->t_async_read
= NULL
;
287 thread_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
288 &apiserv
->t_async_read
);
290 #endif /* USE_ASYNC_READ */
291 case OSPF_APISERVER_SYNC_WRITE
:
292 thread_add_write(master
, ospf_apiserver_sync_write
, apiserv
, fd
,
293 &apiserv
->t_sync_write
);
295 case OSPF_APISERVER_ASYNC_WRITE
:
296 thread_add_write(master
, ospf_apiserver_async_write
, apiserv
,
297 fd
, &apiserv
->t_async_write
);
302 /* Free instance. First unregister all opaque types used by
303 application, flush opaque LSAs injected by application
304 from network and close connection. */
305 void ospf_apiserver_free(struct ospf_apiserver
*apiserv
)
307 struct listnode
*node
;
309 /* Cancel read and write threads. */
310 THREAD_OFF(apiserv
->t_sync_read
);
311 #ifdef USE_ASYNC_READ
312 THREAD_OFF(apiserv
->t_async_read
);
313 #endif /* USE_ASYNC_READ */
314 THREAD_OFF(apiserv
->t_sync_write
);
315 THREAD_OFF(apiserv
->t_async_write
);
317 /* Unregister all opaque types that application registered
318 and flush opaque LSAs if still in LSDB. */
320 while ((node
= listhead(apiserv
->opaque_types
)) != NULL
) {
321 struct registered_opaque_type
*regtype
= listgetdata(node
);
323 ospf_apiserver_unregister_opaque_type(
324 apiserv
, regtype
->lsa_type
, regtype
->opaque_type
);
327 /* Close connections to OSPFd. */
328 if (apiserv
->fd_sync
> 0) {
329 close(apiserv
->fd_sync
);
332 if (apiserv
->fd_async
> 0) {
333 close(apiserv
->fd_async
);
337 msg_fifo_free(apiserv
->out_sync_fifo
);
338 msg_fifo_free(apiserv
->out_async_fifo
);
340 /* Clear temporary strage for LSA instances to be refreshed. */
341 ospf_lsdb_delete_all(&apiserv
->reserve
);
342 ospf_lsdb_cleanup(&apiserv
->reserve
);
344 /* Remove from the list of active clients. */
345 listnode_delete(apiserver_list
, apiserv
);
347 if (IS_DEBUG_OSPF_EVENT
)
348 zlog_debug("API: Delete apiserv(%p), total#(%d)",
349 (void *)apiserv
, apiserver_list
->count
);
351 /* And free instance. */
352 XFREE(MTYPE_APISERVER
, apiserv
);
355 void ospf_apiserver_read(struct thread
*thread
)
357 struct ospf_apiserver
*apiserv
;
360 enum ospf_apiserver_event event
;
362 apiserv
= THREAD_ARG(thread
);
363 fd
= THREAD_FD(thread
);
365 if (fd
== apiserv
->fd_sync
) {
366 event
= OSPF_APISERVER_SYNC_READ
;
367 apiserv
->t_sync_read
= NULL
;
369 if (IS_DEBUG_OSPF_EVENT
)
370 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
371 &apiserv
->peer_sync
.sin_addr
,
372 ntohs(apiserv
->peer_sync
.sin_port
));
374 #ifdef USE_ASYNC_READ
375 else if (fd
== apiserv
->fd_async
) {
376 event
= OSPF_APISERVER_ASYNC_READ
;
377 apiserv
->t_async_read
= NULL
;
379 if (IS_DEBUG_OSPF_EVENT
)
380 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
381 &apiserv
->peer_async
.sin_addr
,
382 ntohs(apiserv
->peer_async
.sin_port
));
384 #endif /* USE_ASYNC_READ */
386 zlog_warn("%s: Unknown fd(%d)", __func__
, fd
);
387 ospf_apiserver_free(apiserv
);
391 /* Read message from fd. */
394 zlog_warn("%s: read failed on fd=%d, closing connection",
397 /* Perform cleanup. */
398 ospf_apiserver_free(apiserv
);
402 if (IS_DEBUG_OSPF_EVENT
)
405 /* Dispatch to corresponding message handler. */
406 ospf_apiserver_handle_msg(apiserv
, msg
);
408 /* Prepare for next message, add read thread. */
409 ospf_apiserver_event(event
, fd
, apiserv
);
414 void ospf_apiserver_sync_write(struct thread
*thread
)
416 struct ospf_apiserver
*apiserv
;
421 apiserv
= THREAD_ARG(thread
);
423 fd
= THREAD_FD(thread
);
425 apiserv
->t_sync_write
= NULL
;
428 if (fd
!= apiserv
->fd_sync
) {
429 zlog_warn("%s: Unknown fd=%d", __func__
, fd
);
433 if (IS_DEBUG_OSPF_EVENT
)
434 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
435 &apiserv
->peer_sync
.sin_addr
,
436 ntohs(apiserv
->peer_sync
.sin_port
));
438 /* Check whether there is really a message in the fifo. */
439 msg
= msg_fifo_pop(apiserv
->out_sync_fifo
);
441 zlog_warn("API: %s: No message in Sync-FIFO?", __func__
);
445 if (IS_DEBUG_OSPF_EVENT
)
448 rc
= msg_write(fd
, msg
);
450 /* Once a message is dequeued, it should be freed anyway. */
454 zlog_warn("%s: write failed on fd=%d", __func__
, fd
);
459 /* If more messages are in sync message fifo, schedule write thread. */
460 if (msg_fifo_head(apiserv
->out_sync_fifo
)) {
461 ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE
,
462 apiserv
->fd_sync
, apiserv
);
468 /* Perform cleanup and disconnect with peer */
469 ospf_apiserver_free(apiserv
);
474 void ospf_apiserver_async_write(struct thread
*thread
)
476 struct ospf_apiserver
*apiserv
;
481 apiserv
= THREAD_ARG(thread
);
483 fd
= THREAD_FD(thread
);
485 apiserv
->t_async_write
= NULL
;
488 if (fd
!= apiserv
->fd_async
) {
489 zlog_warn("%s: Unknown fd=%d", __func__
, fd
);
493 if (IS_DEBUG_OSPF_EVENT
)
494 zlog_debug("API: %s: Peer: %pI4/%u", __func__
,
495 &apiserv
->peer_async
.sin_addr
,
496 ntohs(apiserv
->peer_async
.sin_port
));
498 /* Check whether there is really a message in the fifo. */
499 msg
= msg_fifo_pop(apiserv
->out_async_fifo
);
501 zlog_warn("API: %s: No message in Async-FIFO?", __func__
);
505 if (IS_DEBUG_OSPF_EVENT
)
508 rc
= msg_write(fd
, msg
);
510 /* Once a message is dequeued, it should be freed anyway. */
514 zlog_warn("%s: write failed on fd=%d", __func__
, fd
);
519 /* If more messages are in async message fifo, schedule write thread. */
520 if (msg_fifo_head(apiserv
->out_async_fifo
)) {
521 ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE
,
522 apiserv
->fd_async
, apiserv
);
528 /* Perform cleanup and disconnect with peer */
529 ospf_apiserver_free(apiserv
);
534 int ospf_apiserver_serv_sock_family(unsigned short port
, int family
)
540 memset(&su
, 0, sizeof(union sockunion
));
541 su
.sa
.sa_family
= family
;
543 /* Make new socket */
544 accept_sock
= sockunion_stream_socket(&su
);
548 /* This is a server, so reuse address and port */
549 sockopt_reuseaddr(accept_sock
);
550 sockopt_reuseport(accept_sock
);
552 /* Bind socket to address and given port. */
553 rc
= sockunion_bind(accept_sock
, &su
, port
, NULL
);
555 close(accept_sock
); /* Close socket */
559 /* Listen socket under queue length 3. */
560 rc
= listen(accept_sock
, 3);
562 zlog_warn("%s: listen: %s", __func__
, safe_strerror(errno
));
563 close(accept_sock
); /* Close socket */
570 /* Accept connection request from external applications. For each
571 accepted connection allocate own connection instance. */
572 void ospf_apiserver_accept(struct thread
*thread
)
578 struct ospf_apiserver
*apiserv
;
579 struct sockaddr_in peer_async
;
580 struct sockaddr_in peer_sync
;
581 unsigned int peerlen
;
584 /* THREAD_ARG (thread) is NULL */
585 accept_sock
= THREAD_FD(thread
);
587 /* Keep hearing on socket for further connections. */
588 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
590 memset(&su
, 0, sizeof(union sockunion
));
591 /* Accept connection for synchronous messages */
592 new_sync_sock
= sockunion_accept(accept_sock
, &su
);
593 if (new_sync_sock
< 0) {
594 zlog_warn("%s: accept: %s", __func__
, safe_strerror(errno
));
598 /* Get port address and port number of peer to make reverse connection.
599 The reverse channel uses the port number of the peer port+1. */
601 memset(&peer_sync
, 0, sizeof(peer_sync
));
602 peerlen
= sizeof(struct sockaddr_in
);
604 ret
= getpeername(new_sync_sock
, (struct sockaddr
*)&peer_sync
,
607 zlog_warn("%s: getpeername: %s", __func__
,
608 safe_strerror(errno
));
609 close(new_sync_sock
);
613 if (IS_DEBUG_OSPF_EVENT
)
614 zlog_debug("API: %s: New peer: %pI4/%u", __func__
,
615 &peer_sync
.sin_addr
, ntohs(peer_sync
.sin_port
));
617 /* Create new socket for asynchronous messages. */
618 peer_async
= peer_sync
;
619 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
621 /* Check if remote port number to make reverse connection is valid one.
623 if (ntohs(peer_async
.sin_port
) == ospf_apiserver_getport()) {
624 zlog_warn("API: %s: Peer(%pI4/%u): Invalid async port number?",
625 __func__
, &peer_async
.sin_addr
,
626 ntohs(peer_async
.sin_port
));
627 close(new_sync_sock
);
631 new_async_sock
= socket(AF_INET
, SOCK_STREAM
, 0);
632 if (new_async_sock
< 0) {
633 zlog_warn("%s: socket: %s", __func__
, safe_strerror(errno
));
634 close(new_sync_sock
);
638 ret
= connect(new_async_sock
, (struct sockaddr
*)&peer_async
,
639 sizeof(struct sockaddr_in
));
642 zlog_warn("%s: connect: %s", __func__
, safe_strerror(errno
));
643 close(new_sync_sock
);
644 close(new_async_sock
);
648 #ifdef USE_ASYNC_READ
649 #else /* USE_ASYNC_READ */
650 /* Make the asynchronous channel write-only. */
651 ret
= shutdown(new_async_sock
, SHUT_RD
);
653 zlog_warn("%s: shutdown: %s", __func__
, safe_strerror(errno
));
654 close(new_sync_sock
);
655 close(new_async_sock
);
658 #endif /* USE_ASYNC_READ */
660 /* Allocate new server-side connection structure */
661 apiserv
= ospf_apiserver_new(new_sync_sock
, new_async_sock
);
663 /* Add to active connection list */
664 listnode_add(apiserver_list
, apiserv
);
665 apiserv
->peer_sync
= peer_sync
;
666 apiserv
->peer_async
= peer_async
;
668 /* And add read threads for new connection */
669 ospf_apiserver_event(OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
670 #ifdef USE_ASYNC_READ
671 ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ
, new_async_sock
,
673 #endif /* USE_ASYNC_READ */
675 if (IS_DEBUG_OSPF_EVENT
)
676 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv
,
677 apiserver_list
->count
);
681 /* -----------------------------------------------------------
682 * Send reply with return code to client application
683 * -----------------------------------------------------------
686 static int ospf_apiserver_send_msg(struct ospf_apiserver
*apiserv
,
689 struct msg_fifo
*fifo
;
691 enum ospf_apiserver_event event
;
694 switch (msg
->hdr
.msgtype
) {
696 fifo
= apiserv
->out_sync_fifo
;
697 fd
= apiserv
->fd_sync
;
698 event
= OSPF_APISERVER_SYNC_WRITE
;
700 case MSG_READY_NOTIFY
:
701 case MSG_LSA_UPDATE_NOTIFY
:
702 case MSG_LSA_DELETE_NOTIFY
:
707 case MSG_REACHABLE_CHANGE
:
708 case MSG_ROUTER_ID_CHANGE
:
709 fifo
= apiserv
->out_async_fifo
;
710 fd
= apiserv
->fd_async
;
711 event
= OSPF_APISERVER_ASYNC_WRITE
;
714 zlog_warn("%s: Unknown message type %d", __func__
,
719 /* Make a copy of the message and put in the fifo. Once the fifo
720 gets drained by the write thread, the message will be freed. */
721 /* NB: Given "msg" is untouched in this function. */
724 /* Enqueue message into corresponding fifo queue */
725 msg_fifo_push(fifo
, msg2
);
727 /* Schedule write thread */
728 ospf_apiserver_event(event
, fd
, apiserv
);
732 int ospf_apiserver_send_reply(struct ospf_apiserver
*apiserv
, uint32_t seqnr
,
735 struct msg
*msg
= new_msg_reply(seqnr
, rc
);
739 zlog_warn("%s: msg_new failed", __func__
);
741 /* Cannot allocate new message. What should we do? */
742 ospf_apiserver_free(apiserv
);
747 ret
= ospf_apiserver_send_msg(apiserv
, msg
);
753 /* -----------------------------------------------------------
754 * Generic message dispatching handler function
755 * -----------------------------------------------------------
758 int ospf_apiserver_handle_msg(struct ospf_apiserver
*apiserv
, struct msg
*msg
)
762 /* Call corresponding message handler function. */
763 switch (msg
->hdr
.msgtype
) {
764 case MSG_REGISTER_OPAQUETYPE
:
765 rc
= ospf_apiserver_handle_register_opaque_type(apiserv
, msg
);
767 case MSG_UNREGISTER_OPAQUETYPE
:
768 rc
= ospf_apiserver_handle_unregister_opaque_type(apiserv
, msg
);
770 case MSG_REGISTER_EVENT
:
771 rc
= ospf_apiserver_handle_register_event(apiserv
, msg
);
774 rc
= ospf_apiserver_handle_sync_lsdb(apiserv
, msg
);
776 case MSG_ORIGINATE_REQUEST
:
777 rc
= ospf_apiserver_handle_originate_request(apiserv
, msg
);
779 case MSG_DELETE_REQUEST
:
780 rc
= ospf_apiserver_handle_delete_request(apiserv
, msg
);
782 case MSG_SYNC_REACHABLE
:
783 rc
= ospf_apiserver_handle_sync_reachable(apiserv
, msg
);
786 rc
= ospf_apiserver_handle_sync_ism(apiserv
, msg
);
789 rc
= ospf_apiserver_handle_sync_nsm(apiserv
, msg
);
791 case MSG_SYNC_ROUTER_ID
:
792 rc
= ospf_apiserver_handle_sync_router_id(apiserv
, msg
);
795 zlog_warn("%s: Unknown message type: %d", __func__
,
803 /* -----------------------------------------------------------
804 * Following are functions for opaque type registration
805 * -----------------------------------------------------------
808 int ospf_apiserver_register_opaque_type(struct ospf_apiserver
*apiserv
,
809 uint8_t lsa_type
, uint8_t opaque_type
)
811 struct registered_opaque_type
*regtype
;
812 int (*originator_func
)(void *arg
);
816 case OSPF_OPAQUE_LINK_LSA
:
817 originator_func
= ospf_apiserver_lsa9_originator
;
819 case OSPF_OPAQUE_AREA_LSA
:
820 originator_func
= ospf_apiserver_lsa10_originator
;
822 case OSPF_OPAQUE_AS_LSA
:
823 originator_func
= ospf_apiserver_lsa11_originator
;
826 zlog_warn("%s: lsa_type(%d)", __func__
, lsa_type
);
827 return OSPF_API_ILLEGALLSATYPE
;
831 /* Register opaque function table */
832 /* NB: Duplicated registration will be detected inside the function. */
833 rc
= ospf_register_opaque_functab(
834 lsa_type
, opaque_type
, NULL
, /* ospf_apiserver_new_if */
835 NULL
, /* ospf_apiserver_del_if */
836 NULL
, /* ospf_apiserver_ism_change */
837 NULL
, /* ospf_apiserver_nsm_change */
838 NULL
, NULL
, NULL
, ospf_apiserver_show_info
, originator_func
,
839 ospf_apiserver_lsa_refresher
,
840 NULL
, /* ospf_apiserver_lsa_update */
841 NULL
/* ospf_apiserver_lsa_delete */);
844 flog_warn(EC_OSPF_OPAQUE_REGISTRATION
,
845 "Failed to register opaque type [%d/%d]", lsa_type
,
847 return OSPF_API_OPAQUETYPEINUSE
;
850 /* Remember the opaque type that application registers so when
851 connection shuts down, we can flush all LSAs of this opaque
855 XCALLOC(MTYPE_APISERVER
, sizeof(struct registered_opaque_type
));
856 regtype
->lsa_type
= lsa_type
;
857 regtype
->opaque_type
= opaque_type
;
859 /* Add to list of registered opaque types */
860 listnode_add(apiserv
->opaque_types
, regtype
);
862 if (IS_DEBUG_OSPF_EVENT
)
864 "API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)",
865 lsa_type
, opaque_type
, (void *)apiserv
,
866 listcount(apiserv
->opaque_types
));
871 int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
872 uint8_t lsa_type
, uint8_t opaque_type
)
874 struct listnode
*node
, *nnode
;
875 struct registered_opaque_type
*regtype
;
877 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
878 /* Check if we really registered this opaque type */
879 if (regtype
->lsa_type
== lsa_type
880 && regtype
->opaque_type
== opaque_type
) {
882 /* Yes, we registered this opaque type. Flush
883 all existing opaque LSAs of this type */
885 ospf_apiserver_flush_opaque_lsa(apiserv
, lsa_type
,
887 ospf_delete_opaque_functab(lsa_type
, opaque_type
);
889 /* Remove from list of registered opaque types */
890 listnode_delete(apiserv
->opaque_types
, regtype
);
892 if (IS_DEBUG_OSPF_EVENT
)
894 "API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)",
895 lsa_type
, opaque_type
, (void *)apiserv
,
896 listcount(apiserv
->opaque_types
));
902 /* Opaque type is not registered */
903 zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type
,
905 return OSPF_API_OPAQUETYPENOTREGISTERED
;
909 static int apiserver_is_opaque_type_registered(struct ospf_apiserver
*apiserv
,
913 struct listnode
*node
, *nnode
;
914 struct registered_opaque_type
*regtype
;
916 /* XXX: how many types are there? if few, why not just a bitmap? */
917 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
918 /* Check if we really registered this opaque type */
919 if (regtype
->lsa_type
== lsa_type
920 && regtype
->opaque_type
== opaque_type
) {
929 int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver
*apiserv
,
932 struct msg_register_opaque_type
*rmsg
;
937 /* Extract parameters from register opaque type message */
938 rmsg
= (struct msg_register_opaque_type
*)STREAM_DATA(msg
->s
);
940 lsa_type
= rmsg
->lsatype
;
941 opaque_type
= rmsg
->opaquetype
;
943 rc
= ospf_apiserver_register_opaque_type(apiserv
, lsa_type
,
946 /* Send a reply back to client including return code */
947 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
951 /* Now inform application about opaque types that are ready */
953 case OSPF_OPAQUE_LINK_LSA
:
954 ospf_apiserver_notify_ready_type9(apiserv
);
956 case OSPF_OPAQUE_AREA_LSA
:
957 ospf_apiserver_notify_ready_type10(apiserv
);
959 case OSPF_OPAQUE_AS_LSA
:
960 ospf_apiserver_notify_ready_type11(apiserv
);
968 /* Notify specific client about all opaque types 9 that are ready. */
969 void ospf_apiserver_notify_ready_type9(struct ospf_apiserver
*apiserv
)
971 struct listnode
*node
, *nnode
;
972 struct listnode
*node2
, *nnode2
;
974 struct ospf_interface
*oi
;
975 struct registered_opaque_type
*r
;
977 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
979 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
)) {
980 /* Check if this interface is indeed ready for type 9 */
981 if (!ospf_apiserver_is_ready_type9(oi
))
984 /* Check for registered opaque type 9 types */
985 /* XXX: loop-de-loop - optimise me */
986 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
990 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
992 /* Yes, this opaque type is ready */
993 msg
= new_msg_ready_notify(
994 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
995 oi
->address
->u
.prefix4
);
997 zlog_warn("%s: msg_new failed",
1000 /* Cannot allocate new message. What
1002 ospf_apiserver_free(apiserv
);
1006 ospf_apiserver_send_msg(apiserv
, msg
);
1017 /* Notify specific client about all opaque types 10 that are ready. */
1018 void ospf_apiserver_notify_ready_type10(struct ospf_apiserver
*apiserv
)
1020 struct listnode
*node
, *nnode
;
1021 struct listnode
*node2
, *nnode2
;
1023 struct ospf_area
*area
;
1025 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1027 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1028 struct registered_opaque_type
*r
;
1030 if (!ospf_apiserver_is_ready_type10(area
)) {
1034 /* Check for registered opaque type 10 types */
1035 /* XXX: loop in loop - optimise me */
1036 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
1040 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
1041 /* Yes, this opaque type is ready */
1042 msg
= new_msg_ready_notify(
1043 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
1046 zlog_warn("%s: msg_new failed",
1049 /* Cannot allocate new message. What
1051 ospf_apiserver_free(apiserv
);
1055 ospf_apiserver_send_msg(apiserv
, msg
);
1065 /* Notify specific client about all opaque types 11 that are ready */
1066 void ospf_apiserver_notify_ready_type11(struct ospf_apiserver
*apiserv
)
1068 struct listnode
*node
, *nnode
;
1070 struct registered_opaque_type
*r
;
1072 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1074 /* Can type 11 be originated? */
1075 if (!ospf_apiserver_is_ready_type11(ospf
))
1078 /* Check for registered opaque type 11 types */
1079 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, r
)) {
1081 struct in_addr noarea_id
= {.s_addr
= 0L};
1083 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
1084 /* Yes, this opaque type is ready */
1085 msg
= new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA
,
1086 r
->opaque_type
, noarea_id
);
1089 zlog_warn("%s: msg_new failed", __func__
);
1091 /* Cannot allocate new message. What should we
1093 ospf_apiserver_free(apiserv
);
1097 ospf_apiserver_send_msg(apiserv
, msg
);
1106 int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
1109 struct msg_unregister_opaque_type
*umsg
;
1114 /* Extract parameters from unregister opaque type message */
1115 umsg
= (struct msg_unregister_opaque_type
*)STREAM_DATA(msg
->s
);
1117 ltype
= umsg
->lsatype
;
1118 otype
= umsg
->opaquetype
;
1120 rc
= ospf_apiserver_unregister_opaque_type(apiserv
, ltype
, otype
);
1122 /* Send a reply back to client including return code */
1123 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1129 /* -----------------------------------------------------------
1130 * Following are functions for event (filter) registration.
1131 * -----------------------------------------------------------
1133 int ospf_apiserver_handle_register_event(struct ospf_apiserver
*apiserv
,
1136 struct msg_register_event
*rmsg
;
1141 rmsg
= (struct msg_register_event
*)STREAM_DATA(msg
->s
);
1143 /* Get request sequence number */
1144 seqnum
= msg_get_seq(msg
);
1146 /* Free existing filter in apiserv. */
1147 XFREE(MTYPE_APISERVER_MSGFILTER
, apiserv
->filter
);
1148 /* Alloc new space for filter. */
1149 size
= ntohs(msg
->hdr
.msglen
);
1150 if (size
< OSPF_MAX_LSA_SIZE
) {
1152 apiserv
->filter
= XMALLOC(MTYPE_APISERVER_MSGFILTER
, size
);
1155 memcpy(apiserv
->filter
, &rmsg
->filter
, size
);
1158 rc
= OSPF_API_NOMEMORY
;
1160 /* Send a reply back to client with return code */
1161 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1166 /* -----------------------------------------------------------
1167 * Following are functions for LSDB synchronization.
1168 * -----------------------------------------------------------
1171 static int apiserver_sync_callback(struct ospf_lsa
*lsa
, void *p_arg
,
1174 struct ospf_apiserver
*apiserv
;
1178 struct ospf_apiserver
*apiserv
;
1179 struct lsa_filter_type
*filter
;
1187 param
= (struct param_t
*)p_arg
;
1188 apiserv
= param
->apiserv
;
1189 seqnum
= (uint32_t)int_arg
;
1191 /* Check origin in filter. */
1192 if ((param
->filter
->origin
== ANY_ORIGIN
)
1193 || (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
))) {
1195 /* Default area for AS-External and Opaque11 LSAs */
1196 struct in_addr area_id
= {.s_addr
= 0L};
1198 /* Default interface for non Opaque9 LSAs */
1199 struct in_addr ifaddr
= {.s_addr
= 0L};
1202 area_id
= lsa
->area
->area_id
;
1204 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
1205 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1208 msg
= new_msg_lsa_change_notify(
1209 MSG_LSA_UPDATE_NOTIFY
, seqnum
, ifaddr
, area_id
,
1210 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1212 zlog_warn("%s: new_msg_update failed", __func__
);
1214 /* Cannot allocate new message. What should we do? */
1215 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1223 ospf_apiserver_send_msg(apiserv
, msg
);
1232 int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver
*apiserv
,
1235 struct listnode
*node
, *nnode
;
1238 struct msg_sync_lsdb
*smsg
;
1239 struct ospf_apiserver_param_t
{
1240 struct ospf_apiserver
*apiserv
;
1241 struct lsa_filter_type
*filter
;
1244 struct route_node
*rn
;
1245 struct ospf_lsa
*lsa
;
1247 struct ospf_area
*area
;
1249 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1251 /* Get request sequence number */
1252 seqnum
= msg_get_seq(msg
);
1254 smsg
= (struct msg_sync_lsdb
*)STREAM_DATA(msg
->s
);
1256 /* Set parameter struct. */
1257 param
.apiserv
= apiserv
;
1258 param
.filter
= &smsg
->filter
;
1260 /* Remember mask. */
1261 mask
= ntohs(smsg
->filter
.typemask
);
1263 /* Iterate over all areas. */
1264 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1266 uint32_t *area_id
= NULL
;
1268 /* Compare area_id with area_ids in sync request. */
1269 if ((i
= smsg
->filter
.num_areas
) > 0) {
1270 /* Let area_id point to the list of area IDs,
1271 * which is at the end of smsg->filter. */
1272 area_id
= (uint32_t *)(&smsg
->filter
+ 1);
1274 if (*area_id
== area
->area_id
.s_addr
) {
1284 /* If area was found, then i>0 here. */
1286 /* Check msg type. */
1287 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1288 LSDB_LOOP (ROUTER_LSDB(area
), rn
, lsa
)
1289 apiserver_sync_callback(
1290 lsa
, (void *)¶m
, seqnum
);
1291 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1292 LSDB_LOOP (NETWORK_LSDB(area
), rn
, lsa
)
1293 apiserver_sync_callback(
1294 lsa
, (void *)¶m
, seqnum
);
1295 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1296 LSDB_LOOP (SUMMARY_LSDB(area
), rn
, lsa
)
1297 apiserver_sync_callback(
1298 lsa
, (void *)¶m
, seqnum
);
1299 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1300 LSDB_LOOP (ASBR_SUMMARY_LSDB(area
), rn
, lsa
)
1301 apiserver_sync_callback(
1302 lsa
, (void *)¶m
, seqnum
);
1303 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1304 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1305 apiserver_sync_callback(
1306 lsa
, (void *)¶m
, seqnum
);
1307 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1308 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1309 apiserver_sync_callback(
1310 lsa
, (void *)¶m
, seqnum
);
1314 /* For AS-external LSAs */
1316 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1317 LSDB_LOOP (EXTERNAL_LSDB(ospf
), rn
, lsa
)
1318 apiserver_sync_callback(lsa
, (void *)¶m
,
1322 /* For AS-external opaque LSAs */
1324 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1325 LSDB_LOOP (OPAQUE_AS_LSDB(ospf
), rn
, lsa
)
1326 apiserver_sync_callback(lsa
, (void *)¶m
,
1330 /* Send a reply back to client with return code */
1331 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1336 * -----------------------------------------------------------
1337 * Followings are functions for synchronization.
1338 * -----------------------------------------------------------
1341 int ospf_apiserver_handle_sync_reachable(struct ospf_apiserver
*apiserv
,
1344 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1345 struct route_table
*rt
= ospf
->all_rtrs
;
1346 uint32_t seqnum
= msg_get_seq(msg
);
1347 struct in_addr
*a
, *abuf
;
1348 struct msg_reachable_change
*areach
;
1356 /* send all adds based on current reachable routers */
1357 a
= abuf
= XCALLOC(MTYPE_APISERVER
, sizeof(struct in_addr
) * rt
->count
);
1358 for (struct route_node
*rn
= route_top(rt
); rn
; rn
= route_next(rn
))
1359 if (listhead((struct list
*)rn
->info
))
1360 *a
++ = rn
->p
.u
.prefix4
;
1362 assert((a
- abuf
) <= (long)rt
->count
);
1366 while (count
&& !rc
) {
1367 amsg
= new_msg_reachable_change(seqnum
, count
, a
, 0, NULL
);
1368 areach
= (struct msg_reachable_change
*)STREAM_DATA(amsg
->s
);
1369 mcount
= ntohs(areach
->nadd
) + ntohs(areach
->nremove
);
1370 assert(mcount
<= count
);
1373 rc
= ospf_apiserver_send_msg(apiserv
, amsg
);
1376 XFREE(MTYPE_APISERVER
, abuf
);
1379 /* Send a reply back to client with return code */
1380 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1382 apiserv
->reachable_sync
= !rc
;
1386 int ospf_apiserver_handle_sync_ism(struct ospf_apiserver
*apiserv
,
1389 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1390 struct listnode
*anode
, *inode
;
1391 struct ospf_area
*area
;
1392 struct ospf_interface
*oi
;
1394 uint32_t seqnum
= msg_get_seq(msg
);
1397 /* walk all areas */
1398 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, anode
, area
)) {
1399 /* walk all interfaces */
1400 for (ALL_LIST_ELEMENTS_RO(area
->oiflist
, inode
, oi
)) {
1401 m
= new_msg_ism_change(seqnum
, oi
->address
->u
.prefix4
,
1402 area
->area_id
, oi
->state
);
1403 rc
= ospf_apiserver_send_msg(apiserv
, m
);
1411 /* Send a reply back to client with return code */
1412 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1413 return rc
? rc
: _rc
;
1417 int ospf_apiserver_handle_sync_nsm(struct ospf_apiserver
*apiserv
,
1420 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1421 struct listnode
*anode
, *inode
;
1422 struct ospf_area
*area
;
1423 struct ospf_interface
*oi
;
1424 struct ospf_neighbor
*nbr
;
1425 struct route_node
*rn
;
1427 uint32_t seqnum
= msg_get_seq(msg
);
1430 /* walk all areas */
1431 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, anode
, area
)) {
1432 /* walk all interfaces */
1433 for (ALL_LIST_ELEMENTS_RO(area
->oiflist
, inode
, oi
)) {
1434 /* walk all neighbors */
1435 for (rn
= route_top(oi
->nbrs
); rn
;
1436 rn
= route_next(rn
)) {
1440 m
= new_msg_nsm_change(
1441 seqnum
, oi
->address
->u
.prefix4
,
1442 nbr
->src
, nbr
->router_id
, nbr
->state
);
1443 rc
= ospf_apiserver_send_msg(apiserv
, m
);
1454 /* Send a reply back to client with return code */
1455 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1456 return rc
? rc
: _rc
;
1460 int ospf_apiserver_handle_sync_router_id(struct ospf_apiserver
*apiserv
,
1463 struct ospf
*ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1464 uint32_t seqnum
= msg_get_seq(msg
);
1468 m
= new_msg_router_id_change(seqnum
, ospf
->router_id
);
1469 rc
= ospf_apiserver_send_msg(apiserv
, m
);
1472 /* Send a reply back to client with return code */
1473 _rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1474 return rc
? rc
: _rc
;
1477 /* -----------------------------------------------------------
1478 * Following are functions to originate or update LSA
1479 * from an application.
1480 * -----------------------------------------------------------
1483 /* Create a new internal opaque LSA by taking prototype and filling in
1484 missing fields such as age, sequence number, advertising router,
1485 checksum and so on. The interface parameter is used for type 9
1486 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1489 struct ospf_lsa
*ospf_apiserver_opaque_lsa_new(struct ospf_area
*area
,
1490 struct ospf_interface
*oi
,
1491 struct lsa_header
*protolsa
)
1494 struct lsa_header
*newlsa
;
1495 struct ospf_lsa
*new = NULL
;
1496 uint8_t options
= 0x0;
1504 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1508 /* Create a stream for internal opaque LSA */
1509 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
1510 zlog_warn("%s: stream_new failed", __func__
);
1514 newlsa
= (struct lsa_header
*)STREAM_DATA(s
);
1516 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1517 have to set options? */
1520 options
= LSA_OPTIONS_GET(area
);
1521 options
|= LSA_OPTIONS_NSSA_GET(area
);
1524 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1526 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1527 zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
1528 protolsa
->type
, &protolsa
->id
);
1531 /* Set opaque-LSA header fields. */
1532 lsa_header_set(s
, options
, protolsa
->type
, protolsa
->id
,
1535 /* Set opaque-LSA body fields. */
1536 stream_put(s
, ((uint8_t *)protolsa
) + sizeof(struct lsa_header
),
1537 ntohs(protolsa
->length
) - sizeof(struct lsa_header
));
1539 /* Determine length of LSA. */
1540 length
= stream_get_endp(s
);
1541 newlsa
->length
= htons(length
);
1543 /* Create OSPF LSA. */
1544 new = ospf_lsa_new_and_data(length
);
1548 new->vrf_id
= ospf
->vrf_id
;
1550 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1551 memcpy(new->data
, newlsa
, length
);
1558 int ospf_apiserver_is_ready_type9(struct ospf_interface
*oi
)
1560 /* We can always handle getting opaque's even if we can't flood them */
1564 int ospf_apiserver_is_ready_type10(struct ospf_area
*area
)
1566 /* We can always handle getting opaque's even if we can't flood them */
1570 int ospf_apiserver_is_ready_type11(struct ospf
*ospf
)
1572 /* We can always handle getting opaque's even if we can't flood them */
1577 int ospf_apiserver_handle_originate_request(struct ospf_apiserver
*apiserv
,
1580 struct msg_originate_request
*omsg
;
1581 struct lsa_header
*data
;
1582 struct ospf_lsa
*new;
1583 struct ospf_lsa
*old
;
1584 struct ospf_area
*area
= NULL
;
1585 struct ospf_interface
*oi
= NULL
;
1586 struct ospf_lsdb
*lsdb
= NULL
;
1588 int lsa_type
, opaque_type
;
1592 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1594 /* Extract opaque LSA data from message */
1595 omsg
= (struct msg_originate_request
*)STREAM_DATA(msg
->s
);
1598 /* Determine interface for type9 or area for type10 LSAs. */
1599 switch (data
->type
) {
1600 case OSPF_OPAQUE_LINK_LSA
:
1601 oi
= ospf_apiserver_if_lookup_by_addr(omsg
->ifaddr
);
1603 zlog_warn("%s: unknown interface %pI4", __func__
,
1605 rc
= OSPF_API_NOSUCHINTERFACE
;
1611 case OSPF_OPAQUE_AREA_LSA
:
1612 area
= ospf_area_lookup_by_area_id(ospf
, omsg
->area_id
);
1614 zlog_warn("%s: unknown area %pI4", __func__
,
1616 rc
= OSPF_API_NOSUCHAREA
;
1621 case OSPF_OPAQUE_AS_LSA
:
1625 /* We can only handle opaque types here */
1626 zlog_warn("%s: Cannot originate non-opaque LSA type %d",
1627 __func__
, data
->type
);
1628 rc
= OSPF_API_ILLEGALLSATYPE
;
1632 /* Check if we registered this opaque type */
1633 lsa_type
= data
->type
;
1634 opaque_type
= GET_OPAQUE_TYPE(ntohl(data
->id
.s_addr
));
1636 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1638 zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
1639 __func__
, lsa_type
, opaque_type
);
1640 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1644 /* Make sure that the neighbors are ready before we can originate */
1645 switch (data
->type
) {
1646 case OSPF_OPAQUE_LINK_LSA
:
1647 ready
= ospf_apiserver_is_ready_type9(oi
);
1649 case OSPF_OPAQUE_AREA_LSA
:
1650 ready
= ospf_apiserver_is_ready_type10(area
);
1652 case OSPF_OPAQUE_AS_LSA
:
1653 ready
= ospf_apiserver_is_ready_type11(ospf
);
1660 zlog_warn("Neighbors not ready to originate type %d",
1662 rc
= OSPF_API_NOTREADY
;
1666 /* Create OSPF's internal opaque LSA representation */
1667 new = ospf_apiserver_opaque_lsa_new(area
, oi
, data
);
1669 rc
= OSPF_API_NOMEMORY
; /* XXX */
1673 /* Determine if LSA is new or an update for an existing one. */
1674 old
= ospf_lsdb_lookup(lsdb
, new);
1676 if (!old
|| !ospf_opaque_is_owned(old
)) {
1677 /* New LSA install in LSDB. */
1678 rc
= ospf_apiserver_originate1(new, old
);
1681 * Keep the new LSA instance in the "waiting place" until the
1683 * refresh timing. If several LSA update requests for the same
1685 * have issued by peer, the last one takes effect.
1687 new->lsdb
= &apiserv
->reserve
;
1688 ospf_lsdb_add(&apiserv
->reserve
, new);
1690 /* Kick the scheduler function. */
1691 ospf_opaque_lsa_refresh_schedule(old
);
1696 /* Send a reply back to client with return code */
1697 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1702 /* -----------------------------------------------------------
1703 * Flood an LSA within its flooding scope.
1704 * -----------------------------------------------------------
1707 /* XXX We can probably use ospf_flood_through instead of this function
1708 but then we need the neighbor parameter. If we set nbr to
1709 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1711 void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa
*lsa
)
1715 switch (lsa
->data
->type
) {
1716 case OSPF_OPAQUE_LINK_LSA
:
1717 /* Increment counters? XXX */
1719 /* Flood LSA through local network. */
1720 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1722 case OSPF_OPAQUE_AREA_LSA
:
1723 /* Update LSA origination count. */
1725 lsa
->area
->ospf
->lsa_originate_count
++;
1727 /* Flood LSA through area. */
1728 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1730 case OSPF_OPAQUE_AS_LSA
: {
1733 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1736 /* Increment counters? XXX */
1738 /* Flood LSA through AS. */
1739 ospf_flood_through_as(ospf
, NULL
/*nbr */, lsa
);
1745 int ospf_apiserver_originate1(struct ospf_lsa
*lsa
, struct ospf_lsa
*old
)
1749 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1754 * An old LSA exists that we didn't originate it in this
1755 * session. Dump it, but increment past it's seqnum.
1757 assert(!ospf_opaque_is_owned(old
));
1758 if (IS_LSA_MAX_SEQ(old
)) {
1759 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1760 "%s: old LSA at maxseq", __func__
);
1763 lsa
->data
->ls_seqnum
= lsa_seqnum_increment(old
);
1764 ospf_discard_from_db(ospf
, old
->lsdb
, old
);
1767 /* Install this LSA into LSDB. */
1768 if (ospf_lsa_install(ospf
, lsa
->oi
, lsa
) == NULL
) {
1769 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1770 "%s: ospf_lsa_install failed", __func__
);
1774 /* Flood LSA within scope */
1778 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1779 * parameter, and thus it does not cause SIGSEGV error.
1781 ospf_flood_through(NULL
/*nbr */, lsa
);
1784 ospf_apiserver_flood_opaque_lsa(lsa
);
1791 /* Opaque LSAs of type 9 on a specific interface can now be
1792 originated. Tell clients that registered type 9. */
1793 int ospf_apiserver_lsa9_originator(void *arg
)
1795 struct ospf_interface
*oi
;
1797 oi
= (struct ospf_interface
*)arg
;
1798 if (listcount(apiserver_list
) > 0) {
1799 ospf_apiserver_clients_notify_ready_type9(oi
);
1804 int ospf_apiserver_lsa10_originator(void *arg
)
1806 struct ospf_area
*area
;
1808 area
= (struct ospf_area
*)arg
;
1809 if (listcount(apiserver_list
) > 0) {
1810 ospf_apiserver_clients_notify_ready_type10(area
);
1815 int ospf_apiserver_lsa11_originator(void *arg
)
1819 ospf
= (struct ospf
*)arg
;
1820 if (listcount(apiserver_list
) > 0) {
1821 ospf_apiserver_clients_notify_ready_type11(ospf
);
1827 /* Periodically refresh opaque LSAs so that they do not expire in
1829 struct ospf_lsa
*ospf_apiserver_lsa_refresher(struct ospf_lsa
*lsa
)
1831 struct ospf_apiserver
*apiserv
;
1832 struct ospf_lsa
*new = NULL
;
1837 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1840 apiserv
= lookup_apiserver_by_lsa(lsa
);
1842 zlog_warn("%s: LSA[%s]: No apiserver?", __func__
,
1845 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1849 if (IS_LSA_MAXAGE(lsa
)) {
1850 ospf_opaque_lsa_flush_schedule(lsa
);
1854 /* Check if updated version of LSA instance has already prepared. */
1855 new = ospf_lsdb_lookup(&apiserv
->reserve
, lsa
);
1857 /* This is a periodic refresh, driven by core OSPF mechanism. */
1858 new = ospf_apiserver_opaque_lsa_new(lsa
->area
, lsa
->oi
,
1861 zlog_warn("%s: Cannot create a new LSA?", __func__
);
1865 /* This is a forcible refresh, requested by OSPF-API client. */
1866 ospf_lsdb_delete(&apiserv
->reserve
, new);
1870 /* Increment sequence number */
1871 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1873 /* New LSA is in same area. */
1874 new->area
= lsa
->area
;
1875 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1877 /* Install LSA into LSDB. */
1878 if (ospf_lsa_install(ospf
, new->oi
, new) == NULL
) {
1879 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1880 "%s: ospf_lsa_install failed", __func__
);
1881 ospf_lsa_unlock(&new);
1885 /* Flood updated LSA through interface, area or AS */
1888 ospf_flood_through(NULL
/*nbr */, new);
1890 ospf_apiserver_flood_opaque_lsa(new);
1892 /* Debug logging. */
1893 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1894 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
1895 new->data
->type
, &new->data
->id
);
1896 ospf_lsa_header_dump(new->data
);
1904 /* -----------------------------------------------------------
1905 * Following are functions to delete LSAs
1906 * -----------------------------------------------------------
1909 int ospf_apiserver_handle_delete_request(struct ospf_apiserver
*apiserv
,
1912 struct msg_delete_request
*dmsg
;
1913 struct ospf_lsa
*old
;
1914 struct ospf_area
*area
= NULL
;
1915 struct ospf_interface
*oi
= NULL
;
1917 int lsa_type
, opaque_type
;
1921 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1924 /* Extract opaque LSA from message */
1925 dmsg
= (struct msg_delete_request
*)STREAM_DATA(msg
->s
);
1927 /* Lookup area for link-local and area-local opaque LSAs */
1928 switch (dmsg
->lsa_type
) {
1929 case OSPF_OPAQUE_LINK_LSA
:
1930 oi
= ospf_apiserver_if_lookup_by_addr(dmsg
->addr
);
1932 zlog_warn("%s: unknown interface %pI4", __func__
,
1934 rc
= OSPF_API_NOSUCHINTERFACE
;
1939 case OSPF_OPAQUE_AREA_LSA
:
1940 area
= ospf_area_lookup_by_area_id(ospf
, dmsg
->addr
);
1942 zlog_warn("%s: unknown area %pI4", __func__
,
1944 rc
= OSPF_API_NOSUCHAREA
;
1948 case OSPF_OPAQUE_AS_LSA
:
1949 /* AS-external opaque LSAs have no designated area */
1953 zlog_warn("%s: Cannot delete non-opaque LSA type %d", __func__
,
1955 rc
= OSPF_API_ILLEGALLSATYPE
;
1959 /* Check if we registered this opaque type */
1960 lsa_type
= dmsg
->lsa_type
;
1961 opaque_type
= dmsg
->opaque_type
;
1963 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1965 zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
1966 __func__
, lsa_type
, opaque_type
);
1967 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1971 /* opaque_id is in network byte order */
1973 SET_OPAQUE_LSID(dmsg
->opaque_type
, ntohl(dmsg
->opaque_id
)));
1976 * Even if the target LSA has once scheduled to flush, it remains in
1977 * the LSDB until it is finally handled by the maxage remover thread.
1978 * Therefore, the lookup function below may return non-NULL result.
1980 old
= ospf_lsa_lookup(ospf
, area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1982 zlog_warn("%s: LSA[Type%d:%pI4] not in LSDB", __func__
,
1983 dmsg
->lsa_type
, &id
);
1984 rc
= OSPF_API_NOSUCHLSA
;
1988 if (IS_DEL_ZERO_LEN_LSA(dmsg
)) {
1989 /* minimize the size of the withdrawal: */
1990 old
->opaque_zero_len_delete
= 1;
1993 /* Schedule flushing of LSA from LSDB */
1994 /* NB: Multiple scheduling will produce a warning message, but harmless.
1996 ospf_opaque_lsa_flush_schedule(old
);
2000 /* Send reply back to client including return code */
2001 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
2005 /* Flush self-originated opaque LSA */
2006 static int apiserver_flush_opaque_type_callback(struct ospf_lsa
*lsa
,
2007 void *p_arg
, int int_arg
)
2010 struct ospf_apiserver
*apiserv
;
2012 uint8_t opaque_type
;
2018 param
= (struct param_t
*)p_arg
;
2020 /* If LSA matches type and opaque type then delete it */
2021 if (IS_LSA_SELF(lsa
) && lsa
->data
->type
== param
->lsa_type
2022 && GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
2023 == param
->opaque_type
) {
2024 ospf_opaque_lsa_flush_schedule(lsa
);
2029 /* Delete self-originated opaque LSAs of a given opaque type. This
2030 function is called when an application unregisters a given opaque
2031 type or a connection to an application closes and all those opaque
2032 LSAs need to be flushed the LSDB. */
2033 void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver
*apiserv
,
2034 uint8_t lsa_type
, uint8_t opaque_type
)
2037 struct ospf_apiserver
*apiserv
;
2039 uint8_t opaque_type
;
2041 struct listnode
*node
, *nnode
;
2043 struct ospf_area
*area
;
2045 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
2048 /* Set parameter struct. */
2049 param
.apiserv
= apiserv
;
2050 param
.lsa_type
= lsa_type
;
2051 param
.opaque_type
= opaque_type
;
2054 struct route_node
*rn
;
2055 struct ospf_lsa
*lsa
;
2057 case OSPF_OPAQUE_LINK_LSA
:
2058 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
2059 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
2060 apiserver_flush_opaque_type_callback(
2061 lsa
, (void *)¶m
, 0);
2063 case OSPF_OPAQUE_AREA_LSA
:
2064 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
2065 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
2066 apiserver_flush_opaque_type_callback(
2067 lsa
, (void *)¶m
, 0);
2069 case OSPF_OPAQUE_AS_LSA
:
2070 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf
), rn
, lsa
)
2071 apiserver_flush_opaque_type_callback(lsa
,
2081 /* -----------------------------------------------------------
2082 * Following are callback functions to handle opaque types
2083 * -----------------------------------------------------------
2086 int ospf_apiserver_new_if(struct interface
*ifp
)
2088 struct ospf_interface
*oi
;
2090 /* For some strange reason it seems possible that we are invoked
2091 with an interface that has no name. This seems to happen during
2092 initialization. Return if this happens */
2094 if (ifp
->name
[0] == '\0') {
2095 /* interface has empty name */
2096 zlog_warn("%s: interface has no name?", __func__
);
2100 /* zlog_warn for debugging */
2101 zlog_warn("ospf_apiserver_new_if");
2102 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2105 if (ifp
->name
[0] == '\0') {
2106 /* interface has empty name */
2107 zlog_warn("%s: interface has no name?", __func__
);
2111 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2114 /* This interface is known to Zebra but not to OSPF daemon yet.
2116 zlog_warn("%s: interface %s not known to OSPFd?", __func__
,
2123 /* New interface added to OSPF, tell clients about it */
2124 if (listcount(apiserver_list
) > 0) {
2125 ospf_apiserver_clients_notify_new_if(oi
);
2130 int ospf_apiserver_del_if(struct interface
*ifp
)
2132 struct ospf_interface
*oi
;
2134 /* zlog_warn for debugging */
2135 zlog_warn("%s ifp name=%s status=%d index=%d", __func__
, ifp
->name
,
2136 ifp
->status
, ifp
->ifindex
);
2138 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2141 /* This interface is known to Zebra but not to OSPF daemon
2142 anymore. No need to tell clients about it */
2143 zlog_warn("ifp name=%s not known to OSPFd", ifp
->name
);
2147 /* Interface deleted, tell clients about it */
2148 if (listcount(apiserver_list
) > 0) {
2149 ospf_apiserver_clients_notify_del_if(oi
);
2154 void ospf_apiserver_ism_change(struct ospf_interface
*oi
, int old_state
)
2156 /* Tell clients about interface change */
2158 /* zlog_warn for debugging */
2159 zlog_warn("%s", __func__
);
2160 if (listcount(apiserver_list
) > 0) {
2161 ospf_apiserver_clients_notify_ism_change(oi
);
2164 zlog_warn("%s oi->ifp->name=%s old_state=%d oi->state=%d", __func__
,
2165 oi
->ifp
->name
, old_state
, oi
->state
);
2168 void ospf_apiserver_nsm_change(struct ospf_neighbor
*nbr
, int old_status
)
2170 /* Neighbor status changed, tell clients about it */
2171 zlog_warn("%s", __func__
);
2172 if (listcount(apiserver_list
) > 0) {
2173 ospf_apiserver_clients_notify_nsm_change(nbr
);
2177 void ospf_apiserver_show_info(struct vty
*vty
, struct json_object
*json
,
2178 struct ospf_lsa
*lsa
)
2181 struct lsa_header header
;
2182 uint8_t data
[1]; /* opaque data have variable length. This is
2186 struct opaque_lsa
*olsa
;
2189 olsa
= (struct opaque_lsa
*)lsa
->data
;
2191 if (VALID_OPAQUE_INFO_LEN(lsa
->data
))
2192 opaquelen
= ntohs(lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2196 /* Output information about opaque LSAs */
2198 json_object_string_addf(json
, "opaqueData", "%*pHXn",
2199 (int)opaquelen
, olsa
->data
);
2200 else if (vty
!= NULL
) {
2203 " Added using OSPF API: %u octets of opaque data %s\n",
2205 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2206 : "(Invalid length?)");
2207 vty_out(vty
, " Opaque data: ");
2209 for (i
= 0; i
< opaquelen
; i
++) {
2210 vty_out(vty
, "0x%x ", olsa
->data
[i
]);
2216 " Added using OSPF API: %u octets of opaque data %s",
2218 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2219 : "(Invalid length?)");
2220 zlog_debug(" Opaque data: ");
2222 for (i
= 0; i
< opaquelen
; i
++) {
2223 zlog_debug("0x%x ", olsa
->data
[i
]);
2229 /* -----------------------------------------------------------
2230 * Following are functions to notify clients about events
2231 * -----------------------------------------------------------
2234 /* Send a message to all clients. This is useful for messages
2235 that need to be notified to all clients (such as interface
2238 void ospf_apiserver_clients_notify_all(struct msg
*msg
)
2240 struct listnode
*node
, *nnode
;
2241 struct ospf_apiserver
*apiserv
;
2243 /* Send message to all clients */
2244 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
))
2245 ospf_apiserver_send_msg(apiserv
, msg
);
2248 /* An interface is now ready to accept opaque LSAs. Notify all
2249 clients that registered to use this opaque type */
2250 void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface
*oi
)
2252 struct listnode
*node
, *nnode
;
2254 struct ospf_apiserver
*apiserv
;
2258 zlog_warn("Interface has no address?");
2262 if (!ospf_apiserver_is_ready_type9(oi
)) {
2263 zlog_warn("Interface not ready for type 9?");
2267 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2268 struct listnode
*node2
, *nnode2
;
2269 struct registered_opaque_type
*r
;
2271 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2273 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
2274 msg
= new_msg_ready_notify(
2275 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
2276 oi
->address
->u
.prefix4
);
2279 "%s: new_msg_ready_notify failed",
2282 /* Cannot allocate new message. What
2284 ospf_apiserver_free(apiserv
);
2289 ospf_apiserver_send_msg(apiserv
, msg
);
2299 void ospf_apiserver_clients_notify_ready_type10(struct ospf_area
*area
)
2301 struct listnode
*node
, *nnode
;
2303 struct ospf_apiserver
*apiserv
;
2307 if (!ospf_apiserver_is_ready_type10(area
)) {
2308 zlog_warn("Area not ready for type 10?");
2312 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2313 struct listnode
*node2
, *nnode2
;
2314 struct registered_opaque_type
*r
;
2316 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2318 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
2319 msg
= new_msg_ready_notify(
2320 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
2324 "%s: new_msg_ready_nofity failed",
2327 /* Cannot allocate new message. What
2329 ospf_apiserver_free(apiserv
);
2334 ospf_apiserver_send_msg(apiserv
, msg
);
2345 void ospf_apiserver_clients_notify_ready_type11(struct ospf
*top
)
2347 struct listnode
*node
, *nnode
;
2349 struct in_addr id_null
= {.s_addr
= 0L};
2350 struct ospf_apiserver
*apiserv
;
2354 if (!ospf_apiserver_is_ready_type11(top
)) {
2355 zlog_warn("AS not ready for type 11?");
2359 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2360 struct listnode
*node2
, *nnode2
;
2361 struct registered_opaque_type
*r
;
2363 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2365 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
2366 msg
= new_msg_ready_notify(
2367 0, OSPF_OPAQUE_AS_LSA
, r
->opaque_type
,
2371 "%s: new_msg_ready_notify failed",
2374 /* Cannot allocate new message. What
2376 ospf_apiserver_free(apiserv
);
2381 ospf_apiserver_send_msg(apiserv
, msg
);
2391 void ospf_apiserver_clients_notify_new_if(struct ospf_interface
*oi
)
2395 msg
= new_msg_new_if(0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2397 ospf_apiserver_clients_notify_all(msg
);
2402 void ospf_apiserver_clients_notify_del_if(struct ospf_interface
*oi
)
2406 msg
= new_msg_del_if(0, oi
->address
->u
.prefix4
);
2408 ospf_apiserver_clients_notify_all(msg
);
2413 void ospf_apiserver_clients_notify_ism_change(struct ospf_interface
*oi
)
2416 struct in_addr ifaddr
= {.s_addr
= 0L};
2417 struct in_addr area_id
= {.s_addr
= 0L};
2423 ifaddr
= oi
->address
->u
.prefix4
;
2426 area_id
= oi
->area
->area_id
;
2429 msg
= new_msg_ism_change(0, ifaddr
, area_id
, oi
->state
);
2431 zlog_warn("%s: msg_new failed", __func__
);
2435 ospf_apiserver_clients_notify_all(msg
);
2439 void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor
*nbr
)
2442 struct in_addr ifaddr
;
2443 struct in_addr nbraddr
;
2447 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2449 nbraddr
= nbr
->address
.u
.prefix4
;
2451 msg
= new_msg_nsm_change(0, ifaddr
, nbraddr
, nbr
->router_id
,
2454 zlog_warn("%s: msg_new failed", __func__
);
2458 ospf_apiserver_clients_notify_all(msg
);
2462 static int apiserver_clients_lsa_change_notify(uint8_t msgtype
,
2463 struct ospf_lsa
*lsa
)
2466 struct listnode
*node
, *nnode
;
2467 struct ospf_apiserver
*apiserv
;
2469 /* Default area for AS-External and Opaque11 LSAs */
2470 struct in_addr area_id
= {.s_addr
= 0L};
2472 /* Default interface for non Opaque9 LSAs */
2473 struct in_addr ifaddr
= {.s_addr
= 0L};
2476 area_id
= lsa
->area
->area_id
;
2478 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2480 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2483 /* Prepare message that can be sent to clients that have a matching
2485 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2487 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2489 zlog_warn("%s: msg_new failed", __func__
);
2493 /* Now send message to all clients with a matching filter */
2494 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2495 struct lsa_filter_type
*filter
;
2500 /* Check filter for this client. */
2501 filter
= apiserv
->filter
;
2503 /* Check area IDs in case of non AS-E LSAs.
2504 * If filter has areas (num_areas > 0),
2505 * then one of the areas must match the area ID of this LSA. */
2507 i
= filter
->num_areas
;
2508 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)
2509 || (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
)) {
2514 area
= (uint32_t *)(filter
+ 1);
2516 if (*area
== area_id
.s_addr
) {
2527 /* Area match. Check LSA type. */
2528 mask
= ntohs(filter
->typemask
);
2530 if (mask
& Power2
[lsa
->data
->type
]) {
2531 /* Type also matches. Check origin. */
2532 if ((filter
->origin
== ANY_ORIGIN
)
2533 || (filter
->origin
== IS_LSA_SELF(lsa
))) {
2534 ospf_apiserver_send_msg(apiserv
, msg
);
2539 /* Free message since it is not used anymore */
2546 /* -------------------------------------------------------------
2547 * Following are hooks invoked when LSAs are updated or deleted
2548 * -------------------------------------------------------------
2552 int ospf_apiserver_lsa_update(struct ospf_lsa
*lsa
)
2555 /* Only notify this update if the LSA's age is smaller than
2556 MAXAGE. Otherwise clients would see LSA updates with max age just
2557 before they are deleted from the LSDB. LSA delete messages have
2558 MAXAGE too but should not be filtered. */
2559 if (IS_LSA_MAXAGE(lsa
))
2561 return apiserver_clients_lsa_change_notify(MSG_LSA_UPDATE_NOTIFY
, lsa
);
2564 int ospf_apiserver_lsa_delete(struct ospf_lsa
*lsa
)
2566 return apiserver_clients_lsa_change_notify(MSG_LSA_DELETE_NOTIFY
, lsa
);
2569 /* -------------------------------------------------------------
2570 * Reachable functions
2571 * -------------------------------------------------------------
2574 static inline int cmp_route_nodes(struct route_node
*orn
,
2575 struct route_node
*nrn
)
2581 else if (orn
->p
.u
.prefix4
.s_addr
< nrn
->p
.u
.prefix4
.s_addr
)
2583 else if (orn
->p
.u
.prefix4
.s_addr
> nrn
->p
.u
.prefix4
.s_addr
)
2589 void ospf_apiserver_notify_reachable(struct route_table
*ort
,
2590 struct route_table
*nrt
)
2593 struct msg_reachable_change
*areach
;
2594 struct route_node
*orn
, *nrn
;
2595 const uint insz
= sizeof(struct in_addr
);
2596 struct in_addr
*abuf
= NULL
, *dbuf
= NULL
;
2597 struct in_addr
*a
= NULL
, *d
= NULL
;
2602 if (IS_DEBUG_OSPF_CLIENT_API
)
2603 zlog_debug("%s: no routing tables", __func__
);
2606 if (nrt
&& nrt
->count
)
2607 a
= abuf
= XCALLOC(MTYPE_APISERVER
, insz
* nrt
->count
);
2608 if (ort
&& ort
->count
)
2609 d
= dbuf
= XCALLOC(MTYPE_APISERVER
, insz
* ort
->count
);
2611 /* walk both tables */
2612 orn
= ort
? route_top(ort
) : NULL
;
2613 nrn
= nrt
? route_top(nrt
) : NULL
;
2614 while (orn
|| nrn
) {
2615 if (orn
&& !listhead((struct list
*)orn
->info
)) {
2616 orn
= route_next(orn
);
2619 if (nrn
&& !listhead((struct list
*)nrn
->info
)) {
2620 nrn
= route_next(nrn
);
2623 cmp
= cmp_route_nodes(orn
, nrn
);
2625 /* if old == new advance old and new */
2626 if (IS_DEBUG_OSPF_CLIENT_API
)
2627 zlog_debug("keeping router id: %pI4",
2629 orn
= route_next(orn
);
2630 nrn
= route_next(nrn
);
2631 } else if (cmp
< 0) {
2632 assert(d
!= NULL
); /* Silence SA warning */
2634 /* if old < new, delete old, advance old */
2635 *d
++ = orn
->p
.u
.prefix4
;
2636 if (IS_DEBUG_OSPF_CLIENT_API
)
2637 zlog_debug("removing router id: %pI4",
2639 orn
= route_next(orn
);
2641 assert(a
!= NULL
); /* Silence SA warning */
2643 /* if new < old, add new, advance new */
2644 *a
++ = nrn
->p
.u
.prefix4
;
2645 if (IS_DEBUG_OSPF_CLIENT_API
)
2646 zlog_debug("adding router id: %pI4",
2648 nrn
= route_next(nrn
);
2652 nadd
= abuf
? (a
- abuf
) : 0;
2653 nremove
= dbuf
? (d
- dbuf
) : 0;
2657 while (nadd
+ nremove
) {
2658 msg
= new_msg_reachable_change(0, nadd
, a
, nremove
, d
);
2659 areach
= (struct msg_reachable_change
*)STREAM_DATA(msg
->s
);
2661 a
+= ntohs(areach
->nadd
);
2662 nadd
= nadd
- ntohs(areach
->nadd
);
2664 d
+= ntohs(areach
->nremove
);
2665 nremove
= nremove
- ntohs(areach
->nremove
);
2667 if (IS_DEBUG_OSPF_CLIENT_API
)
2668 zlog_debug("%s: adding %d removing %d", __func__
,
2669 ntohs(areach
->nadd
), ntohs(areach
->nremove
));
2670 ospf_apiserver_clients_notify_all(msg
);
2674 XFREE(MTYPE_APISERVER
, abuf
);
2676 XFREE(MTYPE_APISERVER
, dbuf
);
2680 void ospf_apiserver_clients_notify_router_id_change(struct in_addr router_id
)
2684 msg
= new_msg_router_id_change(0, router_id
);
2686 zlog_warn("%s: new_msg_router_id_change failed", __func__
);
2690 ospf_apiserver_clients_notify_all(msg
);
2695 #endif /* SUPPORT_OSPF_API */