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 * Followings 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 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 if (apiserv
->t_sync_read
) {
321 thread_cancel(apiserv
->t_sync_read
);
323 #ifdef USE_ASYNC_READ
324 if (apiserv
->t_async_read
) {
325 thread_cancel(apiserv
->t_async_read
);
327 #endif /* USE_ASYNC_READ */
328 if (apiserv
->t_sync_write
) {
329 thread_cancel(apiserv
->t_sync_write
);
332 if (apiserv
->t_async_write
) {
333 thread_cancel(apiserv
->t_async_write
);
336 /* Unregister all opaque types that application registered
337 and flush opaque LSAs if still in LSDB. */
339 while ((node
= listhead(apiserv
->opaque_types
)) != NULL
) {
340 struct registered_opaque_type
*regtype
= listgetdata(node
);
342 ospf_apiserver_unregister_opaque_type(
343 apiserv
, regtype
->lsa_type
, regtype
->opaque_type
);
346 /* Close connections to OSPFd. */
347 if (apiserv
->fd_sync
> 0) {
348 close(apiserv
->fd_sync
);
351 if (apiserv
->fd_async
> 0) {
352 close(apiserv
->fd_async
);
356 msg_fifo_free(apiserv
->out_sync_fifo
);
357 msg_fifo_free(apiserv
->out_async_fifo
);
359 /* Clear temporary strage for LSA instances to be refreshed. */
360 ospf_lsdb_delete_all(&apiserv
->reserve
);
361 ospf_lsdb_cleanup(&apiserv
->reserve
);
363 /* Remove from the list of active clients. */
364 listnode_delete(apiserver_list
, apiserv
);
366 if (IS_DEBUG_OSPF_EVENT
)
367 zlog_debug("API: Delete apiserv(%p), total#(%d)",
368 (void *)apiserv
, apiserver_list
->count
);
370 /* And free instance. */
371 XFREE(MTYPE_OSPF_APISERVER
, apiserv
);
374 int ospf_apiserver_read(struct thread
*thread
)
376 struct ospf_apiserver
*apiserv
;
382 apiserv
= THREAD_ARG(thread
);
383 fd
= THREAD_FD(thread
);
385 if (fd
== apiserv
->fd_sync
) {
386 event
= OSPF_APISERVER_SYNC_READ
;
387 apiserv
->t_sync_read
= NULL
;
389 if (IS_DEBUG_OSPF_EVENT
)
390 zlog_debug("API: ospf_apiserver_read: Peer: %s/%u",
391 inet_ntoa(apiserv
->peer_sync
.sin_addr
),
392 ntohs(apiserv
->peer_sync
.sin_port
));
394 #ifdef USE_ASYNC_READ
395 else if (fd
== apiserv
->fd_async
) {
396 event
= OSPF_APISERVER_ASYNC_READ
;
397 apiserv
->t_async_read
= NULL
;
399 if (IS_DEBUG_OSPF_EVENT
)
400 zlog_debug("API: ospf_apiserver_read: Peer: %s/%u",
401 inet_ntoa(apiserv
->peer_async
.sin_addr
),
402 ntohs(apiserv
->peer_async
.sin_port
));
404 #endif /* USE_ASYNC_READ */
406 zlog_warn("ospf_apiserver_read: Unknown fd(%d)", fd
);
407 ospf_apiserver_free(apiserv
);
411 /* Read message from fd. */
415 "ospf_apiserver_read: read failed on fd=%d, closing connection",
418 /* Perform cleanup. */
419 ospf_apiserver_free(apiserv
);
423 if (IS_DEBUG_OSPF_EVENT
)
426 /* Dispatch to corresponding message handler. */
427 rc
= ospf_apiserver_handle_msg(apiserv
, msg
);
429 /* Prepare for next message, add read thread. */
430 ospf_apiserver_event(event
, fd
, apiserv
);
438 int ospf_apiserver_sync_write(struct thread
*thread
)
440 struct ospf_apiserver
*apiserv
;
445 apiserv
= THREAD_ARG(thread
);
447 fd
= THREAD_FD(thread
);
449 apiserv
->t_sync_write
= NULL
;
452 if (fd
!= apiserv
->fd_sync
) {
453 zlog_warn("ospf_apiserver_sync_write: Unknown fd=%d", fd
);
457 if (IS_DEBUG_OSPF_EVENT
)
458 zlog_debug("API: ospf_apiserver_sync_write: Peer: %s/%u",
459 inet_ntoa(apiserv
->peer_sync
.sin_addr
),
460 ntohs(apiserv
->peer_sync
.sin_port
));
462 /* Check whether there is really a message in the fifo. */
463 msg
= msg_fifo_pop(apiserv
->out_sync_fifo
);
466 "API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
470 if (IS_DEBUG_OSPF_EVENT
)
473 rc
= msg_write(fd
, msg
);
475 /* Once a message is dequeued, it should be freed anyway. */
479 zlog_warn("ospf_apiserver_sync_write: write failed on fd=%d",
485 /* If more messages are in sync message fifo, schedule write thread. */
486 if (msg_fifo_head(apiserv
->out_sync_fifo
)) {
487 ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE
,
488 apiserv
->fd_sync
, apiserv
);
494 /* Perform cleanup and disconnect with peer */
495 ospf_apiserver_free(apiserv
);
502 int ospf_apiserver_async_write(struct thread
*thread
)
504 struct ospf_apiserver
*apiserv
;
509 apiserv
= THREAD_ARG(thread
);
511 fd
= THREAD_FD(thread
);
513 apiserv
->t_async_write
= NULL
;
516 if (fd
!= apiserv
->fd_async
) {
517 zlog_warn("ospf_apiserver_async_write: Unknown fd=%d", fd
);
521 if (IS_DEBUG_OSPF_EVENT
)
522 zlog_debug("API: ospf_apiserver_async_write: Peer: %s/%u",
523 inet_ntoa(apiserv
->peer_async
.sin_addr
),
524 ntohs(apiserv
->peer_async
.sin_port
));
526 /* Check whether there is really a message in the fifo. */
527 msg
= msg_fifo_pop(apiserv
->out_async_fifo
);
530 "API: ospf_apiserver_async_write: No message in Async-FIFO?");
534 if (IS_DEBUG_OSPF_EVENT
)
537 rc
= msg_write(fd
, msg
);
539 /* Once a message is dequeued, it should be freed anyway. */
543 zlog_warn("ospf_apiserver_async_write: write failed on fd=%d",
549 /* If more messages are in async message fifo, schedule write thread. */
550 if (msg_fifo_head(apiserv
->out_async_fifo
)) {
551 ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE
,
552 apiserv
->fd_async
, apiserv
);
558 /* Perform cleanup and disconnect with peer */
559 ospf_apiserver_free(apiserv
);
566 int ospf_apiserver_serv_sock_family(unsigned short port
, int family
)
572 memset(&su
, 0, sizeof(union sockunion
));
573 su
.sa
.sa_family
= family
;
575 /* Make new socket */
576 accept_sock
= sockunion_stream_socket(&su
);
580 /* This is a server, so reuse address and port */
581 sockopt_reuseaddr(accept_sock
);
582 sockopt_reuseport(accept_sock
);
584 /* Bind socket to address and given port. */
585 rc
= sockunion_bind(accept_sock
, &su
, port
, NULL
);
587 close(accept_sock
); /* Close socket */
591 /* Listen socket under queue length 3. */
592 rc
= listen(accept_sock
, 3);
594 zlog_warn("ospf_apiserver_serv_sock_family: listen: %s",
595 safe_strerror(errno
));
596 close(accept_sock
); /* Close socket */
603 /* Accept connection request from external applications. For each
604 accepted connection allocate own connection instance. */
605 int ospf_apiserver_accept(struct thread
*thread
)
611 struct ospf_apiserver
*apiserv
;
612 struct sockaddr_in peer_async
;
613 struct sockaddr_in peer_sync
;
614 unsigned int peerlen
;
617 /* THREAD_ARG (thread) is NULL */
618 accept_sock
= THREAD_FD(thread
);
620 /* Keep hearing on socket for further connections. */
621 ospf_apiserver_event(OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
623 memset(&su
, 0, sizeof(union sockunion
));
624 /* Accept connection for synchronous messages */
625 new_sync_sock
= sockunion_accept(accept_sock
, &su
);
626 if (new_sync_sock
< 0) {
627 zlog_warn("ospf_apiserver_accept: accept: %s",
628 safe_strerror(errno
));
632 /* Get port address and port number of peer to make reverse connection.
633 The reverse channel uses the port number of the peer port+1. */
635 memset(&peer_sync
, 0, sizeof(struct sockaddr_in
));
636 peerlen
= sizeof(struct sockaddr_in
);
638 ret
= getpeername(new_sync_sock
, (struct sockaddr
*)&peer_sync
,
641 zlog_warn("ospf_apiserver_accept: getpeername: %s",
642 safe_strerror(errno
));
643 close(new_sync_sock
);
647 if (IS_DEBUG_OSPF_EVENT
)
648 zlog_debug("API: ospf_apiserver_accept: New peer: %s/%u",
649 inet_ntoa(peer_sync
.sin_addr
),
650 ntohs(peer_sync
.sin_port
));
652 /* Create new socket for asynchronous messages. */
653 peer_async
= peer_sync
;
654 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
656 /* Check if remote port number to make reverse connection is valid one.
658 if (ntohs(peer_async
.sin_port
) == ospf_apiserver_getport()) {
660 "API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
661 inet_ntoa(peer_async
.sin_addr
),
662 ntohs(peer_async
.sin_port
));
663 close(new_sync_sock
);
667 new_async_sock
= socket(AF_INET
, SOCK_STREAM
, 0);
668 if (new_async_sock
< 0) {
669 zlog_warn("ospf_apiserver_accept: socket: %s",
670 safe_strerror(errno
));
671 close(new_sync_sock
);
675 ret
= connect(new_async_sock
, (struct sockaddr
*)&peer_async
,
676 sizeof(struct sockaddr_in
));
679 zlog_warn("ospf_apiserver_accept: connect: %s",
680 safe_strerror(errno
));
681 close(new_sync_sock
);
682 close(new_async_sock
);
686 #ifdef USE_ASYNC_READ
687 #else /* USE_ASYNC_READ */
688 /* Make the asynchronous channel write-only. */
689 ret
= shutdown(new_async_sock
, SHUT_RD
);
691 zlog_warn("ospf_apiserver_accept: shutdown: %s",
692 safe_strerror(errno
));
693 close(new_sync_sock
);
694 close(new_async_sock
);
697 #endif /* USE_ASYNC_READ */
699 /* Allocate new server-side connection structure */
700 apiserv
= ospf_apiserver_new(new_sync_sock
, new_async_sock
);
702 /* Add to active connection list */
703 listnode_add(apiserver_list
, apiserv
);
704 apiserv
->peer_sync
= peer_sync
;
705 apiserv
->peer_async
= peer_async
;
707 /* And add read threads for new connection */
708 ospf_apiserver_event(OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
709 #ifdef USE_ASYNC_READ
710 ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ
, new_async_sock
,
712 #endif /* USE_ASYNC_READ */
714 if (IS_DEBUG_OSPF_EVENT
)
715 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv
,
716 apiserver_list
->count
);
722 /* -----------------------------------------------------------
723 * Send reply with return code to client application
724 * -----------------------------------------------------------
727 static int ospf_apiserver_send_msg(struct ospf_apiserver
*apiserv
,
730 struct msg_fifo
*fifo
;
735 switch (msg
->hdr
.msgtype
) {
737 fifo
= apiserv
->out_sync_fifo
;
738 fd
= apiserv
->fd_sync
;
739 event
= OSPF_APISERVER_SYNC_WRITE
;
741 case MSG_READY_NOTIFY
:
742 case MSG_LSA_UPDATE_NOTIFY
:
743 case MSG_LSA_DELETE_NOTIFY
:
748 fifo
= apiserv
->out_async_fifo
;
749 fd
= apiserv
->fd_async
;
750 event
= OSPF_APISERVER_ASYNC_WRITE
;
753 zlog_warn("ospf_apiserver_send_msg: Unknown message type %d",
758 /* Make a copy of the message and put in the fifo. Once the fifo
759 gets drained by the write thread, the message will be freed. */
760 /* NB: Given "msg" is untouched in this function. */
763 /* Enqueue message into corresponding fifo queue */
764 msg_fifo_push(fifo
, msg2
);
766 /* Schedule write thread */
767 ospf_apiserver_event(event
, fd
, apiserv
);
771 int ospf_apiserver_send_reply(struct ospf_apiserver
*apiserv
, uint32_t seqnr
,
774 struct msg
*msg
= new_msg_reply(seqnr
, rc
);
778 zlog_warn("ospf_apiserver_send_reply: msg_new failed");
780 /* Cannot allocate new message. What should we do? */
781 ospf_apiserver_free(apiserv
);
786 ret
= ospf_apiserver_send_msg(apiserv
, msg
);
792 /* -----------------------------------------------------------
793 * Generic message dispatching handler function
794 * -----------------------------------------------------------
797 int ospf_apiserver_handle_msg(struct ospf_apiserver
*apiserv
, struct msg
*msg
)
801 /* Call corresponding message handler function. */
802 switch (msg
->hdr
.msgtype
) {
803 case MSG_REGISTER_OPAQUETYPE
:
804 rc
= ospf_apiserver_handle_register_opaque_type(apiserv
, msg
);
806 case MSG_UNREGISTER_OPAQUETYPE
:
807 rc
= ospf_apiserver_handle_unregister_opaque_type(apiserv
, msg
);
809 case MSG_REGISTER_EVENT
:
810 rc
= ospf_apiserver_handle_register_event(apiserv
, msg
);
813 rc
= ospf_apiserver_handle_sync_lsdb(apiserv
, msg
);
815 case MSG_ORIGINATE_REQUEST
:
816 rc
= ospf_apiserver_handle_originate_request(apiserv
, msg
);
818 case MSG_DELETE_REQUEST
:
819 rc
= ospf_apiserver_handle_delete_request(apiserv
, msg
);
822 zlog_warn("ospf_apiserver_handle_msg: Unknown message type: %d",
830 /* -----------------------------------------------------------
831 * Following are functions for opaque type registration
832 * -----------------------------------------------------------
835 int ospf_apiserver_register_opaque_type(struct ospf_apiserver
*apiserv
,
836 uint8_t lsa_type
, uint8_t opaque_type
)
838 struct registered_opaque_type
*regtype
;
839 int (*originator_func
)(void *arg
);
843 case OSPF_OPAQUE_LINK_LSA
:
844 originator_func
= ospf_apiserver_lsa9_originator
;
846 case OSPF_OPAQUE_AREA_LSA
:
847 originator_func
= ospf_apiserver_lsa10_originator
;
849 case OSPF_OPAQUE_AS_LSA
:
850 originator_func
= ospf_apiserver_lsa11_originator
;
853 zlog_warn("ospf_apiserver_register_opaque_type: lsa_type(%d)",
855 return OSPF_API_ILLEGALLSATYPE
;
859 /* Register opaque function table */
860 /* NB: Duplicated registration will be detected inside the function. */
861 rc
= ospf_register_opaque_functab(
862 lsa_type
, opaque_type
, NULL
, /* ospf_apiserver_new_if */
863 NULL
, /* ospf_apiserver_del_if */
864 NULL
, /* ospf_apiserver_ism_change */
865 NULL
, /* ospf_apiserver_nsm_change */
866 NULL
, NULL
, NULL
, ospf_apiserver_show_info
, originator_func
,
867 ospf_apiserver_lsa_refresher
,
868 NULL
, /* ospf_apiserver_lsa_update */
869 NULL
/* ospf_apiserver_lsa_delete */);
872 flog_warn(EC_OSPF_OPAQUE_REGISTRATION
,
873 "Failed to register opaque type [%d/%d]", lsa_type
,
875 return OSPF_API_OPAQUETYPEINUSE
;
878 /* Remember the opaque type that application registers so when
879 connection shuts down, we can flush all LSAs of this opaque
882 regtype
= XCALLOC(MTYPE_OSPF_APISERVER
,
883 sizeof(struct registered_opaque_type
));
884 regtype
->lsa_type
= lsa_type
;
885 regtype
->opaque_type
= opaque_type
;
887 /* Add to list of registered opaque types */
888 listnode_add(apiserv
->opaque_types
, regtype
);
890 if (IS_DEBUG_OSPF_EVENT
)
892 "API: Add LSA-type(%d)/Opaque-type(%d) into"
893 " apiserv(%p), total#(%d)",
894 lsa_type
, opaque_type
, (void *)apiserv
,
895 listcount(apiserv
->opaque_types
));
900 int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
901 uint8_t lsa_type
, uint8_t opaque_type
)
903 struct listnode
*node
, *nnode
;
904 struct registered_opaque_type
*regtype
;
906 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
907 /* Check if we really registered this opaque type */
908 if (regtype
->lsa_type
== lsa_type
909 && regtype
->opaque_type
== opaque_type
) {
911 /* Yes, we registered this opaque type. Flush
912 all existing opaque LSAs of this type */
914 ospf_apiserver_flush_opaque_lsa(apiserv
, lsa_type
,
916 ospf_delete_opaque_functab(lsa_type
, opaque_type
);
918 /* Remove from list of registered opaque types */
919 listnode_delete(apiserv
->opaque_types
, regtype
);
921 if (IS_DEBUG_OSPF_EVENT
)
923 "API: Del LSA-type(%d)/Opaque-type(%d)"
924 " from apiserv(%p), total#(%d)",
925 lsa_type
, opaque_type
, (void *)apiserv
,
926 listcount(apiserv
->opaque_types
));
932 /* Opaque type is not registered */
933 zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type
,
935 return OSPF_API_OPAQUETYPENOTREGISTERED
;
939 static int apiserver_is_opaque_type_registered(struct ospf_apiserver
*apiserv
,
943 struct listnode
*node
, *nnode
;
944 struct registered_opaque_type
*regtype
;
946 /* XXX: how many types are there? if few, why not just a bitmap? */
947 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, regtype
)) {
948 /* Check if we really registered this opaque type */
949 if (regtype
->lsa_type
== lsa_type
950 && regtype
->opaque_type
== opaque_type
) {
959 int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver
*apiserv
,
962 struct msg_register_opaque_type
*rmsg
;
967 /* Extract parameters from register opaque type message */
968 rmsg
= (struct msg_register_opaque_type
*)STREAM_DATA(msg
->s
);
970 lsa_type
= rmsg
->lsatype
;
971 opaque_type
= rmsg
->opaquetype
;
973 rc
= ospf_apiserver_register_opaque_type(apiserv
, lsa_type
,
976 /* Send a reply back to client including return code */
977 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
981 /* Now inform application about opaque types that are ready */
983 case OSPF_OPAQUE_LINK_LSA
:
984 ospf_apiserver_notify_ready_type9(apiserv
);
986 case OSPF_OPAQUE_AREA_LSA
:
987 ospf_apiserver_notify_ready_type10(apiserv
);
989 case OSPF_OPAQUE_AS_LSA
:
990 ospf_apiserver_notify_ready_type11(apiserv
);
998 /* Notify specific client about all opaque types 9 that are ready. */
999 void ospf_apiserver_notify_ready_type9(struct ospf_apiserver
*apiserv
)
1001 struct listnode
*node
, *nnode
;
1002 struct listnode
*node2
, *nnode2
;
1004 struct ospf_interface
*oi
;
1005 struct registered_opaque_type
*r
;
1007 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1009 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
)) {
1010 /* Check if this interface is indeed ready for type 9 */
1011 if (!ospf_apiserver_is_ready_type9(oi
))
1014 /* Check for registered opaque type 9 types */
1015 /* XXX: loop-de-loop - optimise me */
1016 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
1020 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
1022 /* Yes, this opaque type is ready */
1023 msg
= new_msg_ready_notify(
1024 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
1025 oi
->address
->u
.prefix4
);
1028 "apiserver_notify_ready_type9: msg_new failed");
1030 /* Cannot allocate new message. What
1032 ospf_apiserver_free(apiserv
);
1036 ospf_apiserver_send_msg(apiserv
, msg
);
1047 /* Notify specific client about all opaque types 10 that are ready. */
1048 void ospf_apiserver_notify_ready_type10(struct ospf_apiserver
*apiserv
)
1050 struct listnode
*node
, *nnode
;
1051 struct listnode
*node2
, *nnode2
;
1053 struct ospf_area
*area
;
1055 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1057 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1058 struct registered_opaque_type
*r
;
1060 if (!ospf_apiserver_is_ready_type10(area
)) {
1064 /* Check for registered opaque type 10 types */
1065 /* XXX: loop in loop - optimise me */
1066 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
1070 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
1071 /* Yes, this opaque type is ready */
1072 msg
= new_msg_ready_notify(
1073 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
1077 "apiserver_notify_ready_type10: msg_new failed");
1079 /* Cannot allocate new message. What
1081 ospf_apiserver_free(apiserv
);
1085 ospf_apiserver_send_msg(apiserv
, msg
);
1095 /* Notify specific client about all opaque types 11 that are ready */
1096 void ospf_apiserver_notify_ready_type11(struct ospf_apiserver
*apiserv
)
1098 struct listnode
*node
, *nnode
;
1100 struct registered_opaque_type
*r
;
1102 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1104 /* Can type 11 be originated? */
1105 if (!ospf_apiserver_is_ready_type11(ospf
))
1108 /* Check for registered opaque type 11 types */
1109 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node
, nnode
, r
)) {
1111 struct in_addr noarea_id
= {.s_addr
= 0L};
1113 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
1114 /* Yes, this opaque type is ready */
1115 msg
= new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA
,
1116 r
->opaque_type
, noarea_id
);
1120 "apiserver_notify_ready_type11: msg_new failed");
1122 /* Cannot allocate new message. What should we
1124 ospf_apiserver_free(apiserv
);
1128 ospf_apiserver_send_msg(apiserv
, msg
);
1137 int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver
*apiserv
,
1140 struct msg_unregister_opaque_type
*umsg
;
1145 /* Extract parameters from unregister opaque type message */
1146 umsg
= (struct msg_unregister_opaque_type
*)STREAM_DATA(msg
->s
);
1148 ltype
= umsg
->lsatype
;
1149 otype
= umsg
->opaquetype
;
1151 rc
= ospf_apiserver_unregister_opaque_type(apiserv
, ltype
, otype
);
1153 /* Send a reply back to client including return code */
1154 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1160 /* -----------------------------------------------------------
1161 * Following are functions for event (filter) registration.
1162 * -----------------------------------------------------------
1164 int ospf_apiserver_handle_register_event(struct ospf_apiserver
*apiserv
,
1167 struct msg_register_event
*rmsg
;
1171 rmsg
= (struct msg_register_event
*)STREAM_DATA(msg
->s
);
1173 /* Get request sequence number */
1174 seqnum
= msg_get_seq(msg
);
1176 /* Free existing filter in apiserv. */
1177 XFREE(MTYPE_OSPF_APISERVER_MSGFILTER
, apiserv
->filter
);
1178 /* Alloc new space for filter. */
1181 XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER
, ntohs(msg
->hdr
.msglen
));
1184 memcpy(apiserv
->filter
, &rmsg
->filter
, ntohs(msg
->hdr
.msglen
));
1187 /* Send a reply back to client with return code */
1188 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1193 /* -----------------------------------------------------------
1194 * Followings are functions for LSDB synchronization.
1195 * -----------------------------------------------------------
1198 static int apiserver_sync_callback(struct ospf_lsa
*lsa
, void *p_arg
,
1201 struct ospf_apiserver
*apiserv
;
1205 struct ospf_apiserver
*apiserv
;
1206 struct lsa_filter_type
*filter
;
1214 param
= (struct param_t
*)p_arg
;
1215 apiserv
= param
->apiserv
;
1216 seqnum
= (uint32_t)int_arg
;
1218 /* Check origin in filter. */
1219 if ((param
->filter
->origin
== ANY_ORIGIN
)
1220 || (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
))) {
1222 /* Default area for AS-External and Opaque11 LSAs */
1223 struct in_addr area_id
= {.s_addr
= 0L};
1225 /* Default interface for non Opaque9 LSAs */
1226 struct in_addr ifaddr
= {.s_addr
= 0L};
1229 area_id
= lsa
->area
->area_id
;
1231 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
1232 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1235 msg
= new_msg_lsa_change_notify(
1236 MSG_LSA_UPDATE_NOTIFY
, seqnum
, ifaddr
, area_id
,
1237 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1240 "apiserver_sync_callback: new_msg_update failed");
1242 /* Cannot allocate new message. What should we do? */
1243 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1251 ospf_apiserver_send_msg(apiserv
, msg
);
1260 int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver
*apiserv
,
1263 struct listnode
*node
, *nnode
;
1266 struct msg_sync_lsdb
*smsg
;
1267 struct ospf_apiserver_param_t
{
1268 struct ospf_apiserver
*apiserv
;
1269 struct lsa_filter_type
*filter
;
1272 struct route_node
*rn
;
1273 struct ospf_lsa
*lsa
;
1275 struct ospf_area
*area
;
1277 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1279 /* Get request sequence number */
1280 seqnum
= msg_get_seq(msg
);
1282 smsg
= (struct msg_sync_lsdb
*)STREAM_DATA(msg
->s
);
1284 /* Set parameter struct. */
1285 param
.apiserv
= apiserv
;
1286 param
.filter
= &smsg
->filter
;
1288 /* Remember mask. */
1289 mask
= ntohs(smsg
->filter
.typemask
);
1291 /* Iterate over all areas. */
1292 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
)) {
1294 uint32_t *area_id
= NULL
;
1296 /* Compare area_id with area_ids in sync request. */
1297 if ((i
= smsg
->filter
.num_areas
) > 0) {
1298 /* Let area_id point to the list of area IDs,
1299 * which is at the end of smsg->filter. */
1300 area_id
= (uint32_t *)(&smsg
->filter
+ 1);
1302 if (*area_id
== area
->area_id
.s_addr
) {
1312 /* If area was found, then i>0 here. */
1314 /* Check msg type. */
1315 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1316 LSDB_LOOP (ROUTER_LSDB(area
), rn
, lsa
)
1317 apiserver_sync_callback(
1318 lsa
, (void *)¶m
, seqnum
);
1319 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1320 LSDB_LOOP (NETWORK_LSDB(area
), rn
, lsa
)
1321 apiserver_sync_callback(
1322 lsa
, (void *)¶m
, seqnum
);
1323 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1324 LSDB_LOOP (SUMMARY_LSDB(area
), rn
, lsa
)
1325 apiserver_sync_callback(
1326 lsa
, (void *)¶m
, seqnum
);
1327 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1328 LSDB_LOOP (ASBR_SUMMARY_LSDB(area
), rn
, lsa
)
1329 apiserver_sync_callback(
1330 lsa
, (void *)¶m
, seqnum
);
1331 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1332 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1333 apiserver_sync_callback(
1334 lsa
, (void *)¶m
, seqnum
);
1335 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1336 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1337 apiserver_sync_callback(
1338 lsa
, (void *)¶m
, seqnum
);
1342 /* For AS-external LSAs */
1344 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1345 LSDB_LOOP (EXTERNAL_LSDB(ospf
), rn
, lsa
)
1346 apiserver_sync_callback(lsa
, (void *)¶m
,
1350 /* For AS-external opaque LSAs */
1352 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1353 LSDB_LOOP (OPAQUE_AS_LSDB(ospf
), rn
, lsa
)
1354 apiserver_sync_callback(lsa
, (void *)¶m
,
1358 /* Send a reply back to client with return code */
1359 rc
= ospf_apiserver_send_reply(apiserv
, seqnum
, rc
);
1364 /* -----------------------------------------------------------
1365 * Followings are functions to originate or update LSA
1366 * from an application.
1367 * -----------------------------------------------------------
1370 /* Create a new internal opaque LSA by taking prototype and filling in
1371 missing fields such as age, sequence number, advertising router,
1372 checksum and so on. The interface parameter is used for type 9
1373 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1376 struct ospf_lsa
*ospf_apiserver_opaque_lsa_new(struct ospf_area
*area
,
1377 struct ospf_interface
*oi
,
1378 struct lsa_header
*protolsa
)
1381 struct lsa_header
*newlsa
;
1382 struct ospf_lsa
*new = NULL
;
1383 uint8_t options
= 0x0;
1391 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1395 /* Create a stream for internal opaque LSA */
1396 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
1397 zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
1401 newlsa
= (struct lsa_header
*)STREAM_DATA(s
);
1403 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1404 have to set options? */
1407 options
= LSA_OPTIONS_GET(area
);
1408 options
|= LSA_OPTIONS_NSSA_GET(area
);
1411 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1413 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1414 zlog_debug("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1415 protolsa
->type
, inet_ntoa(protolsa
->id
));
1418 /* Set opaque-LSA header fields. */
1419 lsa_header_set(s
, options
, protolsa
->type
, protolsa
->id
,
1422 /* Set opaque-LSA body fields. */
1423 stream_put(s
, ((uint8_t *)protolsa
) + sizeof(struct lsa_header
),
1424 ntohs(protolsa
->length
) - sizeof(struct lsa_header
));
1426 /* Determine length of LSA. */
1427 length
= stream_get_endp(s
);
1428 newlsa
->length
= htons(length
);
1430 /* Create OSPF LSA. */
1431 new = ospf_lsa_new_and_data(length
);
1435 new->vrf_id
= ospf
->vrf_id
;
1437 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1438 memcpy(new->data
, newlsa
, length
);
1445 int ospf_apiserver_is_ready_type9(struct ospf_interface
*oi
)
1447 /* Type 9 opaque LSA can be originated if there is at least one
1448 active opaque-capable neighbor attached to the outgoing
1451 return (ospf_nbr_count_opaque_capable(oi
) > 0);
1454 int ospf_apiserver_is_ready_type10(struct ospf_area
*area
)
1456 /* Type 10 opaque LSA can be originated if there is at least one
1457 interface belonging to the area that has an active opaque-capable
1459 struct listnode
*node
, *nnode
;
1460 struct ospf_interface
*oi
;
1462 for (ALL_LIST_ELEMENTS(area
->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 in area */
1471 int ospf_apiserver_is_ready_type11(struct ospf
*ospf
)
1473 /* Type 11 opaque LSA can be originated if there is at least one
1475 that has an active opaque-capable neighbor. */
1476 struct listnode
*node
, *nnode
;
1477 struct ospf_interface
*oi
;
1479 for (ALL_LIST_ELEMENTS(ospf
->oiflist
, node
, nnode
, oi
))
1480 /* Is there an active neighbor attached to this interface? */
1481 if (ospf_apiserver_is_ready_type9(oi
))
1484 /* No active neighbor at all */
1489 int ospf_apiserver_handle_originate_request(struct ospf_apiserver
*apiserv
,
1492 struct msg_originate_request
*omsg
;
1493 struct lsa_header
*data
;
1494 struct ospf_lsa
*new;
1495 struct ospf_lsa
*old
;
1496 struct ospf_area
*area
= NULL
;
1497 struct ospf_interface
*oi
= NULL
;
1498 struct ospf_lsdb
*lsdb
= NULL
;
1500 int lsa_type
, opaque_type
;
1504 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1506 /* Extract opaque LSA data from message */
1507 omsg
= (struct msg_originate_request
*)STREAM_DATA(msg
->s
);
1510 /* Determine interface for type9 or area for type10 LSAs. */
1511 switch (data
->type
) {
1512 case OSPF_OPAQUE_LINK_LSA
:
1513 oi
= ospf_apiserver_if_lookup_by_addr(omsg
->ifaddr
);
1515 zlog_warn("apiserver_originate: unknown interface %s",
1516 inet_ntoa(omsg
->ifaddr
));
1517 rc
= OSPF_API_NOSUCHINTERFACE
;
1523 case OSPF_OPAQUE_AREA_LSA
:
1524 area
= ospf_area_lookup_by_area_id(ospf
, omsg
->area_id
);
1526 zlog_warn("apiserver_originate: unknown area %s",
1527 inet_ntoa(omsg
->area_id
));
1528 rc
= OSPF_API_NOSUCHAREA
;
1533 case OSPF_OPAQUE_AS_LSA
:
1537 /* We can only handle opaque types here */
1539 "apiserver_originate: Cannot originate non-opaque LSA type %d",
1541 rc
= OSPF_API_ILLEGALLSATYPE
;
1545 /* Check if we registered this opaque type */
1546 lsa_type
= data
->type
;
1547 opaque_type
= GET_OPAQUE_TYPE(ntohl(data
->id
.s_addr
));
1549 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1552 "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered",
1553 lsa_type
, opaque_type
);
1554 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1558 /* Make sure that the neighbors are ready before we can originate */
1559 switch (data
->type
) {
1560 case OSPF_OPAQUE_LINK_LSA
:
1561 ready
= ospf_apiserver_is_ready_type9(oi
);
1563 case OSPF_OPAQUE_AREA_LSA
:
1564 ready
= ospf_apiserver_is_ready_type10(area
);
1566 case OSPF_OPAQUE_AS_LSA
:
1567 ready
= ospf_apiserver_is_ready_type11(ospf
);
1574 zlog_warn("Neighbors not ready to originate type %d",
1576 rc
= OSPF_API_NOTREADY
;
1580 /* Create OSPF's internal opaque LSA representation */
1581 new = ospf_apiserver_opaque_lsa_new(area
, oi
, data
);
1583 rc
= OSPF_API_NOMEMORY
; /* XXX */
1587 /* Determine if LSA is new or an update for an existing one. */
1588 old
= ospf_lsdb_lookup(lsdb
, new);
1591 /* New LSA install in LSDB. */
1592 rc
= ospf_apiserver_originate1(new);
1595 * Keep the new LSA instance in the "waiting place" until the
1597 * refresh timing. If several LSA update requests for the same
1599 * have issued by peer, the last one takes effect.
1601 new->lsdb
= &apiserv
->reserve
;
1602 ospf_lsdb_add(&apiserv
->reserve
, new);
1604 /* Kick the scheduler function. */
1605 ospf_opaque_lsa_refresh_schedule(old
);
1610 /* Send a reply back to client with return code */
1611 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1616 /* -----------------------------------------------------------
1617 * Flood an LSA within its flooding scope.
1618 * -----------------------------------------------------------
1621 /* XXX We can probably use ospf_flood_through instead of this function
1622 but then we need the neighbor parameter. If we set nbr to
1623 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1625 void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa
*lsa
)
1629 switch (lsa
->data
->type
) {
1630 case OSPF_OPAQUE_LINK_LSA
:
1631 /* Increment counters? XXX */
1633 /* Flood LSA through local network. */
1634 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1636 case OSPF_OPAQUE_AREA_LSA
:
1637 /* Update LSA origination count. */
1639 lsa
->area
->ospf
->lsa_originate_count
++;
1641 /* Flood LSA through area. */
1642 ospf_flood_through_area(lsa
->area
, NULL
/*nbr */, lsa
);
1644 case OSPF_OPAQUE_AS_LSA
: {
1647 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1650 /* Increment counters? XXX */
1652 /* Flood LSA through AS. */
1653 ospf_flood_through_as(ospf
, NULL
/*nbr */, lsa
);
1659 int ospf_apiserver_originate1(struct ospf_lsa
*lsa
)
1663 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1666 /* Install this LSA into LSDB. */
1667 if (ospf_lsa_install(ospf
, lsa
->oi
, lsa
) == NULL
) {
1668 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1669 "ospf_apiserver_originate1: ospf_lsa_install failed");
1673 /* Flood LSA within scope */
1677 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1678 * parameter, and thus it does not cause SIGSEGV error.
1680 ospf_flood_through(NULL
/*nbr */, lsa
);
1683 ospf_apiserver_flood_opaque_lsa(lsa
);
1690 /* Opaque LSAs of type 9 on a specific interface can now be
1691 originated. Tell clients that registered type 9. */
1692 int ospf_apiserver_lsa9_originator(void *arg
)
1694 struct ospf_interface
*oi
;
1696 oi
= (struct ospf_interface
*)arg
;
1697 if (listcount(apiserver_list
) > 0) {
1698 ospf_apiserver_clients_notify_ready_type9(oi
);
1703 int ospf_apiserver_lsa10_originator(void *arg
)
1705 struct ospf_area
*area
;
1707 area
= (struct ospf_area
*)arg
;
1708 if (listcount(apiserver_list
) > 0) {
1709 ospf_apiserver_clients_notify_ready_type10(area
);
1714 int ospf_apiserver_lsa11_originator(void *arg
)
1718 ospf
= (struct ospf
*)arg
;
1719 if (listcount(apiserver_list
) > 0) {
1720 ospf_apiserver_clients_notify_ready_type11(ospf
);
1726 /* Periodically refresh opaque LSAs so that they do not expire in
1728 struct ospf_lsa
*ospf_apiserver_lsa_refresher(struct ospf_lsa
*lsa
)
1730 struct ospf_apiserver
*apiserv
;
1731 struct ospf_lsa
*new = NULL
;
1736 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1739 apiserv
= lookup_apiserver_by_lsa(lsa
);
1742 "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
1745 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1749 if (IS_LSA_MAXAGE(lsa
)) {
1750 ospf_opaque_lsa_flush_schedule(lsa
);
1754 /* Check if updated version of LSA instance has already prepared. */
1755 new = ospf_lsdb_lookup(&apiserv
->reserve
, lsa
);
1757 /* This is a periodic refresh, driven by core OSPF mechanism. */
1758 new = ospf_apiserver_opaque_lsa_new(lsa
->area
, lsa
->oi
,
1762 "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1766 /* This is a forcible refresh, requested by OSPF-API client. */
1767 ospf_lsdb_delete(&apiserv
->reserve
, new);
1771 /* Increment sequence number */
1772 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1774 /* New LSA is in same area. */
1775 new->area
= lsa
->area
;
1776 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
1778 /* Install LSA into LSDB. */
1779 if (ospf_lsa_install(ospf
, new->oi
, new) == NULL
) {
1781 EC_OSPF_LSA_INSTALL_FAILURE
,
1782 "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1783 ospf_lsa_unlock(&new);
1787 /* Flood updated LSA through interface, area or AS */
1790 ospf_flood_through(NULL
/*nbr */, new);
1792 ospf_apiserver_flood_opaque_lsa(new);
1794 /* Debug logging. */
1795 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1796 zlog_debug("LSA[Type%d:%s]: Refresh Opaque LSA",
1797 new->data
->type
, inet_ntoa(new->data
->id
));
1798 ospf_lsa_header_dump(new->data
);
1806 /* -----------------------------------------------------------
1807 * Followings are functions to delete LSAs
1808 * -----------------------------------------------------------
1811 int ospf_apiserver_handle_delete_request(struct ospf_apiserver
*apiserv
,
1814 struct msg_delete_request
*dmsg
;
1815 struct ospf_lsa
*old
;
1816 struct ospf_area
*area
= NULL
;
1818 int lsa_type
, opaque_type
;
1822 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1825 /* Extract opaque LSA from message */
1826 dmsg
= (struct msg_delete_request
*)STREAM_DATA(msg
->s
);
1828 /* Lookup area for link-local and area-local opaque LSAs */
1829 switch (dmsg
->lsa_type
) {
1830 case OSPF_OPAQUE_LINK_LSA
:
1831 case OSPF_OPAQUE_AREA_LSA
:
1832 area
= ospf_area_lookup_by_area_id(ospf
, dmsg
->area_id
);
1834 zlog_warn("ospf_apiserver_lsa_delete: unknown area %s",
1835 inet_ntoa(dmsg
->area_id
));
1836 rc
= OSPF_API_NOSUCHAREA
;
1840 case OSPF_OPAQUE_AS_LSA
:
1841 /* AS-external opaque LSAs have no designated area */
1846 "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1848 rc
= OSPF_API_ILLEGALLSATYPE
;
1852 /* Check if we registered this opaque type */
1853 lsa_type
= dmsg
->lsa_type
;
1854 opaque_type
= dmsg
->opaque_type
;
1856 if (!apiserver_is_opaque_type_registered(apiserv
, lsa_type
,
1859 "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
1860 lsa_type
, opaque_type
);
1861 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1865 /* opaque_id is in network byte order */
1867 SET_OPAQUE_LSID(dmsg
->opaque_type
, ntohl(dmsg
->opaque_id
)));
1870 * Even if the target LSA has once scheduled to flush, it remains in
1871 * the LSDB until it is finally handled by the maxage remover thread.
1872 * Therefore, the lookup function below may return non-NULL result.
1874 old
= ospf_lsa_lookup(ospf
, area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1877 "ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1878 dmsg
->lsa_type
, inet_ntoa(id
));
1879 rc
= OSPF_API_NOSUCHLSA
;
1883 /* Schedule flushing of LSA from LSDB */
1884 /* NB: Multiple scheduling will produce a warning message, but harmless.
1886 ospf_opaque_lsa_flush_schedule(old
);
1890 /* Send reply back to client including return code */
1891 rc
= ospf_apiserver_send_reply(apiserv
, ntohl(msg
->hdr
.msgseq
), rc
);
1895 /* Flush self-originated opaque LSA */
1896 static int apiserver_flush_opaque_type_callback(struct ospf_lsa
*lsa
,
1897 void *p_arg
, int int_arg
)
1900 struct ospf_apiserver
*apiserv
;
1902 uint8_t opaque_type
;
1908 param
= (struct param_t
*)p_arg
;
1910 /* If LSA matches type and opaque type then delete it */
1911 if (IS_LSA_SELF(lsa
) && lsa
->data
->type
== param
->lsa_type
1912 && GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1913 == param
->opaque_type
) {
1914 ospf_opaque_lsa_flush_schedule(lsa
);
1919 /* Delete self-originated opaque LSAs of a given opaque type. This
1920 function is called when an application unregisters a given opaque
1921 type or a connection to an application closes and all those opaque
1922 LSAs need to be flushed the LSDB. */
1923 void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver
*apiserv
,
1924 uint8_t lsa_type
, uint8_t opaque_type
)
1927 struct ospf_apiserver
*apiserv
;
1929 uint8_t opaque_type
;
1931 struct listnode
*node
, *nnode
;
1933 struct ospf_area
*area
;
1935 ospf
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1938 /* Set parameter struct. */
1939 param
.apiserv
= apiserv
;
1940 param
.lsa_type
= lsa_type
;
1941 param
.opaque_type
= opaque_type
;
1944 struct route_node
*rn
;
1945 struct ospf_lsa
*lsa
;
1947 case OSPF_OPAQUE_LINK_LSA
:
1948 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
1949 LSDB_LOOP (OPAQUE_LINK_LSDB(area
), rn
, lsa
)
1950 apiserver_flush_opaque_type_callback(
1951 lsa
, (void *)¶m
, 0);
1953 case OSPF_OPAQUE_AREA_LSA
:
1954 for (ALL_LIST_ELEMENTS(ospf
->areas
, node
, nnode
, area
))
1955 LSDB_LOOP (OPAQUE_AREA_LSDB(area
), rn
, lsa
)
1956 apiserver_flush_opaque_type_callback(
1957 lsa
, (void *)¶m
, 0);
1959 case OSPF_OPAQUE_AS_LSA
:
1960 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf
), rn
, lsa
)
1961 apiserver_flush_opaque_type_callback(lsa
,
1971 /* -----------------------------------------------------------
1972 * Followings are callback functions to handle opaque types
1973 * -----------------------------------------------------------
1976 int ospf_apiserver_new_if(struct interface
*ifp
)
1978 struct ospf_interface
*oi
;
1980 /* For some strange reason it seems possible that we are invoked
1981 with an interface that has no name. This seems to happen during
1982 initialization. Return if this happens */
1984 if (ifp
->name
[0] == '\0') {
1985 /* interface has empty name */
1986 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1990 /* zlog_warn for debugging */
1991 zlog_warn("ospf_apiserver_new_if");
1992 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
1995 if (ifp
->name
[0] == '\0') {
1996 /* interface has empty name */
1997 zlog_warn("ospf_apiserver_new_if: interface has no name?");
2001 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2004 /* This interface is known to Zebra but not to OSPF daemon yet.
2007 "ospf_apiserver_new_if: interface %s not known to OSPFd?",
2014 /* New interface added to OSPF, tell clients about it */
2015 if (listcount(apiserver_list
) > 0) {
2016 ospf_apiserver_clients_notify_new_if(oi
);
2021 int ospf_apiserver_del_if(struct interface
*ifp
)
2023 struct ospf_interface
*oi
;
2025 /* zlog_warn for debugging */
2026 zlog_warn("ospf_apiserver_del_if");
2027 zlog_warn("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2030 oi
= ospf_apiserver_if_lookup_by_ifp(ifp
);
2033 /* This interface is known to Zebra but not to OSPF daemon
2034 anymore. No need to tell clients about it */
2038 /* Interface deleted, tell clients about it */
2039 if (listcount(apiserver_list
) > 0) {
2040 ospf_apiserver_clients_notify_del_if(oi
);
2045 void ospf_apiserver_ism_change(struct ospf_interface
*oi
, int old_state
)
2047 /* Tell clients about interface change */
2049 /* zlog_warn for debugging */
2050 zlog_warn("ospf_apiserver_ism_change");
2051 if (listcount(apiserver_list
) > 0) {
2052 ospf_apiserver_clients_notify_ism_change(oi
);
2055 zlog_warn("oi->ifp->name=%s", oi
->ifp
->name
);
2056 zlog_warn("old_state=%d", old_state
);
2057 zlog_warn("oi->state=%d", oi
->state
);
2060 void ospf_apiserver_nsm_change(struct ospf_neighbor
*nbr
, int old_status
)
2062 /* Neighbor status changed, tell clients about it */
2063 zlog_warn("ospf_apiserver_nsm_change");
2064 if (listcount(apiserver_list
) > 0) {
2065 ospf_apiserver_clients_notify_nsm_change(nbr
);
2069 void ospf_apiserver_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
2072 struct lsa_header header
;
2073 uint8_t data
[1]; /* opaque data have variable length. This is
2077 struct opaque_lsa
*olsa
;
2080 olsa
= (struct opaque_lsa
*)lsa
->data
;
2082 if (VALID_OPAQUE_INFO_LEN(lsa
->data
))
2083 opaquelen
= ntohs(lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2087 /* Output information about opaque LSAs */
2091 " Added using OSPF API: %u octets of opaque data %s\n",
2093 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2094 : "(Invalid length?)");
2095 vty_out(vty
, " Opaque data: ");
2097 for (i
= 0; i
< opaquelen
; i
++) {
2098 vty_out(vty
, "0x%x ", olsa
->data
[i
]);
2104 " Added using OSPF API: %u octets of opaque data %s",
2106 VALID_OPAQUE_INFO_LEN(lsa
->data
) ? ""
2107 : "(Invalid length?)");
2108 zlog_debug(" Opaque data: ");
2110 for (i
= 0; i
< opaquelen
; i
++) {
2111 zlog_debug("0x%x ", olsa
->data
[i
]);
2117 /* -----------------------------------------------------------
2118 * Followings are functions to notify clients about events
2119 * -----------------------------------------------------------
2122 /* Send a message to all clients. This is useful for messages
2123 that need to be notified to all clients (such as interface
2126 void ospf_apiserver_clients_notify_all(struct msg
*msg
)
2128 struct listnode
*node
, *nnode
;
2129 struct ospf_apiserver
*apiserv
;
2131 /* Send message to all clients */
2132 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
))
2133 ospf_apiserver_send_msg(apiserv
, msg
);
2136 /* An interface is now ready to accept opaque LSAs. Notify all
2137 clients that registered to use this opaque type */
2138 void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface
*oi
)
2140 struct listnode
*node
, *nnode
;
2142 struct ospf_apiserver
*apiserv
;
2146 zlog_warn("Interface has no address?");
2150 if (!ospf_apiserver_is_ready_type9(oi
)) {
2151 zlog_warn("Interface not ready for type 9?");
2155 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2156 struct listnode
*node2
, *nnode2
;
2157 struct registered_opaque_type
*r
;
2159 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2161 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
) {
2162 msg
= new_msg_ready_notify(
2163 0, OSPF_OPAQUE_LINK_LSA
, r
->opaque_type
,
2164 oi
->address
->u
.prefix4
);
2167 "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2169 /* Cannot allocate new message. What
2171 ospf_apiserver_free(apiserv
);
2176 ospf_apiserver_send_msg(apiserv
, msg
);
2186 void ospf_apiserver_clients_notify_ready_type10(struct ospf_area
*area
)
2188 struct listnode
*node
, *nnode
;
2190 struct ospf_apiserver
*apiserv
;
2194 if (!ospf_apiserver_is_ready_type10(area
)) {
2195 zlog_warn("Area not ready for type 10?");
2199 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2200 struct listnode
*node2
, *nnode2
;
2201 struct registered_opaque_type
*r
;
2203 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2205 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
) {
2206 msg
= new_msg_ready_notify(
2207 0, OSPF_OPAQUE_AREA_LSA
, r
->opaque_type
,
2211 "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2213 /* Cannot allocate new message. What
2215 ospf_apiserver_free(apiserv
);
2220 ospf_apiserver_send_msg(apiserv
, msg
);
2231 void ospf_apiserver_clients_notify_ready_type11(struct ospf
*top
)
2233 struct listnode
*node
, *nnode
;
2235 struct in_addr id_null
= {.s_addr
= 0L};
2236 struct ospf_apiserver
*apiserv
;
2240 if (!ospf_apiserver_is_ready_type11(top
)) {
2241 zlog_warn("AS not ready for type 11?");
2245 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2246 struct listnode
*node2
, *nnode2
;
2247 struct registered_opaque_type
*r
;
2249 for (ALL_LIST_ELEMENTS(apiserv
->opaque_types
, node2
, nnode2
,
2251 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
) {
2252 msg
= new_msg_ready_notify(
2253 0, OSPF_OPAQUE_AS_LSA
, r
->opaque_type
,
2257 "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2259 /* Cannot allocate new message. What
2261 ospf_apiserver_free(apiserv
);
2266 ospf_apiserver_send_msg(apiserv
, msg
);
2276 void ospf_apiserver_clients_notify_new_if(struct ospf_interface
*oi
)
2280 msg
= new_msg_new_if(0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2282 ospf_apiserver_clients_notify_all(msg
);
2287 void ospf_apiserver_clients_notify_del_if(struct ospf_interface
*oi
)
2291 msg
= new_msg_del_if(0, oi
->address
->u
.prefix4
);
2293 ospf_apiserver_clients_notify_all(msg
);
2298 void ospf_apiserver_clients_notify_ism_change(struct ospf_interface
*oi
)
2301 struct in_addr ifaddr
= {.s_addr
= 0L};
2302 struct in_addr area_id
= {.s_addr
= 0L};
2308 ifaddr
= oi
->address
->u
.prefix4
;
2311 area_id
= oi
->area
->area_id
;
2314 msg
= new_msg_ism_change(0, ifaddr
, area_id
, oi
->state
);
2317 "apiserver_clients_notify_ism_change: msg_new failed");
2321 ospf_apiserver_clients_notify_all(msg
);
2325 void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor
*nbr
)
2328 struct in_addr ifaddr
;
2329 struct in_addr nbraddr
;
2333 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2335 nbraddr
= nbr
->address
.u
.prefix4
;
2337 msg
= new_msg_nsm_change(0, ifaddr
, nbraddr
, nbr
->router_id
,
2341 "apiserver_clients_notify_nsm_change: msg_new failed");
2345 ospf_apiserver_clients_notify_all(msg
);
2349 static void apiserver_clients_lsa_change_notify(uint8_t msgtype
,
2350 struct ospf_lsa
*lsa
)
2353 struct listnode
*node
, *nnode
;
2354 struct ospf_apiserver
*apiserv
;
2356 /* Default area for AS-External and Opaque11 LSAs */
2357 struct in_addr area_id
= {.s_addr
= 0L};
2359 /* Default interface for non Opaque9 LSAs */
2360 struct in_addr ifaddr
= {.s_addr
= 0L};
2363 area_id
= lsa
->area
->area_id
;
2365 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2367 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2370 /* Prepare message that can be sent to clients that have a matching
2372 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2374 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2377 "apiserver_clients_lsa_change_notify: msg_new failed");
2381 /* Now send message to all clients with a matching filter */
2382 for (ALL_LIST_ELEMENTS(apiserver_list
, node
, nnode
, apiserv
)) {
2383 struct lsa_filter_type
*filter
;
2388 /* Check filter for this client. */
2389 filter
= apiserv
->filter
;
2391 /* Check area IDs in case of non AS-E LSAs.
2392 * If filter has areas (num_areas > 0),
2393 * then one of the areas must match the area ID of this LSA. */
2395 i
= filter
->num_areas
;
2396 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
)
2397 || (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
)) {
2402 area
= (uint32_t *)(filter
+ 1);
2404 if (*area
== area_id
.s_addr
) {
2415 /* Area match. Check LSA type. */
2416 mask
= ntohs(filter
->typemask
);
2418 if (mask
& Power2
[lsa
->data
->type
]) {
2419 /* Type also matches. Check origin. */
2420 if ((filter
->origin
== ANY_ORIGIN
)
2421 || (filter
->origin
== IS_LSA_SELF(lsa
))) {
2422 ospf_apiserver_send_msg(apiserv
, msg
);
2427 /* Free message since it is not used anymore */
2432 /* -------------------------------------------------------------
2433 * Followings are hooks invoked when LSAs are updated or deleted
2434 * -------------------------------------------------------------
2438 static int apiserver_notify_clients_lsa(uint8_t msgtype
, struct ospf_lsa
*lsa
)
2441 /* default area for AS-External and Opaque11 LSAs */
2442 struct in_addr area_id
= {.s_addr
= 0L};
2444 /* default interface for non Opaque9 LSAs */
2445 struct in_addr ifaddr
= {.s_addr
= 0L};
2447 /* Only notify this update if the LSA's age is smaller than
2448 MAXAGE. Otherwise clients would see LSA updates with max age just
2449 before they are deleted from the LSDB. LSA delete messages have
2450 MAXAGE too but should not be filtered. */
2451 if (IS_LSA_MAXAGE(lsa
) && (msgtype
== MSG_LSA_UPDATE_NOTIFY
)) {
2456 area_id
= lsa
->area
->area_id
;
2458 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
) {
2459 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2461 msg
= new_msg_lsa_change_notify(msgtype
, 0L, /* no sequence number */
2463 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2465 zlog_warn("notify_clients_lsa: msg_new failed");
2468 /* Notify all clients that new LSA is added/updated */
2469 apiserver_clients_lsa_change_notify(msgtype
, lsa
);
2471 /* Clients made their own copies of msg so we can free msg here */
2477 int ospf_apiserver_lsa_update(struct ospf_lsa
*lsa
)
2479 return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY
, lsa
);
2482 int ospf_apiserver_lsa_delete(struct ospf_lsa
*lsa
)
2484 return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY
, lsa
);
2487 #endif /* SUPPORT_OSPF_API */