2 * Server side of OSPF API.
3 * Copyright (C) 2001, 2002 Ralph Keller
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #ifdef SUPPORT_OSPF_API
37 #include "sockunion.h" /* for inet_aton() */
40 #include <sys/types.h>
42 #include "ospfd/ospfd.h" /* for "struct thread_master" */
43 #include "ospfd/ospf_interface.h"
44 #include "ospfd/ospf_ism.h"
45 #include "ospfd/ospf_asbr.h"
46 #include "ospfd/ospf_lsa.h"
47 #include "ospfd/ospf_lsdb.h"
48 #include "ospfd/ospf_neighbor.h"
49 #include "ospfd/ospf_nsm.h"
50 #include "ospfd/ospf_flood.h"
51 #include "ospfd/ospf_packet.h"
52 #include "ospfd/ospf_spf.h"
53 #include "ospfd/ospf_dump.h"
54 #include "ospfd/ospf_route.h"
55 #include "ospfd/ospf_ase.h"
56 #include "ospfd/ospf_zebra.h"
57 #include "ospfd/ospf_errors.h"
59 #include "ospfd/ospf_api.h"
60 #include "ospfd/ospf_apiserver.h"
62 /* This is an implementation of an API to the OSPF daemon that allows
63 * external applications to access the OSPF daemon through socket
64 * connections. The application can use this API to inject its own
65 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
66 * daemons then receive these LSAs and inform applications through the
67 * API by sending a corresponding message. The application can also
68 * register to receive all LSA types (in addition to opaque types) and
69 * use this information to reconstruct the OSPF's LSDB. The OSPF
70 * daemon supports multiple applications concurrently. */
72 /* List of all active connections. */
73 struct list
*apiserver_list
;
75 /* -----------------------------------------------------------
76 * Functions to lookup interfaces
77 * -----------------------------------------------------------
80 struct ospf_interface
*ospf_apiserver_if_lookup_by_addr(struct in_addr address
)
82 struct listnode
*node
, *nnode
;
83 struct ospf_interface
*oi
;
84 struct ospf
*ospf
= NULL
;
86 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
90 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
91 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
92 if (IPV4_ADDR_SAME(&address
, &oi
->address
->u
.prefix4
))
98 struct ospf_interface
*ospf_apiserver_if_lookup_by_ifp(struct interface
*ifp
)
100 struct listnode
*node
, *nnode
;
101 struct ospf_interface
*oi
;
102 struct ospf
*ospf
= NULL
;
104 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
108 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
115 /* -----------------------------------------------------------
117 * -----------------------------------------------------------
120 unsigned short ospf_apiserver_getport(void)
122 struct servent
*sp
= getservbyname("ospfapi", "tcp");
124 return sp
? ntohs(sp
->s_port
) : OSPF_API_SYNC_PORT
;
127 /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
128 int ospf_apiserver_init(void)
133 /* Create new socket for synchronous messages. */
134 fd
= ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET
);
139 /* Schedule new thread that handles accepted connections. */
140 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, fd
, NULL
);
142 /* Initialize list that keeps track of all connections. */
143 apiserver_list
= list_new();
145 /* Register opaque-independent call back functions. These functions
146 are invoked on ISM, NSM changes and LSA update and LSA deletes */
147 rc
= ospf_register_opaque_functab(
148 0 /* all LSAs */, 0 /* all opaque types */,
149 ospf_apiserver_new_if
, ospf_apiserver_del_if
,
150 ospf_apiserver_ism_change
, ospf_apiserver_nsm_change
, NULL
,
151 NULL
, NULL
, NULL
, /* ospf_apiserver_show_info */
152 NULL
, /* originator_func */
153 NULL
, /* ospf_apiserver_lsa_refresher */
154 ospf_apiserver_lsa_update
, ospf_apiserver_lsa_delete
);
157 EC_OSPF_OPAQUE_REGISTRATION
,
158 "ospf_apiserver_init: Failed to register opaque type [0/0]");
167 /* Terminate OSPF API module. */
168 void ospf_apiserver_term(void)
170 struct ospf_apiserver
*apiserv
;
172 /* Unregister wildcard [0/0] type */
173 ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */);
176 * Free all client instances. ospf_apiserver_free removes the node
177 * from the list, so we examine the head of the list anew each time.
179 while (apiserver_list
180 && (apiserv
= listgetdata(listhead(apiserver_list
))) != NULL
)
181 ospf_apiserver_free(apiserv
);
183 /* Free client list itself */
185 list_delete(&apiserver_list
);
187 /* Free wildcard list */
191 static struct ospf_apiserver
*lookup_apiserver(uint8_t lsa_type
,
194 struct listnode
*n1
, *n2
;
195 struct registered_opaque_type
*r
;
196 struct ospf_apiserver
*apiserv
, *found
= NULL
;
198 /* XXX: this approaches O(n**2) */
199 for (ALL_LIST_ELEMENTS_RO(apiserver_list
, n1
, apiserv
)) {
200 for (ALL_LIST_ELEMENTS_RO(apiserv
->opaque_types
, n2
, r
))
201 if (r
->lsa_type
== lsa_type
202 && r
->opaque_type
== opaque_type
) {
211 static struct ospf_apiserver
*lookup_apiserver_by_lsa(struct ospf_lsa
*lsa
)
213 struct lsa_header
*lsah
= lsa
->data
;
214 struct ospf_apiserver
*found
= NULL
;
216 if (IS_OPAQUE_LSA(lsah
->type
)) {
217 found
= lookup_apiserver(
218 lsah
->type
, GET_OPAQUE_TYPE(ntohl(lsah
->id
.s_addr
)));
223 /* -----------------------------------------------------------
224 * Following are functions to manage client connections.
225 * -----------------------------------------------------------
227 static int ospf_apiserver_new_lsa_hook(struct ospf_lsa
*lsa
)
229 if (IS_DEBUG_OSPF_EVENT
)
230 zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
231 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
235 static int ospf_apiserver_del_lsa_hook(struct ospf_lsa
*lsa
)
237 if (IS_DEBUG_OSPF_EVENT
)
238 zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
239 (void *)lsa
, dump_lsa_key(lsa
), lsa
->lsdb
->total
);
243 /* Allocate new connection structure. */
244 struct ospf_apiserver
*ospf_apiserver_new(int fd_sync
, int fd_async
)
246 struct ospf_apiserver
*new =
247 XMALLOC(MTYPE_OSPF_APISERVER
, sizeof(struct ospf_apiserver
));
249 new->filter
= XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER
,
250 sizeof(struct lsa_filter_type
));
252 new->fd_sync
= fd_sync
;
253 new->fd_async
= fd_async
;
255 /* list of registered opaque types that application uses */
256 new->opaque_types
= list_new();
258 /* Initialize temporary strage for LSA instances to be refreshed. */
259 memset(&new->reserve
, 0, sizeof(struct ospf_lsdb
));
260 ospf_lsdb_init(&new->reserve
);
262 new->reserve
.new_lsa_hook
= ospf_apiserver_new_lsa_hook
; /* debug */
263 new->reserve
.del_lsa_hook
= ospf_apiserver_del_lsa_hook
; /* debug */
265 new->out_sync_fifo
= msg_fifo_new();
266 new->out_async_fifo
= msg_fifo_new();
267 new->t_sync_read
= NULL
;
268 #ifdef USE_ASYNC_READ
269 new->t_async_read
= NULL
;
270 #endif /* USE_ASYNC_READ */
271 new->t_sync_write
= NULL
;
272 new->t_async_write
= NULL
;
274 new->filter
->typemask
= 0; /* filter all LSAs */
275 new->filter
->origin
= ANY_ORIGIN
;
276 new->filter
->num_areas
= 0;
281 void ospf_apiserver_event(enum ospf_apiserver_event event
, int fd
,
282 struct ospf_apiserver
*apiserv
)
285 case OSPF_APISERVER_ACCEPT
:
286 (void)thread_add_read(master
, ospf_apiserver_accept
, apiserv
,
289 case OSPF_APISERVER_SYNC_READ
:
290 apiserv
->t_sync_read
= NULL
;
291 thread_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
292 &apiserv
->t_sync_read
);
294 #ifdef USE_ASYNC_READ
295 case OSPF_APISERVER_ASYNC_READ
:
296 apiserv
->t_async_read
= NULL
;
297 thread_add_read(master
, ospf_apiserver_read
, apiserv
, fd
,
298 &apiserv
->t_async_read
);
300 #endif /* USE_ASYNC_READ */
301 case OSPF_APISERVER_SYNC_WRITE
:
302 thread_add_write(master
, ospf_apiserver_sync_write
, apiserv
, fd
,
303 &apiserv
->t_sync_write
);
305 case OSPF_APISERVER_ASYNC_WRITE
:
306 thread_add_write(master
, ospf_apiserver_async_write
, apiserv
,
307 fd
, &apiserv
->t_async_write
);
312 /* Free instance. First unregister all opaque types used by
313 application, flush opaque LSAs injected by application
314 from network and close connection. */
315 void ospf_apiserver_free(struct ospf_apiserver
*apiserv
)
317 struct listnode
*node
;
319 /* Cancel read and write threads. */
320 thread_cancel(&apiserv
->t_sync_read
);
321 #ifdef USE_ASYNC_READ
322 thread_cancel(&apiserv
->t_async_read
);
323 #endif /* USE_ASYNC_READ */
324 thread_cancel(&apiserv
->t_sync_write
);
325 thread_cancel(&apiserv
->t_async_write
);
327 /* Unregister all opaque types that application registered
328 and flush opaque LSAs if still in LSDB. */
330 while ((node
= listhead(apiserv
->opaque_types
)) != NULL
) {
331 struct registered_opaque_type
*regtype
= listgetdata(node
);
333 ospf_apiserver_unregister_opaque_type(
334 apiserv
, regtype
->lsa_type
, regtype
->opaque_type
);
337 /* Close connections to OSPFd. */
338 if (apiserv
->fd_sync
> 0) {
339 close(apiserv
->fd_sync
);
342 if (apiserv
->fd_async
> 0) {
343 close(apiserv
->fd_async
);
347 msg_fifo_free(apiserv
->out_sync_fifo
);
348 msg_fifo_free(apiserv
->out_async_fifo
);
350 /* Clear temporary strage for LSA instances to be refreshed. */
351 ospf_lsdb_delete_all(&apiserv
->reserve
);
352 ospf_lsdb_cleanup(&apiserv
->reserve
);
354 /* Remove from the list of active clients. */
355 listnode_delete(apiserver_list
, apiserv
);
357 if (IS_DEBUG_OSPF_EVENT
)
358 zlog_debug("API: Delete apiserv(%p), total#(%d)",
359 (void *)apiserv
, apiserver_list
->count
);
361 /* And free instance. */
362 XFREE(MTYPE_OSPF_APISERVER
, apiserv
);
365 void ospf_apiserver_read(struct thread
*thread
)
367 struct ospf_apiserver
*apiserv
;
370 enum ospf_apiserver_event event
;
372 apiserv
= THREAD_ARG(thread
);
373 fd
= THREAD_FD(thread
);
375 if (fd
== apiserv
->fd_sync
) {
376 event
= OSPF_APISERVER_SYNC_READ
;
377 apiserv
->t_sync_read
= NULL
;
379 if (IS_DEBUG_OSPF_EVENT
)
380 zlog_debug("API: ospf_apiserver_read: Peer: %pI4/%u",
381 &apiserv
->peer_sync
.sin_addr
,
382 ntohs(apiserv
->peer_sync
.sin_port
));
384 #ifdef USE_ASYNC_READ
385 else if (fd
== apiserv
->fd_async
) {
386 event
= OSPF_APISERVER_ASYNC_READ
;
387 apiserv
->t_async_read
= NULL
;
389 if (IS_DEBUG_OSPF_EVENT
)
390 zlog_debug("API: ospf_apiserver_read: Peer: %pI4/%u",
391 &apiserv
->peer_async
.sin_addr
,
392 ntohs(apiserv
->peer_async
.sin_port
));
394 #endif /* USE_ASYNC_READ */
396 zlog_warn("ospf_apiserver_read: Unknown fd(%d)", fd
);
397 ospf_apiserver_free(apiserv
);
401 /* Read message from fd. */
405 "ospf_apiserver_read: read failed on fd=%d, closing connection",
408 /* Perform cleanup. */
409 ospf_apiserver_free(apiserv
);
413 if (IS_DEBUG_OSPF_EVENT
)
416 /* Dispatch to corresponding message handler. */
417 ospf_apiserver_handle_msg(apiserv
, msg
);
419 /* Prepare for next message, add read thread. */
420 ospf_apiserver_event(event
, fd
, apiserv
);
425 void ospf_apiserver_sync_write(struct thread
*thread
)
427 struct ospf_apiserver
*apiserv
;
432 apiserv
= THREAD_ARG(thread
);
434 fd
= THREAD_FD(thread
);
436 apiserv
->t_sync_write
= NULL
;
439 if (fd
!= apiserv
->fd_sync
) {
440 zlog_warn("ospf_apiserver_sync_write: Unknown fd=%d", fd
);
444 if (IS_DEBUG_OSPF_EVENT
)
445 zlog_debug("API: ospf_apiserver_sync_write: Peer: %pI4/%u",
446 &apiserv
->peer_sync
.sin_addr
,
447 ntohs(apiserv
->peer_sync
.sin_port
));
449 /* Check whether there is really a message in the fifo. */
450 msg
= msg_fifo_pop(apiserv
->out_sync_fifo
);
453 "API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
457 if (IS_DEBUG_OSPF_EVENT
)
460 rc
= msg_write(fd
, msg
);
462 /* Once a message is dequeued, it should be freed anyway. */
466 zlog_warn("ospf_apiserver_sync_write: write failed on fd=%d",
472 /* If more messages are in sync message fifo, schedule write thread. */
473 if (msg_fifo_head(apiserv
->out_sync_fifo
)) {
474 ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE
,
475 apiserv
->fd_sync
, apiserv
);
481 /* Perform cleanup and disconnect with peer */
482 ospf_apiserver_free(apiserv
);
487 void ospf_apiserver_async_write(struct thread
*thread
)
489 struct ospf_apiserver
*apiserv
;
494 apiserv
= THREAD_ARG(thread
);
496 fd
= THREAD_FD(thread
);
498 apiserv
->t_async_write
= NULL
;
501 if (fd
!= apiserv
->fd_async
) {
502 zlog_warn("ospf_apiserver_async_write: Unknown fd=%d", fd
);
506 if (IS_DEBUG_OSPF_EVENT
)
507 zlog_debug("API: ospf_apiserver_async_write: Peer: %pI4/%u",
508 &apiserv
->peer_async
.sin_addr
,
509 ntohs(apiserv
->peer_async
.sin_port
));
511 /* Check whether there is really a message in the fifo. */
512 msg
= msg_fifo_pop(apiserv
->out_async_fifo
);
515 "API: ospf_apiserver_async_write: No message in Async-FIFO?");
519 if (IS_DEBUG_OSPF_EVENT
)
522 rc
= msg_write(fd
, msg
);
524 /* Once a message is dequeued, it should be freed anyway. */
528 zlog_warn("ospf_apiserver_async_write: write failed on fd=%d",
534 /* If more messages are in async message fifo, schedule write thread. */
535 if (msg_fifo_head(apiserv
->out_async_fifo
)) {
536 ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE
,
537 apiserv
->fd_async
, apiserv
);
543 /* Perform cleanup and disconnect with peer */
544 ospf_apiserver_free(apiserv
);
549 int ospf_apiserver_serv_sock_family(unsigned short port
, int family
)
555 memset(&su
, 0, sizeof(union sockunion
));
556 su
.sa
.sa_family
= family
;
558 /* Make new socket */
559 accept_sock
= sockunion_stream_socket(&su
);
563 /* This is a server, so reuse address and port */
564 sockopt_reuseaddr(accept_sock
);
565 sockopt_reuseport(accept_sock
);
567 /* Bind socket to address and given port. */
568 rc
= sockunion_bind(accept_sock
, &su
, port
, NULL
);
570 close(accept_sock
); /* Close socket */
574 /* Listen socket under queue length 3. */
575 rc
= listen(accept_sock
, 3);
577 zlog_warn("ospf_apiserver_serv_sock_family: listen: %s",
578 safe_strerror(errno
));
579 close(accept_sock
); /* Close socket */
586 /* Accept connection request from external applications. For each
587 accepted connection allocate own connection instance. */
588 void ospf_apiserver_accept(struct thread
*thread
)
594 struct ospf_apiserver
*apiserv
;
595 struct sockaddr_in peer_async
;
596 struct sockaddr_in peer_sync
;
597 unsigned int peerlen
;
600 /* THREAD_ARG (thread) is NULL */
601 accept_sock
= THREAD_FD(thread
);
603 /* Keep hearing on socket for further connections. */
604 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
606 memset(&su
, 0, sizeof(union sockunion
));
607 /* Accept connection for synchronous messages */
608 new_sync_sock
= sockunion_accept(accept_sock
, &su
);
609 if (new_sync_sock
< 0) {
610 zlog_warn("ospf_apiserver_accept: accept: %s",
611 safe_strerror(errno
));
615 /* Get port address and port number of peer to make reverse connection.
616 The reverse channel uses the port number of the peer port+1. */
618 memset(&peer_sync
, 0, sizeof(peer_sync
));
619 peerlen
= sizeof(struct sockaddr_in
);
621 ret
= getpeername(new_sync_sock
, (struct sockaddr
*)&peer_sync
,
624 zlog_warn("ospf_apiserver_accept: getpeername: %s",
625 safe_strerror(errno
));
626 close(new_sync_sock
);
630 if (IS_DEBUG_OSPF_EVENT
)
631 zlog_debug("API: ospf_apiserver_accept: New peer: %pI4/%u",
633 ntohs(peer_sync
.sin_port
));
635 /* Create new socket for asynchronous messages. */
636 peer_async
= peer_sync
;
637 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
639 /* Check if remote port number to make reverse connection is valid one.
641 if (ntohs(peer_async
.sin_port
) == ospf_apiserver_getport()) {
643 "API: ospf_apiserver_accept: Peer(%pI4/%u): Invalid async port number?",
644 &peer_async
.sin_addr
,
645 ntohs(peer_async
.sin_port
));
646 close(new_sync_sock
);
650 new_async_sock
= socket(AF_INET
, SOCK_STREAM
, 0);
651 if (new_async_sock
< 0) {
652 zlog_warn("ospf_apiserver_accept: socket: %s",
653 safe_strerror(errno
));
654 close(new_sync_sock
);
658 ret
= connect(new_async_sock
, (struct sockaddr
*)&peer_async
,
659 sizeof(struct sockaddr_in
));
662 zlog_warn("ospf_apiserver_accept: connect: %s",
663 safe_strerror(errno
));
664 close(new_sync_sock
);
665 close(new_async_sock
);
669 #ifdef USE_ASYNC_READ
670 #else /* USE_ASYNC_READ */
671 /* Make the asynchronous channel write-only. */
672 ret
= shutdown(new_async_sock
, SHUT_RD
);
674 zlog_warn("ospf_apiserver_accept: shutdown: %s",
675 safe_strerror(errno
));
676 close(new_sync_sock
);
677 close(new_async_sock
);
680 #endif /* USE_ASYNC_READ */
682 /* Allocate new server-side connection structure */
683 apiserv
= ospf_apiserver_new(new_sync_sock
, new_async_sock
);
685 /* Add to active connection list */
686 listnode_add(apiserver_list
, apiserv
);
687 apiserv
->peer_sync
= peer_sync
;
688 apiserv
->peer_async
= peer_async
;
690 /* And add read threads for new connection */
691 ospf_apiserver_event(OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
692 #ifdef USE_ASYNC_READ
693 ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ
, new_async_sock
,
695 #endif /* USE_ASYNC_READ */
697 if (IS_DEBUG_OSPF_EVENT
)
698 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv
,
699 apiserver_list
->count
);
703 /* -----------------------------------------------------------
704 * Send reply with return code to client application
705 * -----------------------------------------------------------
708 static int ospf_apiserver_send_msg(struct ospf_apiserver
*apiserv
,
711 struct msg_fifo
*fifo
;
713 enum ospf_apiserver_event event
;
716 switch (msg
->hdr
.msgtype
) {
718 fifo
= apiserv
->out_sync_fifo
;
719 fd
= apiserv
->fd_sync
;
720 event
= OSPF_APISERVER_SYNC_WRITE
;
722 case MSG_READY_NOTIFY
:
723 case MSG_LSA_UPDATE_NOTIFY
:
724 case MSG_LSA_DELETE_NOTIFY
:
729 fifo
= apiserv
->out_async_fifo
;
730 fd
= apiserv
->fd_async
;
731 event
= OSPF_APISERVER_ASYNC_WRITE
;
734 zlog_warn("ospf_apiserver_send_msg: Unknown message type %d",
739 /* Make a copy of the message and put in the fifo. Once the fifo
740 gets drained by the write thread, the message will be freed. */
741 /* NB: Given "msg" is untouched in this function. */
744 /* Enqueue message into corresponding fifo queue */
745 msg_fifo_push(fifo
, msg2
);
747 /* Schedule write thread */
748 ospf_apiserver_event(event
, fd
, apiserv
);
752 int ospf_apiserver_send_reply(struct ospf_apiserver
*apiserv
, uint32_t seqnr
,
755 struct msg
*msg
= new_msg_reply(seqnr
, rc
);
759 zlog_warn("ospf_apiserver_send_reply: msg_new failed");
761 /* Cannot allocate new message. What should we do? */
762 ospf_apiserver_free(apiserv
);
767 ret
= ospf_apiserver_send_msg(apiserv
, msg
);
773 /* -----------------------------------------------------------
774 * Generic message dispatching handler function
775 * -----------------------------------------------------------
778 int ospf_apiserver_handle_msg(struct ospf_apiserver
*apiserv
, struct msg
*msg
)
782 /* Call corresponding message handler function. */
783 switch (msg
->hdr
.msgtype
) {
784 case MSG_REGISTER_OPAQUETYPE
:
785 rc
= ospf_apiserver_handle_register_opaque_type(apiserv
, msg
);
787 case MSG_UNREGISTER_OPAQUETYPE
:
788 rc
= ospf_apiserver_handle_unregister_opaque_type(apiserv
, msg
);
790 case MSG_REGISTER_EVENT
:
791 rc
= ospf_apiserver_handle_register_event(apiserv
, msg
);
794 rc
= ospf_apiserver_handle_sync_lsdb(apiserv
, msg
);
796 case MSG_ORIGINATE_REQUEST
:
797 rc
= ospf_apiserver_handle_originate_request(apiserv
, msg
);
799 case MSG_DELETE_REQUEST
:
800 rc
= ospf_apiserver_handle_delete_request(apiserv
, msg
);
803 zlog_warn("ospf_apiserver_handle_msg: Unknown message type: %d",
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("ospf_apiserver_register_opaque_type: lsa_type(%d)",
836 return OSPF_API_ILLEGALLSATYPE
;
840 /* Register opaque function table */
841 /* NB: Duplicated registration will be detected inside the function. */
842 rc
= ospf_register_opaque_functab(
843 lsa_type
, opaque_type
, NULL
, /* ospf_apiserver_new_if */
844 NULL
, /* ospf_apiserver_del_if */
845 NULL
, /* ospf_apiserver_ism_change */
846 NULL
, /* ospf_apiserver_nsm_change */
847 NULL
, NULL
, NULL
, ospf_apiserver_show_info
, originator_func
,
848 ospf_apiserver_lsa_refresher
,
849 NULL
, /* ospf_apiserver_lsa_update */
850 NULL
/* ospf_apiserver_lsa_delete */);
853 flog_warn(EC_OSPF_OPAQUE_REGISTRATION
,
854 "Failed to register opaque type [%d/%d]", lsa_type
,
856 return OSPF_API_OPAQUETYPEINUSE
;
859 /* Remember the opaque type that application registers so when
860 connection shuts down, we can flush all LSAs of this opaque
863 regtype
= XCALLOC(MTYPE_OSPF_APISERVER
,
864 sizeof(struct registered_opaque_type
));
865 regtype
->lsa_type
= lsa_type
;
866 regtype
->opaque_type
= opaque_type
;
868 /* Add to list of registered opaque types */
869 listnode_add(apiserv
->opaque_types
, regtype
);
871 if (IS_DEBUG_OSPF_EVENT
)
873 "API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)",
874 lsa_type
, opaque_type
, (void *)apiserv
,
875 listcount(apiserv
->opaque_types
));
880 int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
881 uint8_t lsa_type
, uint8_t opaque_type
)
883 struct listnode
*node
, *nnode
;
884 struct registered_opaque_type
*regtype
;
886 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
887 /* Check if we really registered this opaque type */
888 if (regtype
->lsa_type
== lsa_type
889 && regtype
->opaque_type
== opaque_type
) {
891 /* Yes, we registered this opaque type. Flush
892 all existing opaque LSAs of this type */
894 ospf_apiserver_flush_opaque_lsa(apiserv
, lsa_type
,
896 ospf_delete_opaque_functab(lsa_type
, opaque_type
);
898 /* Remove from list of registered opaque types */
899 listnode_delete(apiserv
->opaque_types
, 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
);
1007 "apiserver_notify_ready_type9: 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
,
1056 "apiserver_notify_ready_type10: 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
);
1099 "apiserver_notify_ready_type11: msg_new failed");
1101 /* Cannot allocate new message. What should we
1103 ospf_apiserver_free(apiserv
);
1107 ospf_apiserver_send_msg(apiserv
, msg
);
1116 int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
1119 struct msg_unregister_opaque_type
*umsg
;
1124 /* Extract parameters from unregister opaque type message */
1125 umsg
= (struct msg_unregister_opaque_type
*)STREAM_DATA(msg
->s
);
1127 ltype
= umsg
->lsatype
;
1128 otype
= umsg
->opaquetype
;
1130 rc
= ospf_apiserver_unregister_opaque_type(apiserv
, ltype
, otype
);
1132 /* Send a reply back to client including return code */
1133 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1139 /* -----------------------------------------------------------
1140 * Following are functions for event (filter) registration.
1141 * -----------------------------------------------------------
1143 int ospf_apiserver_handle_register_event(struct ospf_apiserver
*apiserv
,
1146 struct msg_register_event
*rmsg
;
1151 rmsg
= (struct msg_register_event
*)STREAM_DATA(msg
->s
);
1153 /* Get request sequence number */
1154 seqnum
= msg_get_seq(msg
);
1156 /* Free existing filter in apiserv. */
1157 XFREE(MTYPE_OSPF_APISERVER_MSGFILTER
, apiserv
->filter
);
1158 /* Alloc new space for filter. */
1159 size
= ntohs(msg
->hdr
.msglen
);
1160 if (size
< OSPF_MAX_LSA_SIZE
) {
1162 apiserv
->filter
= XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER
, size
);
1165 memcpy(apiserv
->filter
, &rmsg
->filter
, size
);
1168 rc
= OSPF_API_NOMEMORY
;
1170 /* Send a reply back to client with return code */
1171 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1176 /* -----------------------------------------------------------
1177 * Following are functions for LSDB synchronization.
1178 * -----------------------------------------------------------
1181 static int apiserver_sync_callback(struct ospf_lsa
*lsa
, void *p_arg
,
1184 struct ospf_apiserver
*apiserv
;
1188 struct ospf_apiserver
*apiserv
;
1189 struct lsa_filter_type
*filter
;
1197 param
= (struct param_t
*)p_arg
;
1198 apiserv
= param
->apiserv
;
1199 seqnum
= (uint32_t)int_arg
;
1201 /* Check origin in filter. */
1202 if ((param
->filter
->origin
== ANY_ORIGIN
)
1203 || (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
))) {
1205 /* Default area for AS-External and Opaque11 LSAs */
1206 struct in_addr area_id
= {.s_addr
= 0L};
1208 /* Default interface for non Opaque9 LSAs */
1209 struct in_addr ifaddr
= {.s_addr
= 0L};
1212 area_id
= lsa
->area
->area_id
;
1214 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
1215 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1218 msg
= new_msg_lsa_change_notify(
1219 MSG_LSA_UPDATE_NOTIFY
, seqnum
, ifaddr
, area_id
,
1220 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1223 "apiserver_sync_callback: new_msg_update failed");
1225 /* Cannot allocate new message. What should we do? */
1226 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1234 ospf_apiserver_send_msg(apiserv
, msg
);
1243 int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver
*apiserv
,
1246 struct listnode
*node
, *nnode
;
1249 struct msg_sync_lsdb
*smsg
;
1250 struct ospf_apiserver_param_t
{
1251 struct ospf_apiserver
*apiserv
;
1252 struct lsa_filter_type
*filter
;
1255 struct route_node
*rn
;
1256 struct ospf_lsa
*lsa
;
1258 struct ospf_area
*area
;
1260 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1262 /* Get request sequence number */
1263 seqnum
= msg_get_seq(msg
);
1265 smsg
= (struct msg_sync_lsdb
*)STREAM_DATA(msg
->s
);
1267 /* Set parameter struct. */
1268 param
.apiserv
= apiserv
;
1269 param
.filter
= &smsg
->filter
;
1271 /* Remember mask. */
1272 mask
= ntohs(smsg
->filter
.typemask
);
1274 /* Iterate over all areas. */
1275 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1277 uint32_t *area_id
= NULL
;
1279 /* Compare area_id with area_ids in sync request. */
1280 if ((i
= smsg
->filter
.num_areas
) > 0) {
1281 /* Let area_id point to the list of area IDs,
1282 * which is at the end of smsg->filter. */
1283 area_id
= (uint32_t *)(&smsg
->filter
+ 1);
1285 if (*area_id
== area
->area_id
.s_addr
) {
1295 /* If area was found, then i>0 here. */
1297 /* Check msg type. */
1298 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1299 LSDB_LOOP (ROUTER_LSDB(area
), rn
, lsa
)
1300 apiserver_sync_callback(
1301 lsa
, (void *)¶m
, seqnum
);
1302 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1303 LSDB_LOOP (NETWORK_LSDB(area
), rn
, lsa
)
1304 apiserver_sync_callback(
1305 lsa
, (void *)¶m
, seqnum
);
1306 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1307 LSDB_LOOP (SUMMARY_LSDB(area
), rn
, lsa
)
1308 apiserver_sync_callback(
1309 lsa
, (void *)¶m
, seqnum
);
1310 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1311 LSDB_LOOP (ASBR_SUMMARY_LSDB(area
), rn
, lsa
)
1312 apiserver_sync_callback(
1313 lsa
, (void *)¶m
, seqnum
);
1314 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1315 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1316 apiserver_sync_callback(
1317 lsa
, (void *)¶m
, seqnum
);
1318 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1319 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1320 apiserver_sync_callback(
1321 lsa
, (void *)¶m
, seqnum
);
1325 /* For AS-external LSAs */
1327 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1328 LSDB_LOOP (EXTERNAL_LSDB(ospf
), rn
, lsa
)
1329 apiserver_sync_callback(lsa
, (void *)¶m
,
1333 /* For AS-external opaque LSAs */
1335 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1336 LSDB_LOOP (OPAQUE_AS_LSDB(ospf
), rn
, lsa
)
1337 apiserver_sync_callback(lsa
, (void *)¶m
,
1341 /* Send a reply back to client with return code */
1342 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1347 /* -----------------------------------------------------------
1348 * Following are functions to originate or update LSA
1349 * from an application.
1350 * -----------------------------------------------------------
1353 /* Create a new internal opaque LSA by taking prototype and filling in
1354 missing fields such as age, sequence number, advertising router,
1355 checksum and so on. The interface parameter is used for type 9
1356 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1359 struct ospf_lsa
*ospf_apiserver_opaque_lsa_new(struct ospf_area
*area
,
1360 struct ospf_interface
*oi
,
1361 struct lsa_header
*protolsa
)
1364 struct lsa_header
*newlsa
;
1365 struct ospf_lsa
*new = NULL
;
1366 uint8_t options
= 0x0;
1374 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1378 /* Create a stream for internal opaque LSA */
1379 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
1380 zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
1384 newlsa
= (struct lsa_header
*)STREAM_DATA(s
);
1386 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1387 have to set options? */
1390 options
= LSA_OPTIONS_GET(area
);
1391 options
|= LSA_OPTIONS_NSSA_GET(area
);
1394 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1396 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1397 zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
1398 protolsa
->type
, &protolsa
->id
);
1401 /* Set opaque-LSA header fields. */
1402 lsa_header_set(s
, options
, protolsa
->type
, protolsa
->id
,
1405 /* Set opaque-LSA body fields. */
1406 stream_put(s
, ((uint8_t *)protolsa
) + sizeof(struct lsa_header
),
1407 ntohs(protolsa
->length
) - sizeof(struct lsa_header
));
1409 /* Determine length of LSA. */
1410 length
= stream_get_endp(s
);
1411 newlsa
->length
= htons(length
);
1413 /* Create OSPF LSA. */
1414 new = ospf_lsa_new_and_data(length
);
1418 new->vrf_id
= ospf
->vrf_id
;
1420 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1421 memcpy(new->data
, newlsa
, length
);
1428 int ospf_apiserver_is_ready_type9(struct ospf_interface
*oi
)
1430 /* Type 9 opaque LSA can be originated if there is at least one
1431 active opaque-capable neighbor attached to the outgoing
1434 return (ospf_nbr_count_opaque_capable(oi
) > 0);
1437 int ospf_apiserver_is_ready_type10(struct ospf_area
*area
)
1439 /* Type 10 opaque LSA can be originated if there is at least one
1440 interface belonging to the area that has an active opaque-capable
1442 struct listnode
*node
, *nnode
;
1443 struct ospf_interface
*oi
;
1445 for (ALL_LIST_ELEMENTS(area
->oiflist
, node
, nnode
, oi
))
1446 /* Is there an active neighbor attached to this interface? */
1447 if (ospf_apiserver_is_ready_type9(oi
))
1450 /* No active neighbor in area */
1454 int ospf_apiserver_is_ready_type11(struct ospf
*ospf
)
1456 /* Type 11 opaque LSA can be originated if there is at least one
1458 that has an active opaque-capable neighbor. */
1459 struct listnode
*node
, *nnode
;
1460 struct ospf_interface
*oi
;
1462 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
1463 /* Is there an active neighbor attached to this interface? */
1464 if (ospf_apiserver_is_ready_type9(oi
))
1467 /* No active neighbor at all */
1472 int ospf_apiserver_handle_originate_request(struct ospf_apiserver
*apiserv
,
1475 struct msg_originate_request
*omsg
;
1476 struct lsa_header
*data
;
1477 struct ospf_lsa
*new;
1478 struct ospf_lsa
*old
;
1479 struct ospf_area
*area
= NULL
;
1480 struct ospf_interface
*oi
= NULL
;
1481 struct ospf_lsdb
*lsdb
= NULL
;
1483 int lsa_type
, opaque_type
;
1487 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1489 /* Extract opaque LSA data from message */
1490 omsg
= (struct msg_originate_request
*)STREAM_DATA(msg
->s
);
1493 /* Determine interface for type9 or area for type10 LSAs. */
1494 switch (data
->type
) {
1495 case OSPF_OPAQUE_LINK_LSA
:
1496 oi
= ospf_apiserver_if_lookup_by_addr(omsg
->ifaddr
);
1498 zlog_warn("apiserver_originate: unknown interface %pI4",
1500 rc
= OSPF_API_NOSUCHINTERFACE
;
1506 case OSPF_OPAQUE_AREA_LSA
:
1507 area
= ospf_area_lookup_by_area_id(ospf
, omsg
->area_id
);
1509 zlog_warn("apiserver_originate: unknown area %pI4",
1511 rc
= OSPF_API_NOSUCHAREA
;
1516 case OSPF_OPAQUE_AS_LSA
:
1520 /* We can only handle opaque types here */
1522 "apiserver_originate: Cannot originate non-opaque LSA type %d",
1524 rc
= OSPF_API_ILLEGALLSATYPE
;
1528 /* Check if we registered this opaque type */
1529 lsa_type
= data
->type
;
1530 opaque_type
= GET_OPAQUE_TYPE(ntohl(data
->id
.s_addr
));
1532 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1535 "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered",
1536 lsa_type
, opaque_type
);
1537 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1541 /* Make sure that the neighbors are ready before we can originate */
1542 switch (data
->type
) {
1543 case OSPF_OPAQUE_LINK_LSA
:
1544 ready
= ospf_apiserver_is_ready_type9(oi
);
1546 case OSPF_OPAQUE_AREA_LSA
:
1547 ready
= ospf_apiserver_is_ready_type10(area
);
1549 case OSPF_OPAQUE_AS_LSA
:
1550 ready
= ospf_apiserver_is_ready_type11(ospf
);
1557 zlog_warn("Neighbors not ready to originate type %d",
1559 rc
= OSPF_API_NOTREADY
;
1563 /* Create OSPF's internal opaque LSA representation */
1564 new = ospf_apiserver_opaque_lsa_new(area
, oi
, data
);
1566 rc
= OSPF_API_NOMEMORY
; /* XXX */
1570 /* Determine if LSA is new or an update for an existing one. */
1571 old
= ospf_lsdb_lookup(lsdb
, new);
1574 /* New LSA install in LSDB. */
1575 rc
= ospf_apiserver_originate1(new);
1578 * Keep the new LSA instance in the "waiting place" until the
1580 * refresh timing. If several LSA update requests for the same
1582 * have issued by peer, the last one takes effect.
1584 new->lsdb
= &apiserv
->reserve
;
1585 ospf_lsdb_add(&apiserv
->reserve
, new);
1587 /* Kick the scheduler function. */
1588 ospf_opaque_lsa_refresh_schedule(old
);
1593 /* Send a reply back to client with return code */
1594 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1599 /* -----------------------------------------------------------
1600 * Flood an LSA within its flooding scope.
1601 * -----------------------------------------------------------
1604 /* XXX We can probably use ospf_flood_through instead of this function
1605 but then we need the neighbor parameter. If we set nbr to
1606 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1608 void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa
*lsa
)
1612 switch (lsa
->data
->type
) {
1613 case OSPF_OPAQUE_LINK_LSA
:
1614 /* Increment counters? XXX */
1616 /* Flood LSA through local network. */
1617 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1619 case OSPF_OPAQUE_AREA_LSA
:
1620 /* Update LSA origination count. */
1622 lsa
->area
->ospf
->lsa_originate_count
++;
1624 /* Flood LSA through area. */
1625 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1627 case OSPF_OPAQUE_AS_LSA
: {
1630 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1633 /* Increment counters? XXX */
1635 /* Flood LSA through AS. */
1636 ospf_flood_through_as(ospf
, NULL
/*nbr */, lsa
);
1642 int ospf_apiserver_originate1(struct ospf_lsa
*lsa
)
1646 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1649 /* Install this LSA into LSDB. */
1650 if (ospf_lsa_install(ospf
, lsa
->oi
, lsa
) == NULL
) {
1651 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1652 "ospf_apiserver_originate1: ospf_lsa_install failed");
1656 /* Flood LSA within scope */
1660 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1661 * parameter, and thus it does not cause SIGSEGV error.
1663 ospf_flood_through(NULL
/*nbr */, lsa
);
1666 ospf_apiserver_flood_opaque_lsa(lsa
);
1673 /* Opaque LSAs of type 9 on a specific interface can now be
1674 originated. Tell clients that registered type 9. */
1675 int ospf_apiserver_lsa9_originator(void *arg
)
1677 struct ospf_interface
*oi
;
1679 oi
= (struct ospf_interface
*)arg
;
1680 if (listcount(apiserver_list
) > 0) {
1681 ospf_apiserver_clients_notify_ready_type9(oi
);
1686 int ospf_apiserver_lsa10_originator(void *arg
)
1688 struct ospf_area
*area
;
1690 area
= (struct ospf_area
*)arg
;
1691 if (listcount(apiserver_list
) > 0) {
1692 ospf_apiserver_clients_notify_ready_type10(area
);
1697 int ospf_apiserver_lsa11_originator(void *arg
)
1701 ospf
= (struct ospf
*)arg
;
1702 if (listcount(apiserver_list
) > 0) {
1703 ospf_apiserver_clients_notify_ready_type11(ospf
);
1709 /* Periodically refresh opaque LSAs so that they do not expire in
1711 struct ospf_lsa
*ospf_apiserver_lsa_refresher(struct ospf_lsa
*lsa
)
1713 struct ospf_apiserver
*apiserv
;
1714 struct ospf_lsa
*new = NULL
;
1719 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1722 apiserv
= lookup_apiserver_by_lsa(lsa
);
1725 "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
1728 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1732 if (IS_LSA_MAXAGE(lsa
)) {
1733 ospf_opaque_lsa_flush_schedule(lsa
);
1737 /* Check if updated version of LSA instance has already prepared. */
1738 new = ospf_lsdb_lookup(&apiserv
->reserve
, lsa
);
1740 /* This is a periodic refresh, driven by core OSPF mechanism. */
1741 new = ospf_apiserver_opaque_lsa_new(lsa
->area
, lsa
->oi
,
1745 "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1749 /* This is a forcible refresh, requested by OSPF-API client. */
1750 ospf_lsdb_delete(&apiserv
->reserve
, new);
1754 /* Increment sequence number */
1755 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1757 /* New LSA is in same area. */
1758 new->area
= lsa
->area
;
1759 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1761 /* Install LSA into LSDB. */
1762 if (ospf_lsa_install(ospf
, new->oi
, new) == NULL
) {
1764 EC_OSPF_LSA_INSTALL_FAILURE
,
1765 "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1766 ospf_lsa_unlock(&new);
1770 /* Flood updated LSA through interface, area or AS */
1773 ospf_flood_through(NULL
/*nbr */, new);
1775 ospf_apiserver_flood_opaque_lsa(new);
1777 /* Debug logging. */
1778 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1779 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
1780 new->data
->type
, &new->data
->id
);
1781 ospf_lsa_header_dump(new->data
);
1789 /* -----------------------------------------------------------
1790 * Following are functions to delete LSAs
1791 * -----------------------------------------------------------
1794 int ospf_apiserver_handle_delete_request(struct ospf_apiserver
*apiserv
,
1797 struct msg_delete_request
*dmsg
;
1798 struct ospf_lsa
*old
;
1799 struct ospf_area
*area
= NULL
;
1801 int lsa_type
, opaque_type
;
1805 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1808 /* Extract opaque LSA from message */
1809 dmsg
= (struct msg_delete_request
*)STREAM_DATA(msg
->s
);
1811 /* Lookup area for link-local and area-local opaque LSAs */
1812 switch (dmsg
->lsa_type
) {
1813 case OSPF_OPAQUE_LINK_LSA
:
1814 case OSPF_OPAQUE_AREA_LSA
:
1815 area
= ospf_area_lookup_by_area_id(ospf
, dmsg
->area_id
);
1817 zlog_warn("ospf_apiserver_lsa_delete: unknown area %pI4",
1819 rc
= OSPF_API_NOSUCHAREA
;
1823 case OSPF_OPAQUE_AS_LSA
:
1824 /* AS-external opaque LSAs have no designated area */
1829 "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1831 rc
= OSPF_API_ILLEGALLSATYPE
;
1835 /* Check if we registered this opaque type */
1836 lsa_type
= dmsg
->lsa_type
;
1837 opaque_type
= dmsg
->opaque_type
;
1839 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1842 "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
1843 lsa_type
, opaque_type
);
1844 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1848 /* opaque_id is in network byte order */
1850 SET_OPAQUE_LSID(dmsg
->opaque_type
, ntohl(dmsg
->opaque_id
)));
1853 * Even if the target LSA has once scheduled to flush, it remains in
1854 * the LSDB until it is finally handled by the maxage remover thread.
1855 * Therefore, the lookup function below may return non-NULL result.
1857 old
= ospf_lsa_lookup(ospf
, area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1860 "ospf_apiserver_lsa_delete: LSA[Type%d:%pI4] not in LSDB",
1861 dmsg
->lsa_type
, &id
);
1862 rc
= OSPF_API_NOSUCHLSA
;
1866 /* Schedule flushing of LSA from LSDB */
1867 /* NB: Multiple scheduling will produce a warning message, but harmless.
1869 ospf_opaque_lsa_flush_schedule(old
);
1873 /* Send reply back to client including return code */
1874 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1878 /* Flush self-originated opaque LSA */
1879 static int apiserver_flush_opaque_type_callback(struct ospf_lsa
*lsa
,
1880 void *p_arg
, int int_arg
)
1883 struct ospf_apiserver
*apiserv
;
1885 uint8_t opaque_type
;
1891 param
= (struct param_t
*)p_arg
;
1893 /* If LSA matches type and opaque type then delete it */
1894 if (IS_LSA_SELF(lsa
) && lsa
->data
->type
== param
->lsa_type
1895 && GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1896 == param
->opaque_type
) {
1897 ospf_opaque_lsa_flush_schedule(lsa
);
1902 /* Delete self-originated opaque LSAs of a given opaque type. This
1903 function is called when an application unregisters a given opaque
1904 type or a connection to an application closes and all those opaque
1905 LSAs need to be flushed the LSDB. */
1906 void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver
*apiserv
,
1907 uint8_t lsa_type
, uint8_t opaque_type
)
1910 struct ospf_apiserver
*apiserv
;
1912 uint8_t opaque_type
;
1914 struct listnode
*node
, *nnode
;
1916 struct ospf_area
*area
;
1918 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1921 /* Set parameter struct. */
1922 param
.apiserv
= apiserv
;
1923 param
.lsa_type
= lsa_type
;
1924 param
.opaque_type
= opaque_type
;
1927 struct route_node
*rn
;
1928 struct ospf_lsa
*lsa
;
1930 case OSPF_OPAQUE_LINK_LSA
:
1931 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
1932 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1933 apiserver_flush_opaque_type_callback(
1934 lsa
, (void *)¶m
, 0);
1936 case OSPF_OPAQUE_AREA_LSA
:
1937 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
1938 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1939 apiserver_flush_opaque_type_callback(
1940 lsa
, (void *)¶m
, 0);
1942 case OSPF_OPAQUE_AS_LSA
:
1943 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf
), rn
, lsa
)
1944 apiserver_flush_opaque_type_callback(lsa
,
1954 /* -----------------------------------------------------------
1955 * Following are callback functions to handle opaque types
1956 * -----------------------------------------------------------
1959 int ospf_apiserver_new_if(struct interface
*ifp
)
1961 struct ospf_interface
*oi
;
1963 /* For some strange reason it seems possible that we are invoked
1964 with an interface that has no name. This seems to happen during
1965 initialization. Return if this happens */
1967 if (ifp
->name
[0] == '\0') {
1968 /* interface has empty name */
1969 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1973 /* zlog_warn for debugging */
1974 zlog_warn("ospf_apiserver_new_if");
1975 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
1978 if (ifp
->name
[0] == '\0') {
1979 /* interface has empty name */
1980 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1984 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
1987 /* This interface is known to Zebra but not to OSPF daemon yet.
1990 "ospf_apiserver_new_if: interface %s not known to OSPFd?",
1997 /* New interface added to OSPF, tell clients about it */
1998 if (listcount(apiserver_list
) > 0) {
1999 ospf_apiserver_clients_notify_new_if(oi
);
2004 int ospf_apiserver_del_if(struct interface
*ifp
)
2006 struct ospf_interface
*oi
;
2008 /* zlog_warn for debugging */
2009 zlog_warn("ospf_apiserver_del_if");
2010 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2013 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2016 /* This interface is known to Zebra but not to OSPF daemon
2017 anymore. No need to tell clients about it */
2021 /* Interface deleted, tell clients about it */
2022 if (listcount(apiserver_list
) > 0) {
2023 ospf_apiserver_clients_notify_del_if(oi
);
2028 void ospf_apiserver_ism_change(struct ospf_interface
*oi
, int old_state
)
2030 /* Tell clients about interface change */
2032 /* zlog_warn for debugging */
2033 zlog_warn("ospf_apiserver_ism_change");
2034 if (listcount(apiserver_list
) > 0) {
2035 ospf_apiserver_clients_notify_ism_change(oi
);
2038 zlog_warn("oi->ifp->name=%s", oi
->ifp
->name
);
2039 zlog_warn("old_state=%d", old_state
);
2040 zlog_warn("oi->state=%d", oi
->state
);
2043 void ospf_apiserver_nsm_change(struct ospf_neighbor
*nbr
, int old_status
)
2045 /* Neighbor status changed, tell clients about it */
2046 zlog_warn("ospf_apiserver_nsm_change");
2047 if (listcount(apiserver_list
) > 0) {
2048 ospf_apiserver_clients_notify_nsm_change(nbr
);
2052 void ospf_apiserver_show_info(struct vty
*vty
, struct json_object
*json
,
2053 struct ospf_lsa
*lsa
)
2056 struct lsa_header header
;
2057 uint8_t data
[1]; /* opaque data have variable length. This is
2061 struct opaque_lsa
*olsa
;
2067 olsa
= (struct opaque_lsa
*)lsa
->data
;
2069 if (VALID_OPAQUE_INFO_LEN(lsa
->data
))
2070 opaquelen
= ntohs(lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2074 /* Output information about opaque LSAs */
2078 " Added using OSPF API: %u octets of opaque data %s\n",
2080 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2081 : "(Invalid length?)");
2082 vty_out(vty
, " Opaque data: ");
2084 for (i
= 0; i
< opaquelen
; i
++) {
2085 vty_out(vty
, "0x%x ", olsa
->data
[i
]);
2091 " Added using OSPF API: %u octets of opaque data %s",
2093 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2094 : "(Invalid length?)");
2095 zlog_debug(" Opaque data: ");
2097 for (i
= 0; i
< opaquelen
; i
++) {
2098 zlog_debug("0x%x ", olsa
->data
[i
]);
2104 /* -----------------------------------------------------------
2105 * Following are functions to notify clients about events
2106 * -----------------------------------------------------------
2109 /* Send a message to all clients. This is useful for messages
2110 that need to be notified to all clients (such as interface
2113 void ospf_apiserver_clients_notify_all(struct msg
*msg
)
2115 struct listnode
*node
, *nnode
;
2116 struct ospf_apiserver
*apiserv
;
2118 /* Send message to all clients */
2119 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
))
2120 ospf_apiserver_send_msg(apiserv
, msg
);
2123 /* An interface is now ready to accept opaque LSAs. Notify all
2124 clients that registered to use this opaque type */
2125 void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface
*oi
)
2127 struct listnode
*node
, *nnode
;
2129 struct ospf_apiserver
*apiserv
;
2133 zlog_warn("Interface has no address?");
2137 if (!ospf_apiserver_is_ready_type9(oi
)) {
2138 zlog_warn("Interface not ready for type 9?");
2142 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2143 struct listnode
*node2
, *nnode2
;
2144 struct registered_opaque_type
*r
;
2146 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2148 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
2149 msg
= new_msg_ready_notify(
2150 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
2151 oi
->address
->u
.prefix4
);
2154 "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2156 /* Cannot allocate new message. What
2158 ospf_apiserver_free(apiserv
);
2163 ospf_apiserver_send_msg(apiserv
, msg
);
2173 void ospf_apiserver_clients_notify_ready_type10(struct ospf_area
*area
)
2175 struct listnode
*node
, *nnode
;
2177 struct ospf_apiserver
*apiserv
;
2181 if (!ospf_apiserver_is_ready_type10(area
)) {
2182 zlog_warn("Area not ready for type 10?");
2186 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2187 struct listnode
*node2
, *nnode2
;
2188 struct registered_opaque_type
*r
;
2190 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2192 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
2193 msg
= new_msg_ready_notify(
2194 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
2198 "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2200 /* Cannot allocate new message. What
2202 ospf_apiserver_free(apiserv
);
2207 ospf_apiserver_send_msg(apiserv
, msg
);
2218 void ospf_apiserver_clients_notify_ready_type11(struct ospf
*top
)
2220 struct listnode
*node
, *nnode
;
2222 struct in_addr id_null
= {.s_addr
= 0L};
2223 struct ospf_apiserver
*apiserv
;
2227 if (!ospf_apiserver_is_ready_type11(top
)) {
2228 zlog_warn("AS not ready for type 11?");
2232 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2233 struct listnode
*node2
, *nnode2
;
2234 struct registered_opaque_type
*r
;
2236 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2238 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
2239 msg
= new_msg_ready_notify(
2240 0, OSPF_OPAQUE_AS_LSA
, r
->opaque_type
,
2244 "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2246 /* Cannot allocate new message. What
2248 ospf_apiserver_free(apiserv
);
2253 ospf_apiserver_send_msg(apiserv
, msg
);
2263 void ospf_apiserver_clients_notify_new_if(struct ospf_interface
*oi
)
2267 msg
= new_msg_new_if(0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2269 ospf_apiserver_clients_notify_all(msg
);
2274 void ospf_apiserver_clients_notify_del_if(struct ospf_interface
*oi
)
2278 msg
= new_msg_del_if(0, oi
->address
->u
.prefix4
);
2280 ospf_apiserver_clients_notify_all(msg
);
2285 void ospf_apiserver_clients_notify_ism_change(struct ospf_interface
*oi
)
2288 struct in_addr ifaddr
= {.s_addr
= 0L};
2289 struct in_addr area_id
= {.s_addr
= 0L};
2295 ifaddr
= oi
->address
->u
.prefix4
;
2298 area_id
= oi
->area
->area_id
;
2301 msg
= new_msg_ism_change(0, ifaddr
, area_id
, oi
->state
);
2304 "apiserver_clients_notify_ism_change: msg_new failed");
2308 ospf_apiserver_clients_notify_all(msg
);
2312 void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor
*nbr
)
2315 struct in_addr ifaddr
;
2316 struct in_addr nbraddr
;
2320 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2322 nbraddr
= nbr
->address
.u
.prefix4
;
2324 msg
= new_msg_nsm_change(0, ifaddr
, nbraddr
, nbr
->router_id
,
2328 "apiserver_clients_notify_nsm_change: msg_new failed");
2332 ospf_apiserver_clients_notify_all(msg
);
2336 static void apiserver_clients_lsa_change_notify(uint8_t msgtype
,
2337 struct ospf_lsa
*lsa
)
2340 struct listnode
*node
, *nnode
;
2341 struct ospf_apiserver
*apiserv
;
2343 /* Default area for AS-External and Opaque11 LSAs */
2344 struct in_addr area_id
= {.s_addr
= 0L};
2346 /* Default interface for non Opaque9 LSAs */
2347 struct in_addr ifaddr
= {.s_addr
= 0L};
2350 area_id
= lsa
->area
->area_id
;
2352 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2354 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2357 /* Prepare message that can be sent to clients that have a matching
2359 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2361 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2364 "apiserver_clients_lsa_change_notify: msg_new failed");
2368 /* Now send message to all clients with a matching filter */
2369 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2370 struct lsa_filter_type
*filter
;
2375 /* Check filter for this client. */
2376 filter
= apiserv
->filter
;
2378 /* Check area IDs in case of non AS-E LSAs.
2379 * If filter has areas (num_areas > 0),
2380 * then one of the areas must match the area ID of this LSA. */
2382 i
= filter
->num_areas
;
2383 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)
2384 || (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
)) {
2389 area
= (uint32_t *)(filter
+ 1);
2391 if (*area
== area_id
.s_addr
) {
2402 /* Area match. Check LSA type. */
2403 mask
= ntohs(filter
->typemask
);
2405 if (mask
& Power2
[lsa
->data
->type
]) {
2406 /* Type also matches. Check origin. */
2407 if ((filter
->origin
== ANY_ORIGIN
)
2408 || (filter
->origin
== IS_LSA_SELF(lsa
))) {
2409 ospf_apiserver_send_msg(apiserv
, msg
);
2414 /* Free message since it is not used anymore */
2419 /* -------------------------------------------------------------
2420 * Following are hooks invoked when LSAs are updated or deleted
2421 * -------------------------------------------------------------
2425 static int apiserver_notify_clients_lsa(uint8_t msgtype
, struct ospf_lsa
*lsa
)
2428 /* default area for AS-External and Opaque11 LSAs */
2429 struct in_addr area_id
= {.s_addr
= 0L};
2431 /* default interface for non Opaque9 LSAs */
2432 struct in_addr ifaddr
= {.s_addr
= 0L};
2434 /* Only notify this update if the LSA's age is smaller than
2435 MAXAGE. Otherwise clients would see LSA updates with max age just
2436 before they are deleted from the LSDB. LSA delete messages have
2437 MAXAGE too but should not be filtered. */
2438 if (IS_LSA_MAXAGE(lsa
) && (msgtype
== MSG_LSA_UPDATE_NOTIFY
)) {
2443 area_id
= lsa
->area
->area_id
;
2445 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2446 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2448 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2450 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2452 zlog_warn("notify_clients_lsa: msg_new failed");
2455 /* Notify all clients that new LSA is added/updated */
2456 apiserver_clients_lsa_change_notify(msgtype
, lsa
);
2458 /* Clients made their own copies of msg so we can free msg here */
2464 int ospf_apiserver_lsa_update(struct ospf_lsa
*lsa
)
2466 return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY
, lsa
);
2469 int ospf_apiserver_lsa_delete(struct ospf_lsa
*lsa
)
2471 return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY
, lsa
);
2474 #endif /* SUPPORT_OSPF_API */