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
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 #ifdef SUPPORT_OSPF_API
26 #ifndef HAVE_OPAQUE_LSA
27 #error "Core Opaque-LSA module must be configured."
28 #endif /* HAVE_OPAQUE_LSA */
41 #include "sockunion.h" /* for inet_aton() */
44 #include <sys/types.h>
46 #include "ospfd/ospfd.h" /* for "struct thread_master" */
47 #include "ospfd/ospf_interface.h"
48 #include "ospfd/ospf_ism.h"
49 #include "ospfd/ospf_asbr.h"
50 #include "ospfd/ospf_lsa.h"
51 #include "ospfd/ospf_lsdb.h"
52 #include "ospfd/ospf_neighbor.h"
53 #include "ospfd/ospf_nsm.h"
54 #include "ospfd/ospf_flood.h"
55 #include "ospfd/ospf_packet.h"
56 #include "ospfd/ospf_spf.h"
57 #include "ospfd/ospf_dump.h"
58 #include "ospfd/ospf_route.h"
59 #include "ospfd/ospf_ase.h"
60 #include "ospfd/ospf_zebra.h"
62 #include "ospfd/ospf_api.h"
63 #include "ospfd/ospf_apiserver.h"
65 /* This is an implementation of an API to the OSPF daemon that allows
66 * external applications to access the OSPF daemon through socket
67 * connections. The application can use this API to inject its own
68 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
69 * daemons then receive these LSAs and inform applications through the
70 * API by sending a corresponding message. The application can also
71 * register to receive all LSA types (in addition to opaque types) and
72 * use this information to reconstruct the OSPF's LSDB. The OSPF
73 * daemon supports multiple applications concurrently. */
75 /* List of all active connections. */
76 struct list
*apiserver_list
;
78 /* -----------------------------------------------------------
79 * Functions to lookup interfaces
80 * -----------------------------------------------------------
83 struct ospf_interface
*
84 ospf_apiserver_if_lookup_by_addr (struct in_addr address
)
86 struct listnode
*node
, *nnode
;
87 struct ospf_interface
*oi
;
90 if (!(ospf
= ospf_lookup ()))
93 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
94 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
95 if (IPV4_ADDR_SAME (&address
, &oi
->address
->u
.prefix4
))
101 struct ospf_interface
*
102 ospf_apiserver_if_lookup_by_ifp (struct interface
*ifp
)
104 struct listnode
*node
, *nnode
;
105 struct ospf_interface
*oi
;
108 if (!(ospf
= ospf_lookup ()));
111 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
118 /* -----------------------------------------------------------
120 * -----------------------------------------------------------
124 ospf_apiserver_getport (void)
126 struct servent
*sp
= getservbyname ("ospfapi", "tcp");
128 return sp
? ntohs (sp
->s_port
) : OSPF_API_SYNC_PORT
;
131 /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
133 ospf_apiserver_init (void)
138 /* Create new socket for synchronous messages. */
139 fd
= ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET
);
144 /* Schedule new thread that handles accepted connections. */
145 ospf_apiserver_event (OSPF_APISERVER_ACCEPT
, fd
, NULL
);
147 /* Initialize list that keeps track of all connections. */
148 apiserver_list
= list_new ();
150 /* Register opaque-independent call back functions. These functions
151 are invoked on ISM, NSM changes and LSA update and LSA deletes */
153 ospf_register_opaque_functab (0 /* all LSAs */,
154 0 /* all opaque types */,
155 ospf_apiserver_new_if
,
156 ospf_apiserver_del_if
,
157 ospf_apiserver_ism_change
,
158 ospf_apiserver_nsm_change
,
162 NULL
, /* ospf_apiserver_show_info */
163 NULL
, /* originator_func */
164 NULL
, /* ospf_apiserver_lsa_refresher */
165 ospf_apiserver_lsa_update
,
166 ospf_apiserver_lsa_delete
);
169 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
178 /* Terminate OSPF API module. */
180 ospf_apiserver_term (void)
182 struct ospf_apiserver
*apiserv
;
184 /* Unregister wildcard [0/0] type */
185 ospf_delete_opaque_functab (0 /* all LSAs */,
186 0 /* all opaque types */);
189 * Free all client instances. ospf_apiserver_free removes the node
190 * from the list, so we examine the head of the list anew each time.
192 while ( (apiserv
= listgetdata (listhead (apiserver_list
))) != NULL
)
193 ospf_apiserver_free (apiserv
);
195 /* Free client list itself */
196 list_delete (apiserver_list
);
198 /* Free wildcard list */
202 static struct ospf_apiserver
*
203 lookup_apiserver (u_char lsa_type
, u_char opaque_type
)
205 struct listnode
*n1
, *n2
;
206 struct registered_opaque_type
*r
;
207 struct ospf_apiserver
*apiserv
, *found
= NULL
;
209 /* XXX: this approaches O(n**2) */
210 for (ALL_LIST_ELEMENTS_RO (apiserver_list
, n1
, apiserv
))
212 for (ALL_LIST_ELEMENTS_RO (apiserv
->opaque_types
, n2
, r
))
213 if (r
->lsa_type
== lsa_type
&& r
->opaque_type
== opaque_type
)
223 static struct ospf_apiserver
*
224 lookup_apiserver_by_lsa (struct ospf_lsa
*lsa
)
226 struct lsa_header
*lsah
= lsa
->data
;
227 struct ospf_apiserver
*found
= NULL
;
229 if (IS_OPAQUE_LSA (lsah
->type
))
231 found
= lookup_apiserver (lsah
->type
,
232 GET_OPAQUE_TYPE (ntohl (lsah
->id
.s_addr
)));
237 /* -----------------------------------------------------------
238 * Followings are functions to manage client connections.
239 * -----------------------------------------------------------
242 ospf_apiserver_new_lsa_hook (struct ospf_lsa
*lsa
)
244 if (IS_DEBUG_OSPF_EVENT
)
245 zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa
, dump_lsa_key (lsa
), lsa
->lsdb
->total
);
250 ospf_apiserver_del_lsa_hook (struct ospf_lsa
*lsa
)
252 if (IS_DEBUG_OSPF_EVENT
)
253 zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa
, dump_lsa_key (lsa
), lsa
->lsdb
->total
);
257 /* Allocate new connection structure. */
258 struct ospf_apiserver
*
259 ospf_apiserver_new (int fd_sync
, int fd_async
)
261 struct ospf_apiserver
*new =
262 XMALLOC (MTYPE_OSPF_APISERVER
, sizeof (struct ospf_apiserver
));
265 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER
, sizeof (struct lsa_filter_type
));
267 new->fd_sync
= fd_sync
;
268 new->fd_async
= fd_async
;
270 /* list of registered opaque types that application uses */
271 new->opaque_types
= list_new ();
273 /* Initialize temporary strage for LSA instances to be refreshed. */
274 memset (&new->reserve
, 0, sizeof (struct ospf_lsdb
));
275 ospf_lsdb_init (&new->reserve
);
277 new->reserve
.new_lsa_hook
= ospf_apiserver_new_lsa_hook
; /* debug */
278 new->reserve
.del_lsa_hook
= ospf_apiserver_del_lsa_hook
; /* debug */
280 new->out_sync_fifo
= msg_fifo_new ();
281 new->out_async_fifo
= msg_fifo_new ();
282 new->t_sync_read
= NULL
;
283 #ifdef USE_ASYNC_READ
284 new->t_async_read
= NULL
;
285 #endif /* USE_ASYNC_READ */
286 new->t_sync_write
= NULL
;
287 new->t_async_write
= NULL
;
289 new->filter
->typemask
= 0; /* filter all LSAs */
290 new->filter
->origin
= ANY_ORIGIN
;
291 new->filter
->num_areas
= 0;
297 ospf_apiserver_event (enum event event
, int fd
,
298 struct ospf_apiserver
*apiserv
)
300 struct thread
*apiserver_serv_thread
;
304 case OSPF_APISERVER_ACCEPT
:
305 apiserver_serv_thread
=
306 thread_add_read (master
, ospf_apiserver_accept
, apiserv
, fd
);
308 case OSPF_APISERVER_SYNC_READ
:
309 apiserv
->t_sync_read
=
310 thread_add_read (master
, ospf_apiserver_read
, apiserv
, fd
);
312 #ifdef USE_ASYNC_READ
313 case OSPF_APISERVER_ASYNC_READ
:
314 apiserv
->t_async_read
=
315 thread_add_read (master
, ospf_apiserver_read
, apiserv
, fd
);
317 #endif /* USE_ASYNC_READ */
318 case OSPF_APISERVER_SYNC_WRITE
:
319 if (!apiserv
->t_sync_write
)
321 apiserv
->t_sync_write
=
322 thread_add_write (master
, ospf_apiserver_sync_write
, apiserv
, fd
);
325 case OSPF_APISERVER_ASYNC_WRITE
:
326 if (!apiserv
->t_async_write
)
328 apiserv
->t_async_write
=
329 thread_add_write (master
, ospf_apiserver_async_write
, apiserv
, fd
);
335 /* Free instance. First unregister all opaque types used by
336 application, flush opaque LSAs injected by application
337 from network and close connection. */
339 ospf_apiserver_free (struct ospf_apiserver
*apiserv
)
341 struct listnode
*node
;
343 /* Cancel read and write threads. */
344 if (apiserv
->t_sync_read
)
346 thread_cancel (apiserv
->t_sync_read
);
348 #ifdef USE_ASYNC_READ
349 if (apiserv
->t_async_read
)
351 thread_cancel (apiserv
->t_async_read
);
353 #endif /* USE_ASYNC_READ */
354 if (apiserv
->t_sync_write
)
356 thread_cancel (apiserv
->t_sync_write
);
359 if (apiserv
->t_async_write
)
361 thread_cancel (apiserv
->t_async_write
);
364 /* Unregister all opaque types that application registered
365 and flush opaque LSAs if still in LSDB. */
367 while ((node
= listhead (apiserv
->opaque_types
)) != NULL
)
369 struct registered_opaque_type
*regtype
= listgetdata(node
);
371 ospf_apiserver_unregister_opaque_type (apiserv
, regtype
->lsa_type
,
372 regtype
->opaque_type
);
376 /* Close connections to OSPFd. */
377 if (apiserv
->fd_sync
> 0)
379 close (apiserv
->fd_sync
);
382 if (apiserv
->fd_async
> 0)
384 close (apiserv
->fd_async
);
388 msg_fifo_free (apiserv
->out_sync_fifo
);
389 msg_fifo_free (apiserv
->out_async_fifo
);
391 /* Clear temporary strage for LSA instances to be refreshed. */
392 ospf_lsdb_delete_all (&apiserv
->reserve
);
393 ospf_lsdb_cleanup (&apiserv
->reserve
);
395 /* Remove from the list of active clients. */
396 listnode_delete (apiserver_list
, apiserv
);
398 if (IS_DEBUG_OSPF_EVENT
)
399 zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv
, apiserver_list
->count
);
401 /* And free instance. */
402 XFREE (MTYPE_OSPF_APISERVER
, apiserv
);
406 ospf_apiserver_read (struct thread
*thread
)
408 struct ospf_apiserver
*apiserv
;
414 apiserv
= THREAD_ARG (thread
);
415 fd
= THREAD_FD (thread
);
417 if (fd
== apiserv
->fd_sync
)
419 event
= OSPF_APISERVER_SYNC_READ
;
420 apiserv
->t_sync_read
= NULL
;
422 if (IS_DEBUG_OSPF_EVENT
)
423 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
424 inet_ntoa (apiserv
->peer_sync
.sin_addr
),
425 ntohs (apiserv
->peer_sync
.sin_port
));
427 #ifdef USE_ASYNC_READ
428 else if (fd
== apiserv
->fd_async
)
430 event
= OSPF_APISERVER_ASYNC_READ
;
431 apiserv
->t_async_read
= NULL
;
433 if (IS_DEBUG_OSPF_EVENT
)
434 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
435 inet_ntoa (apiserv
->peer_async
.sin_addr
),
436 ntohs (apiserv
->peer_async
.sin_port
));
438 #endif /* USE_ASYNC_READ */
441 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd
);
442 ospf_apiserver_free (apiserv
);
446 /* Read message from fd. */
451 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd
);
453 /* Perform cleanup. */
454 ospf_apiserver_free (apiserv
);
458 if (IS_DEBUG_OSPF_EVENT
)
461 /* Dispatch to corresponding message handler. */
462 rc
= ospf_apiserver_handle_msg (apiserv
, msg
);
464 /* Prepare for next message, add read thread. */
465 ospf_apiserver_event (event
, fd
, apiserv
);
474 ospf_apiserver_sync_write (struct thread
*thread
)
476 struct ospf_apiserver
*apiserv
;
481 apiserv
= THREAD_ARG (thread
);
483 fd
= THREAD_FD (thread
);
485 apiserv
->t_sync_write
= NULL
;
488 if (fd
!= apiserv
->fd_sync
)
490 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd
);
494 if (IS_DEBUG_OSPF_EVENT
)
495 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
496 inet_ntoa (apiserv
->peer_sync
.sin_addr
),
497 ntohs (apiserv
->peer_sync
.sin_port
));
499 /* Check whether there is really a message in the fifo. */
500 msg
= msg_fifo_pop (apiserv
->out_sync_fifo
);
503 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
507 if (IS_DEBUG_OSPF_EVENT
)
510 rc
= msg_write (fd
, msg
);
512 /* Once a message is dequeued, it should be freed anyway. */
518 ("ospf_apiserver_sync_write: write failed on fd=%d", fd
);
523 /* If more messages are in sync message fifo, schedule write thread. */
524 if (msg_fifo_head (apiserv
->out_sync_fifo
))
526 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE
, apiserv
->fd_sync
,
534 /* Perform cleanup and disconnect with peer */
535 ospf_apiserver_free (apiserv
);
543 ospf_apiserver_async_write (struct thread
*thread
)
545 struct ospf_apiserver
*apiserv
;
550 apiserv
= THREAD_ARG (thread
);
552 fd
= THREAD_FD (thread
);
554 apiserv
->t_async_write
= NULL
;
557 if (fd
!= apiserv
->fd_async
)
559 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd
);
563 if (IS_DEBUG_OSPF_EVENT
)
564 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
565 inet_ntoa (apiserv
->peer_async
.sin_addr
),
566 ntohs (apiserv
->peer_async
.sin_port
));
568 /* Check whether there is really a message in the fifo. */
569 msg
= msg_fifo_pop (apiserv
->out_async_fifo
);
572 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
576 if (IS_DEBUG_OSPF_EVENT
)
579 rc
= msg_write (fd
, msg
);
581 /* Once a message is dequeued, it should be freed anyway. */
587 ("ospf_apiserver_async_write: write failed on fd=%d", fd
);
592 /* If more messages are in async message fifo, schedule write thread. */
593 if (msg_fifo_head (apiserv
->out_async_fifo
))
595 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE
, apiserv
->fd_async
,
603 /* Perform cleanup and disconnect with peer */
604 ospf_apiserver_free (apiserv
);
612 ospf_apiserver_serv_sock_family (unsigned short port
, int family
)
618 memset (&su
, 0, sizeof (union sockunion
));
619 su
.sa
.sa_family
= family
;
621 /* Make new socket */
622 accept_sock
= sockunion_stream_socket (&su
);
626 /* This is a server, so reuse address and port */
627 sockopt_reuseaddr (accept_sock
);
628 sockopt_reuseport (accept_sock
);
630 /* Bind socket to address and given port. */
631 rc
= sockunion_bind (accept_sock
, &su
, port
, NULL
);
634 close (accept_sock
); /* Close socket */
638 /* Listen socket under queue length 3. */
639 rc
= listen (accept_sock
, 3);
642 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
643 safe_strerror (errno
));
644 close (accept_sock
); /* Close socket */
651 /* Accept connection request from external applications. For each
652 accepted connection allocate own connection instance. */
654 ospf_apiserver_accept (struct thread
*thread
)
660 struct ospf_apiserver
*apiserv
;
661 struct sockaddr_in peer_async
;
662 struct sockaddr_in peer_sync
;
666 /* THREAD_ARG (thread) is NULL */
667 accept_sock
= THREAD_FD (thread
);
669 /* Keep hearing on socket for further connections. */
670 ospf_apiserver_event (OSPF_APISERVER_ACCEPT
, accept_sock
, NULL
);
672 memset (&su
, 0, sizeof (union sockunion
));
673 /* Accept connection for synchronous messages */
674 new_sync_sock
= sockunion_accept (accept_sock
, &su
);
675 if (new_sync_sock
< 0)
677 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno
));
681 /* Get port address and port number of peer to make reverse connection.
682 The reverse channel uses the port number of the peer port+1. */
684 memset(&peer_sync
, 0, sizeof(struct sockaddr_in
));
685 peerlen
= sizeof (struct sockaddr_in
);
687 ret
= getpeername (new_sync_sock
, (struct sockaddr
*)&peer_sync
, &peerlen
);
690 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno
));
691 close (new_sync_sock
);
695 if (IS_DEBUG_OSPF_EVENT
)
696 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
697 inet_ntoa (peer_sync
.sin_addr
), ntohs (peer_sync
.sin_port
));
699 /* Create new socket for asynchronous messages. */
700 peer_async
= peer_sync
;
701 peer_async
.sin_port
= htons(ntohs(peer_sync
.sin_port
) + 1);
703 /* Check if remote port number to make reverse connection is valid one. */
704 if (ntohs (peer_async
.sin_port
) == ospf_apiserver_getport ())
706 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
707 inet_ntoa (peer_async
.sin_addr
), ntohs (peer_async
.sin_port
));
708 close (new_sync_sock
);
712 new_async_sock
= socket (AF_INET
, SOCK_STREAM
, 0);
713 if (new_async_sock
< 0)
715 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno
));
716 close (new_sync_sock
);
720 ret
= connect (new_async_sock
, (struct sockaddr
*) &peer_async
,
721 sizeof (struct sockaddr_in
));
725 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno
));
726 close (new_sync_sock
);
727 close (new_async_sock
);
731 #ifdef USE_ASYNC_READ
732 #else /* USE_ASYNC_READ */
733 /* Make the asynchronous channel write-only. */
734 ret
= shutdown (new_async_sock
, SHUT_RD
);
737 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno
));
738 close (new_sync_sock
);
739 close (new_async_sock
);
742 #endif /* USE_ASYNC_READ */
744 /* Allocate new server-side connection structure */
745 apiserv
= ospf_apiserver_new (new_sync_sock
, new_async_sock
);
747 /* Add to active connection list */
748 listnode_add (apiserver_list
, apiserv
);
749 apiserv
->peer_sync
= peer_sync
;
750 apiserv
->peer_async
= peer_async
;
752 /* And add read threads for new connection */
753 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ
, new_sync_sock
, apiserv
);
754 #ifdef USE_ASYNC_READ
755 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ
, new_async_sock
, apiserv
);
756 #endif /* USE_ASYNC_READ */
758 if (IS_DEBUG_OSPF_EVENT
)
759 zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv
, apiserver_list
->count
);
765 /* -----------------------------------------------------------
766 * Send reply with return code to client application
767 * -----------------------------------------------------------
771 ospf_apiserver_send_msg (struct ospf_apiserver
*apiserv
, struct msg
*msg
)
773 struct msg_fifo
*fifo
;
778 switch (msg
->hdr
.msgtype
)
781 fifo
= apiserv
->out_sync_fifo
;
782 fd
= apiserv
->fd_sync
;
783 event
= OSPF_APISERVER_SYNC_WRITE
;
785 case MSG_READY_NOTIFY
:
786 case MSG_LSA_UPDATE_NOTIFY
:
787 case MSG_LSA_DELETE_NOTIFY
:
792 fifo
= apiserv
->out_async_fifo
;
793 fd
= apiserv
->fd_async
;
794 event
= OSPF_APISERVER_ASYNC_WRITE
;
797 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
802 /* Make a copy of the message and put in the fifo. Once the fifo
803 gets drained by the write thread, the message will be freed. */
804 /* NB: Given "msg" is untouched in this function. */
805 msg2
= msg_dup (msg
);
807 /* Enqueue message into corresponding fifo queue */
808 msg_fifo_push (fifo
, msg2
);
810 /* Schedule write thread */
811 ospf_apiserver_event (event
, fd
, apiserv
);
816 ospf_apiserver_send_reply (struct ospf_apiserver
*apiserv
, u_int32_t seqnr
,
819 struct msg
*msg
= new_msg_reply (seqnr
, rc
);
824 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
826 /* Cannot allocate new message. What should we do? */
827 ospf_apiserver_free (apiserv
);
832 ret
= ospf_apiserver_send_msg (apiserv
, msg
);
838 /* -----------------------------------------------------------
839 * Generic message dispatching handler function
840 * -----------------------------------------------------------
844 ospf_apiserver_handle_msg (struct ospf_apiserver
*apiserv
, struct msg
*msg
)
848 /* Call corresponding message handler function. */
849 switch (msg
->hdr
.msgtype
)
851 case MSG_REGISTER_OPAQUETYPE
:
852 rc
= ospf_apiserver_handle_register_opaque_type (apiserv
, msg
);
854 case MSG_UNREGISTER_OPAQUETYPE
:
855 rc
= ospf_apiserver_handle_unregister_opaque_type (apiserv
, msg
);
857 case MSG_REGISTER_EVENT
:
858 rc
= ospf_apiserver_handle_register_event (apiserv
, msg
);
861 rc
= ospf_apiserver_handle_sync_lsdb (apiserv
, msg
);
863 case MSG_ORIGINATE_REQUEST
:
864 rc
= ospf_apiserver_handle_originate_request (apiserv
, msg
);
866 case MSG_DELETE_REQUEST
:
867 rc
= ospf_apiserver_handle_delete_request (apiserv
, msg
);
870 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
878 /* -----------------------------------------------------------
879 * Following are functions for opaque type registration
880 * -----------------------------------------------------------
884 ospf_apiserver_register_opaque_type (struct ospf_apiserver
*apiserv
,
885 u_char lsa_type
, u_char opaque_type
)
887 struct registered_opaque_type
*regtype
;
888 int (*originator_func
) (void *arg
);
893 case OSPF_OPAQUE_LINK_LSA
:
894 originator_func
= ospf_apiserver_lsa9_originator
;
896 case OSPF_OPAQUE_AREA_LSA
:
897 originator_func
= ospf_apiserver_lsa10_originator
;
899 case OSPF_OPAQUE_AS_LSA
:
900 originator_func
= ospf_apiserver_lsa11_originator
;
903 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
905 return OSPF_API_ILLEGALLSATYPE
;
909 /* Register opaque function table */
910 /* NB: Duplicated registration will be detected inside the function. */
912 ospf_register_opaque_functab (lsa_type
, opaque_type
,
913 NULL
, /* ospf_apiserver_new_if */
914 NULL
, /* ospf_apiserver_del_if */
915 NULL
, /* ospf_apiserver_ism_change */
916 NULL
, /* ospf_apiserver_nsm_change */
920 ospf_apiserver_show_info
,
922 ospf_apiserver_lsa_refresher
,
923 NULL
, /* ospf_apiserver_lsa_update */
924 NULL
/* ospf_apiserver_lsa_delete */);
928 zlog_warn ("Failed to register opaque type [%d/%d]",
929 lsa_type
, opaque_type
);
930 return OSPF_API_OPAQUETYPEINUSE
;
933 /* Remember the opaque type that application registers so when
934 connection shuts down, we can flush all LSAs of this opaque
938 XMALLOC (MTYPE_OSPF_APISERVER
, sizeof (struct registered_opaque_type
));
939 memset (regtype
, 0, sizeof (struct registered_opaque_type
));
940 regtype
->lsa_type
= lsa_type
;
941 regtype
->opaque_type
= opaque_type
;
943 /* Add to list of registered opaque types */
944 listnode_add (apiserv
->opaque_types
, regtype
);
946 if (IS_DEBUG_OSPF_EVENT
)
947 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
948 " apiserv(%p), total#(%d)",
949 lsa_type
, opaque_type
, apiserv
,
950 listcount (apiserv
->opaque_types
));
956 ospf_apiserver_unregister_opaque_type (struct ospf_apiserver
*apiserv
,
957 u_char lsa_type
, u_char opaque_type
)
959 struct listnode
*node
, *nnode
;
960 struct registered_opaque_type
*regtype
;
962 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node
, nnode
, regtype
))
964 /* Check if we really registered this opaque type */
965 if (regtype
->lsa_type
== lsa_type
&&
966 regtype
->opaque_type
== opaque_type
)
969 /* Yes, we registered this opaque type. Flush
970 all existing opaque LSAs of this type */
972 ospf_apiserver_flush_opaque_lsa (apiserv
, lsa_type
, opaque_type
);
973 ospf_delete_opaque_functab (lsa_type
, opaque_type
);
975 /* Remove from list of registered opaque types */
976 listnode_delete (apiserv
->opaque_types
, regtype
);
978 if (IS_DEBUG_OSPF_EVENT
)
979 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
980 " from apiserv(%p), total#(%d)",
981 lsa_type
, opaque_type
, apiserv
,
982 listcount (apiserv
->opaque_types
));
988 /* Opaque type is not registered */
989 zlog_warn ("Failed to unregister opaque type [%d/%d]",
990 lsa_type
, opaque_type
);
991 return OSPF_API_OPAQUETYPENOTREGISTERED
;
996 apiserver_is_opaque_type_registered (struct ospf_apiserver
*apiserv
,
997 u_char lsa_type
, u_char opaque_type
)
999 struct listnode
*node
, *nnode
;
1000 struct registered_opaque_type
*regtype
;
1002 /* XXX: how many types are there? if few, why not just a bitmap? */
1003 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node
, nnode
, regtype
))
1005 /* Check if we really registered this opaque type */
1006 if (regtype
->lsa_type
== lsa_type
&&
1007 regtype
->opaque_type
== opaque_type
)
1009 /* Yes registered */
1013 /* Not registered */
1018 ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver
*apiserv
,
1021 struct msg_register_opaque_type
*rmsg
;
1026 /* Extract parameters from register opaque type message */
1027 rmsg
= (struct msg_register_opaque_type
*) STREAM_DATA (msg
->s
);
1029 lsa_type
= rmsg
->lsatype
;
1030 opaque_type
= rmsg
->opaquetype
;
1032 rc
= ospf_apiserver_register_opaque_type (apiserv
, lsa_type
, opaque_type
);
1034 /* Send a reply back to client including return code */
1035 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1039 /* Now inform application about opaque types that are ready */
1042 case OSPF_OPAQUE_LINK_LSA
:
1043 ospf_apiserver_notify_ready_type9 (apiserv
);
1045 case OSPF_OPAQUE_AREA_LSA
:
1046 ospf_apiserver_notify_ready_type10 (apiserv
);
1048 case OSPF_OPAQUE_AS_LSA
:
1049 ospf_apiserver_notify_ready_type11 (apiserv
);
1057 /* Notify specific client about all opaque types 9 that are ready. */
1059 ospf_apiserver_notify_ready_type9 (struct ospf_apiserver
*apiserv
)
1061 struct listnode
*node
, *nnode
;
1062 struct listnode
*node2
, *nnode2
;
1064 struct ospf_interface
*oi
;
1065 struct registered_opaque_type
*r
;
1067 ospf
= ospf_lookup ();
1069 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
1071 /* Check if this interface is indeed ready for type 9 */
1072 if (!ospf_apiserver_is_ready_type9 (oi
))
1075 /* Check for registered opaque type 9 types */
1076 /* XXX: loop-de-loop - optimise me */
1077 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
1081 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
)
1084 /* Yes, this opaque type is ready */
1085 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA
,
1087 oi
->address
->u
.prefix4
);
1090 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1092 /* Cannot allocate new message. What should we do? */
1093 ospf_apiserver_free (apiserv
);
1097 ospf_apiserver_send_msg (apiserv
, msg
);
1108 /* Notify specific client about all opaque types 10 that are ready. */
1110 ospf_apiserver_notify_ready_type10 (struct ospf_apiserver
*apiserv
)
1112 struct listnode
*node
, *nnode
;
1113 struct listnode
*node2
, *nnode2
;
1115 struct ospf_area
*area
;
1117 ospf
= ospf_lookup ();
1119 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
1121 struct registered_opaque_type
*r
;
1123 if (!ospf_apiserver_is_ready_type10 (area
))
1128 /* Check for registered opaque type 10 types */
1129 /* XXX: loop in loop - optimise me */
1130 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
1134 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
)
1136 /* Yes, this opaque type is ready */
1138 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA
,
1139 r
->opaque_type
, area
->area_id
);
1142 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1144 /* Cannot allocate new message. What should we do? */
1145 ospf_apiserver_free (apiserv
);
1149 ospf_apiserver_send_msg (apiserv
, msg
);
1159 /* Notify specific client about all opaque types 11 that are ready */
1161 ospf_apiserver_notify_ready_type11 (struct ospf_apiserver
*apiserv
)
1163 struct listnode
*node
, *nnode
;
1165 struct registered_opaque_type
*r
;
1167 ospf
= ospf_lookup ();
1169 /* Can type 11 be originated? */
1170 if (!ospf_apiserver_is_ready_type11 (ospf
))
1173 /* Check for registered opaque type 11 types */
1174 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node
, nnode
, r
))
1177 struct in_addr noarea_id
= { 0L };
1179 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
)
1181 /* Yes, this opaque type is ready */
1182 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA
,
1183 r
->opaque_type
, noarea_id
);
1187 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1189 /* Cannot allocate new message. What should we do? */
1190 ospf_apiserver_free (apiserv
);
1194 ospf_apiserver_send_msg (apiserv
, msg
);
1204 ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver
*apiserv
,
1207 struct msg_unregister_opaque_type
*umsg
;
1212 /* Extract parameters from unregister opaque type message */
1213 umsg
= (struct msg_unregister_opaque_type
*) STREAM_DATA (msg
->s
);
1215 ltype
= umsg
->lsatype
;
1216 otype
= umsg
->opaquetype
;
1218 rc
= ospf_apiserver_unregister_opaque_type (apiserv
, ltype
, otype
);
1220 /* Send a reply back to client including return code */
1221 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1227 /* -----------------------------------------------------------
1228 * Following are functions for event (filter) registration.
1229 * -----------------------------------------------------------
1232 ospf_apiserver_handle_register_event (struct ospf_apiserver
*apiserv
,
1235 struct msg_register_event
*rmsg
;
1239 rmsg
= (struct msg_register_event
*) STREAM_DATA (msg
->s
);
1241 /* Get request sequence number */
1242 seqnum
= msg_get_seq (msg
);
1244 /* Free existing filter in apiserv. */
1245 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER
, apiserv
->filter
);
1246 /* Alloc new space for filter. */
1248 apiserv
->filter
= XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER
,
1249 ntohs (msg
->hdr
.msglen
));
1250 if (apiserv
->filter
)
1253 memcpy (apiserv
->filter
, &rmsg
->filter
, ntohs (msg
->hdr
.msglen
));
1258 rc
= OSPF_API_NOMEMORY
;
1260 /* Send a reply back to client with return code */
1261 rc
= ospf_apiserver_send_reply (apiserv
, seqnum
, rc
);
1266 /* -----------------------------------------------------------
1267 * Followings are functions for LSDB synchronization.
1268 * -----------------------------------------------------------
1272 apiserver_sync_callback (struct ospf_lsa
*lsa
, void *p_arg
, int int_arg
)
1274 struct ospf_apiserver
*apiserv
;
1279 struct ospf_apiserver
*apiserv
;
1280 struct lsa_filter_type
*filter
;
1289 param
= (struct param_t
*) p_arg
;
1290 apiserv
= param
->apiserv
;
1291 seqnum
= (u_int32_t
) int_arg
;
1293 /* Check origin in filter. */
1294 if ((param
->filter
->origin
== ANY_ORIGIN
) ||
1295 (param
->filter
->origin
== (lsa
->flags
& OSPF_LSA_SELF
)))
1298 /* Default area for AS-External and Opaque11 LSAs */
1299 struct in_addr area_id
= { 0L };
1301 /* Default interface for non Opaque9 LSAs */
1302 struct in_addr ifaddr
= { 0L };
1306 area_id
= lsa
->area
->area_id
;
1308 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
)
1310 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
1313 msg
= new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY
,
1316 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
1319 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1321 /* Cannot allocate new message. What should we do? */
1322 /* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1328 ospf_apiserver_send_msg (apiserv
, msg
);
1338 ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver
*apiserv
,
1341 struct listnode
*node
, *nnode
;
1344 struct msg_sync_lsdb
*smsg
;
1345 struct ospf_apiserver_param_t
1347 struct ospf_apiserver
*apiserv
;
1348 struct lsa_filter_type
*filter
;
1351 struct route_node
*rn
;
1352 struct ospf_lsa
*lsa
;
1354 struct ospf_area
*area
;
1356 ospf
= ospf_lookup ();
1358 /* Get request sequence number */
1359 seqnum
= msg_get_seq (msg
);
1361 smsg
= (struct msg_sync_lsdb
*) STREAM_DATA (msg
->s
);
1363 /* Set parameter struct. */
1364 param
.apiserv
= apiserv
;
1365 param
.filter
= &smsg
->filter
;
1367 /* Remember mask. */
1368 mask
= ntohs (smsg
->filter
.typemask
);
1370 /* Iterate over all areas. */
1371 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
1374 u_int32_t
*area_id
= NULL
;
1376 /* Compare area_id with area_ids in sync request. */
1377 if ((i
= smsg
->filter
.num_areas
) > 0)
1379 /* Let area_id point to the list of area IDs,
1380 * which is at the end of smsg->filter. */
1381 area_id
= (u_int32_t
*) (&smsg
->filter
+ 1);
1384 if (*area_id
== area
->area_id
.s_addr
)
1397 /* If area was found, then i>0 here. */
1400 /* Check msg type. */
1401 if (mask
& Power2
[OSPF_ROUTER_LSA
])
1402 LSDB_LOOP (ROUTER_LSDB (area
), rn
, lsa
)
1403 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1404 if (mask
& Power2
[OSPF_NETWORK_LSA
])
1405 LSDB_LOOP (NETWORK_LSDB (area
), rn
, lsa
)
1406 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1407 if (mask
& Power2
[OSPF_SUMMARY_LSA
])
1408 LSDB_LOOP (SUMMARY_LSDB (area
), rn
, lsa
)
1409 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1410 if (mask
& Power2
[OSPF_ASBR_SUMMARY_LSA
])
1411 LSDB_LOOP (ASBR_SUMMARY_LSDB (area
), rn
, lsa
)
1412 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1413 if (mask
& Power2
[OSPF_OPAQUE_LINK_LSA
])
1414 LSDB_LOOP (OPAQUE_LINK_LSDB (area
), rn
, lsa
)
1415 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1416 if (mask
& Power2
[OSPF_OPAQUE_AREA_LSA
])
1417 LSDB_LOOP (OPAQUE_AREA_LSDB (area
), rn
, lsa
)
1418 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1422 /* For AS-external LSAs */
1425 if (mask
& Power2
[OSPF_AS_EXTERNAL_LSA
])
1426 LSDB_LOOP (EXTERNAL_LSDB (ospf
), rn
, lsa
)
1427 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1430 /* For AS-external opaque LSAs */
1433 if (mask
& Power2
[OSPF_OPAQUE_AS_LSA
])
1434 LSDB_LOOP (OPAQUE_AS_LSDB (ospf
), rn
, lsa
)
1435 apiserver_sync_callback(lsa
, (void *) ¶m
, seqnum
);
1438 /* Send a reply back to client with return code */
1439 rc
= ospf_apiserver_send_reply (apiserv
, seqnum
, rc
);
1444 /* -----------------------------------------------------------
1445 * Followings are functions to originate or update LSA
1446 * from an application.
1447 * -----------------------------------------------------------
1450 /* Create a new internal opaque LSA by taking prototype and filling in
1451 missing fields such as age, sequence number, advertising router,
1452 checksum and so on. The interface parameter is used for type 9
1453 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1457 ospf_apiserver_opaque_lsa_new (struct ospf_area
*area
,
1458 struct ospf_interface
*oi
,
1459 struct lsa_header
*protolsa
)
1462 struct lsa_header
*newlsa
;
1463 struct ospf_lsa
*new = NULL
;
1464 u_char options
= 0x0;
1469 ospf
= ospf_lookup();
1472 /* Create a stream for internal opaque LSA */
1473 if ((s
= stream_new (OSPF_MAX_LSA_SIZE
)) == NULL
)
1475 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1479 newlsa
= (struct lsa_header
*) STREAM_DATA (s
);
1481 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1482 have to set options? */
1486 options
= LSA_OPTIONS_GET (area
);
1487 options
|= LSA_OPTIONS_NSSA_GET (area
);
1490 options
|= OSPF_OPTION_O
; /* Don't forget to set option bit */
1492 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1494 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1495 protolsa
->type
, inet_ntoa (protolsa
->id
));
1498 /* Set opaque-LSA header fields. */
1499 lsa_header_set (s
, options
, protolsa
->type
, protolsa
->id
,
1502 /* Set opaque-LSA body fields. */
1503 stream_put (s
, ((u_char
*) protolsa
) + sizeof (struct lsa_header
),
1504 ntohs (protolsa
->length
) - sizeof (struct lsa_header
));
1506 /* Determine length of LSA. */
1507 length
= stream_get_endp (s
);
1508 newlsa
->length
= htons (length
);
1510 /* Create OSPF LSA. */
1511 if ((new = ospf_lsa_new ()) == NULL
)
1513 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1518 if ((new->data
= ospf_lsa_data_new (length
)) == NULL
)
1520 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1521 ospf_lsa_unlock (new);
1529 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
1530 memcpy (new->data
, newlsa
, length
);
1538 ospf_apiserver_is_ready_type9 (struct ospf_interface
*oi
)
1540 /* Type 9 opaque LSA can be originated if there is at least one
1541 active opaque-capable neighbor attached to the outgoing
1544 return (ospf_nbr_count_opaque_capable (oi
) > 0);
1548 ospf_apiserver_is_ready_type10 (struct ospf_area
*area
)
1550 /* Type 10 opaque LSA can be originated if there is at least one
1551 interface belonging to the area that has an active opaque-capable
1553 struct listnode
*node
, *nnode
;
1554 struct ospf_interface
*oi
;
1556 for (ALL_LIST_ELEMENTS (area
->oiflist
, node
, nnode
, oi
))
1557 /* Is there an active neighbor attached to this interface? */
1558 if (ospf_apiserver_is_ready_type9 (oi
))
1561 /* No active neighbor in area */
1566 ospf_apiserver_is_ready_type11 (struct ospf
*ospf
)
1568 /* Type 11 opaque LSA can be originated if there is at least one interface
1569 that has an active opaque-capable neighbor. */
1570 struct listnode
*node
, *nnode
;
1571 struct ospf_interface
*oi
;
1573 for (ALL_LIST_ELEMENTS (ospf
->oiflist
, node
, nnode
, oi
))
1574 /* Is there an active neighbor attached to this interface? */
1575 if (ospf_apiserver_is_ready_type9 (oi
))
1578 /* No active neighbor at all */
1584 ospf_apiserver_handle_originate_request (struct ospf_apiserver
*apiserv
,
1587 struct msg_originate_request
*omsg
;
1588 struct lsa_header
*data
;
1589 struct ospf_lsa
*new;
1590 struct ospf_lsa
*old
;
1591 struct ospf_area
*area
= NULL
;
1592 struct ospf_interface
*oi
= NULL
;
1593 struct ospf_lsdb
*lsdb
= NULL
;
1595 int lsa_type
, opaque_type
;
1599 ospf
= ospf_lookup();
1601 /* Extract opaque LSA data from message */
1602 omsg
= (struct msg_originate_request
*) STREAM_DATA (msg
->s
);
1605 /* Determine interface for type9 or area for type10 LSAs. */
1608 case OSPF_OPAQUE_LINK_LSA
:
1609 oi
= ospf_apiserver_if_lookup_by_addr (omsg
->ifaddr
);
1612 zlog_warn ("apiserver_originate: unknown interface %s",
1613 inet_ntoa (omsg
->ifaddr
));
1614 rc
= OSPF_API_NOSUCHINTERFACE
;
1620 case OSPF_OPAQUE_AREA_LSA
:
1621 area
= ospf_area_lookup_by_area_id (ospf
, omsg
->area_id
);
1624 zlog_warn ("apiserver_originate: unknown area %s",
1625 inet_ntoa (omsg
->area_id
));
1626 rc
= OSPF_API_NOSUCHAREA
;
1631 case OSPF_OPAQUE_AS_LSA
:
1635 /* We can only handle opaque types here */
1636 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1638 rc
= OSPF_API_ILLEGALLSATYPE
;
1642 /* Check if we registered this opaque type */
1643 lsa_type
= data
->type
;
1644 opaque_type
= GET_OPAQUE_TYPE (ntohl (data
->id
.s_addr
));
1646 if (!apiserver_is_opaque_type_registered (apiserv
, lsa_type
, opaque_type
))
1648 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type
, opaque_type
);
1649 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1653 /* Make sure that the neighbors are ready before we can originate */
1656 case OSPF_OPAQUE_LINK_LSA
:
1657 ready
= ospf_apiserver_is_ready_type9 (oi
);
1659 case OSPF_OPAQUE_AREA_LSA
:
1660 ready
= ospf_apiserver_is_ready_type10 (area
);
1662 case OSPF_OPAQUE_AS_LSA
:
1663 ready
= ospf_apiserver_is_ready_type11 (ospf
);
1671 zlog_warn ("Neighbors not ready to originate type %d", data
->type
);
1672 rc
= OSPF_API_NOTREADY
;
1676 /* Create OSPF's internal opaque LSA representation */
1677 new = ospf_apiserver_opaque_lsa_new (area
, oi
, data
);
1680 rc
= OSPF_API_NOMEMORY
; /* XXX */
1684 /* Determine if LSA is new or an update for an existing one. */
1685 old
= ospf_lsdb_lookup (lsdb
, new);
1689 /* New LSA install in LSDB. */
1690 rc
= ospf_apiserver_originate1 (new);
1695 * Keep the new LSA instance in the "waiting place" until the next
1696 * refresh timing. If several LSA update requests for the same LSID
1697 * have issued by peer, the last one takes effect.
1699 new->lsdb
= &apiserv
->reserve
;
1700 ospf_lsdb_add (&apiserv
->reserve
, new);
1702 /* Kick the scheduler function. */
1703 ospf_opaque_lsa_refresh_schedule (old
);
1708 /* Send a reply back to client with return code */
1709 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1714 /* -----------------------------------------------------------
1715 * Flood an LSA within its flooding scope.
1716 * -----------------------------------------------------------
1719 /* XXX We can probably use ospf_flood_through instead of this function
1720 but then we need the neighbor parameter. If we set nbr to
1721 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1724 ospf_apiserver_flood_opaque_lsa (struct ospf_lsa
*lsa
)
1728 switch (lsa
->data
->type
)
1730 case OSPF_OPAQUE_LINK_LSA
:
1731 /* Increment counters? XXX */
1733 /* Flood LSA through local network. */
1734 ospf_flood_through_area (lsa
->area
, NULL
/*nbr */ , lsa
);
1736 case OSPF_OPAQUE_AREA_LSA
:
1737 /* Update LSA origination count. */
1739 lsa
->area
->ospf
->lsa_originate_count
++;
1741 /* Flood LSA through area. */
1742 ospf_flood_through_area (lsa
->area
, NULL
/*nbr */ , lsa
);
1744 case OSPF_OPAQUE_AS_LSA
:
1748 ospf
= ospf_lookup();
1751 /* Increment counters? XXX */
1753 /* Flood LSA through AS. */
1754 ospf_flood_through_as (ospf
, NULL
/*nbr */ , lsa
);
1761 ospf_apiserver_originate1 (struct ospf_lsa
*lsa
)
1765 ospf
= ospf_lookup();
1768 /* Install this LSA into LSDB. */
1769 if (ospf_lsa_install (ospf
, lsa
->oi
, lsa
) == NULL
)
1771 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1775 /* Flood LSA within scope */
1779 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1780 * parameter, and thus it does not cause SIGSEGV error.
1782 ospf_flood_through (NULL
/*nbr */ , lsa
);
1785 ospf_apiserver_flood_opaque_lsa (lsa
);
1792 /* Opaque LSAs of type 9 on a specific interface can now be
1793 originated. Tell clients that registered type 9. */
1795 ospf_apiserver_lsa9_originator (void *arg
)
1797 struct ospf_interface
*oi
;
1799 oi
= (struct ospf_interface
*) arg
;
1800 if (listcount (apiserver_list
) > 0) {
1801 ospf_apiserver_clients_notify_ready_type9 (oi
);
1807 ospf_apiserver_lsa10_originator (void *arg
)
1809 struct ospf_area
*area
;
1811 area
= (struct ospf_area
*) arg
;
1812 if (listcount (apiserver_list
) > 0) {
1813 ospf_apiserver_clients_notify_ready_type10 (area
);
1819 ospf_apiserver_lsa11_originator (void *arg
)
1823 ospf
= (struct ospf
*) arg
;
1824 if (listcount (apiserver_list
) > 0) {
1825 ospf_apiserver_clients_notify_ready_type11 (ospf
);
1831 /* Periodically refresh opaque LSAs so that they do not expire in
1834 ospf_apiserver_lsa_refresher (struct ospf_lsa
*lsa
)
1836 struct ospf_apiserver
*apiserv
;
1837 struct ospf_lsa
*new = NULL
;
1840 ospf
= ospf_lookup();
1843 apiserv
= lookup_apiserver_by_lsa (lsa
);
1846 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa
));
1847 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1850 if (IS_LSA_MAXAGE (lsa
))
1852 ospf_opaque_lsa_flush_schedule (lsa
);
1856 /* Check if updated version of LSA instance has already prepared. */
1857 new = ospf_lsdb_lookup (&apiserv
->reserve
, lsa
);
1860 /* This is a periodic refresh, driven by core OSPF mechanism. */
1861 new = ospf_apiserver_opaque_lsa_new (lsa
->area
, lsa
->oi
, lsa
->data
);
1864 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1870 /* This is a forcible refresh, requested by OSPF-API client. */
1871 ospf_lsdb_delete (&apiserv
->reserve
, new);
1875 /* Increment sequence number */
1876 new->data
->ls_seqnum
= lsa_seqnum_increment (lsa
);
1878 /* New LSA is in same area. */
1879 new->area
= lsa
->area
;
1880 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
1882 /* Install LSA into LSDB. */
1883 if (ospf_lsa_install (ospf
, new->oi
, new) == NULL
)
1885 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1886 ospf_lsa_unlock (new);
1890 /* Flood updated LSA through interface, area or AS */
1893 ospf_flood_through (NULL
/*nbr */ , new);
1895 ospf_apiserver_flood_opaque_lsa (new);
1897 /* Debug logging. */
1898 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1900 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
1901 new->data
->type
, inet_ntoa (new->data
->id
));
1902 ospf_lsa_header_dump (new->data
);
1910 /* -----------------------------------------------------------
1911 * Followings are functions to delete LSAs
1912 * -----------------------------------------------------------
1916 ospf_apiserver_handle_delete_request (struct ospf_apiserver
*apiserv
,
1919 struct msg_delete_request
*dmsg
;
1920 struct ospf_lsa
*old
;
1921 struct ospf_area
*area
= NULL
;
1923 int lsa_type
, opaque_type
;
1927 ospf
= ospf_lookup();
1930 /* Extract opaque LSA from message */
1931 dmsg
= (struct msg_delete_request
*) STREAM_DATA (msg
->s
);
1933 /* Lookup area for link-local and area-local opaque LSAs */
1934 switch (dmsg
->lsa_type
)
1936 case OSPF_OPAQUE_LINK_LSA
:
1937 case OSPF_OPAQUE_AREA_LSA
:
1938 area
= ospf_area_lookup_by_area_id (ospf
, dmsg
->area_id
);
1941 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1942 inet_ntoa (dmsg
->area_id
));
1943 rc
= OSPF_API_NOSUCHAREA
;
1947 case OSPF_OPAQUE_AS_LSA
:
1948 /* AS-external opaque LSAs have no designated area */
1953 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1955 rc
= OSPF_API_ILLEGALLSATYPE
;
1959 /* Check if we registered this opaque type */
1960 lsa_type
= dmsg
->lsa_type
;
1961 opaque_type
= dmsg
->opaque_type
;
1963 if (!apiserver_is_opaque_type_registered (apiserv
, lsa_type
, opaque_type
))
1965 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type
, opaque_type
);
1966 rc
= OSPF_API_OPAQUETYPENOTREGISTERED
;
1970 /* opaque_id is in network byte order */
1971 id
.s_addr
= htonl (SET_OPAQUE_LSID (dmsg
->opaque_type
,
1972 ntohl (dmsg
->opaque_id
)));
1975 * Even if the target LSA has once scheduled to flush, it remains in
1976 * the LSDB until it is finally handled by the maxage remover thread.
1977 * Therefore, the lookup function below may return non-NULL result.
1979 old
= ospf_lsa_lookup (area
, dmsg
->lsa_type
, id
, ospf
->router_id
);
1982 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1983 dmsg
->lsa_type
, inet_ntoa (id
));
1984 rc
= OSPF_API_NOSUCHLSA
;
1988 /* Schedule flushing of LSA from LSDB */
1989 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1990 ospf_opaque_lsa_flush_schedule (old
);
1994 /* Send reply back to client including return code */
1995 rc
= ospf_apiserver_send_reply (apiserv
, ntohl (msg
->hdr
.msgseq
), rc
);
1999 /* Flush self-originated opaque LSA */
2001 apiserver_flush_opaque_type_callback (struct ospf_lsa
*lsa
,
2002 void *p_arg
, int int_arg
)
2006 struct ospf_apiserver
*apiserv
;
2015 param
= (struct param_t
*) p_arg
;
2017 /* If LSA matches type and opaque type then delete it */
2018 if (IS_LSA_SELF (lsa
) && lsa
->data
->type
== param
->lsa_type
2019 && GET_OPAQUE_TYPE (ntohl (lsa
->data
->id
.s_addr
)) == param
->opaque_type
)
2021 ospf_opaque_lsa_flush_schedule (lsa
);
2026 /* Delete self-originated opaque LSAs of a given opaque type. This
2027 function is called when an application unregisters a given opaque
2028 type or a connection to an application closes and all those opaque
2029 LSAs need to be flushed the LSDB. */
2031 ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver
*apiserv
,
2032 u_char lsa_type
, u_char opaque_type
)
2036 struct ospf_apiserver
*apiserv
;
2040 struct listnode
*node
, *nnode
;
2042 struct ospf_area
*area
;
2044 ospf
= ospf_lookup();
2047 /* Set parameter struct. */
2048 param
.apiserv
= apiserv
;
2049 param
.lsa_type
= lsa_type
;
2050 param
.opaque_type
= opaque_type
;
2054 struct route_node
*rn
;
2055 struct ospf_lsa
*lsa
;
2057 case OSPF_OPAQUE_LINK_LSA
:
2058 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
2059 LSDB_LOOP (OPAQUE_LINK_LSDB (area
), rn
, lsa
)
2060 apiserver_flush_opaque_type_callback(lsa
, (void *) ¶m
, 0);
2062 case OSPF_OPAQUE_AREA_LSA
:
2063 for (ALL_LIST_ELEMENTS (ospf
->areas
, node
, nnode
, area
))
2064 LSDB_LOOP (OPAQUE_AREA_LSDB (area
), rn
, lsa
)
2065 apiserver_flush_opaque_type_callback(lsa
, (void *) ¶m
, 0);
2067 case OSPF_OPAQUE_AS_LSA
:
2068 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf
), rn
, lsa
)
2069 apiserver_flush_opaque_type_callback(lsa
, (void *) ¶m
, 0);
2078 /* -----------------------------------------------------------
2079 * Followings are callback functions to handle opaque types
2080 * -----------------------------------------------------------
2084 ospf_apiserver_new_if (struct interface
*ifp
)
2086 struct ospf_interface
*oi
;
2088 /* For some strange reason it seems possible that we are invoked
2089 with an interface that has no name. This seems to happen during
2090 initialization. Return if this happens */
2092 if (ifp
->name
[0] == '\0') {
2093 /* interface has empty name */
2094 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2098 /* zlog_warn for debugging */
2099 zlog_warn ("ospf_apiserver_new_if");
2100 zlog_warn ("ifp name=%s status=%d index=%d", ifp
->name
, ifp
->status
,
2103 if (ifp
->name
[0] == '\0') {
2104 /* interface has empty name */
2105 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2109 oi
= ospf_apiserver_if_lookup_by_ifp (ifp
);
2112 /* This interface is known to Zebra but not to OSPF daemon yet. */
2113 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2120 /* New interface added to OSPF, tell clients about it */
2121 if (listcount (apiserver_list
) > 0) {
2122 ospf_apiserver_clients_notify_new_if (oi
);
2128 ospf_apiserver_del_if (struct interface
*ifp
)
2130 struct ospf_interface
*oi
;
2132 /* zlog_warn for debugging */
2133 zlog_warn ("ospf_apiserver_del_if");
2134 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp
->name
, ifp
->status
,
2137 oi
= ospf_apiserver_if_lookup_by_ifp (ifp
);
2140 /* This interface is known to Zebra but not to OSPF daemon
2141 anymore. No need to tell clients about it */
2145 /* Interface deleted, tell clients about it */
2146 if (listcount (apiserver_list
) > 0) {
2147 ospf_apiserver_clients_notify_del_if (oi
);
2153 ospf_apiserver_ism_change (struct ospf_interface
*oi
, int old_state
)
2155 /* Tell clients about interface change */
2157 /* zlog_warn for debugging */
2158 zlog_warn ("ospf_apiserver_ism_change");
2159 if (listcount (apiserver_list
) > 0) {
2160 ospf_apiserver_clients_notify_ism_change (oi
);
2163 zlog_warn ("oi->ifp->name=%s", oi
->ifp
->name
);
2164 zlog_warn ("old_state=%d", old_state
);
2165 zlog_warn ("oi->state=%d", oi
->state
);
2169 ospf_apiserver_nsm_change (struct ospf_neighbor
*nbr
, int old_status
)
2171 /* Neighbor status changed, tell clients about it */
2172 zlog_warn ("ospf_apiserver_nsm_change");
2173 if (listcount (apiserver_list
) > 0) {
2174 ospf_apiserver_clients_notify_nsm_change (nbr
);
2179 ospf_apiserver_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
)
2183 struct lsa_header header
;
2184 u_char data
[1]; /* opaque data have variable length. This is start
2187 struct opaque_lsa
*olsa
;
2190 olsa
= (struct opaque_lsa
*) lsa
->data
;
2192 if (VALID_OPAQUE_INFO_LEN (lsa
->data
))
2193 opaquelen
= ntohs (lsa
->data
->length
) - OSPF_LSA_HEADER_SIZE
;
2197 /* Output information about opaque LSAs */
2201 vty_out (vty
, " Added using OSPF API: %u octets of opaque data %s%s",
2203 VALID_OPAQUE_INFO_LEN (lsa
->data
) ? "" : "(Invalid length?)",
2205 vty_out (vty
, " Opaque data: ");
2207 for (i
= 0; i
< opaquelen
; i
++)
2209 vty_out (vty
, "0x%x ", olsa
->data
[i
]);
2211 vty_out (vty
, "%s", VTY_NEWLINE
);
2216 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
2218 VALID_OPAQUE_INFO_LEN (lsa
->
2219 data
) ? "" : "(Invalid length?)");
2220 zlog_debug (" Opaque data: ");
2222 for (i
= 0; i
< opaquelen
; i
++)
2224 zlog_debug ("0x%x ", olsa
->data
[i
]);
2231 /* -----------------------------------------------------------
2232 * Followings are functions to notify clients about events
2233 * -----------------------------------------------------------
2236 /* Send a message to all clients. This is useful for messages
2237 that need to be notified to all clients (such as interface
2241 ospf_apiserver_clients_notify_all (struct msg
*msg
)
2243 struct listnode
*node
, *nnode
;
2244 struct ospf_apiserver
*apiserv
;
2246 /* Send message to all clients */
2247 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2248 ospf_apiserver_send_msg (apiserv
, msg
);
2251 /* An interface is now ready to accept opaque LSAs. Notify all
2252 clients that registered to use this opaque type */
2254 ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface
*oi
)
2256 struct listnode
*node
, *nnode
;
2258 struct ospf_apiserver
*apiserv
;
2263 zlog_warn ("Interface has no address?");
2267 if (!ospf_apiserver_is_ready_type9 (oi
))
2269 zlog_warn ("Interface not ready for type 9?");
2273 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2275 struct listnode
*node2
, *nnode2
;
2276 struct registered_opaque_type
*r
;
2278 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
2280 if (r
->lsa_type
== OSPF_OPAQUE_LINK_LSA
)
2282 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA
,
2284 oi
->address
->u
.prefix4
);
2288 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2290 /* Cannot allocate new message. What should we do? */
2291 ospf_apiserver_free (apiserv
);
2296 ospf_apiserver_send_msg (apiserv
, msg
);
2307 ospf_apiserver_clients_notify_ready_type10 (struct ospf_area
*area
)
2309 struct listnode
*node
, *nnode
;
2311 struct ospf_apiserver
*apiserv
;
2315 if (!ospf_apiserver_is_ready_type10 (area
))
2317 zlog_warn ("Area not ready for type 10?");
2321 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2323 struct listnode
*node2
, *nnode2
;
2324 struct registered_opaque_type
*r
;
2326 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
2328 if (r
->lsa_type
== OSPF_OPAQUE_AREA_LSA
)
2330 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA
,
2331 r
->opaque_type
, area
->area_id
);
2335 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2337 /* Cannot allocate new message. What should we do? */
2338 ospf_apiserver_free (apiserv
);
2343 ospf_apiserver_send_msg (apiserv
, msg
);
2355 ospf_apiserver_clients_notify_ready_type11 (struct ospf
*top
)
2357 struct listnode
*node
, *nnode
;
2359 struct in_addr id_null
= { 0L };
2360 struct ospf_apiserver
*apiserv
;
2364 if (!ospf_apiserver_is_ready_type11 (top
))
2366 zlog_warn ("AS not ready for type 11?");
2370 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2372 struct listnode
*node2
, *nnode2
;
2373 struct registered_opaque_type
*r
;
2375 for (ALL_LIST_ELEMENTS (apiserv
->opaque_types
, node2
, nnode2
, r
))
2377 if (r
->lsa_type
== OSPF_OPAQUE_AS_LSA
)
2379 msg
= new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA
,
2380 r
->opaque_type
, id_null
);
2384 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2386 /* Cannot allocate new message. What should we do? */
2387 ospf_apiserver_free (apiserv
);
2392 ospf_apiserver_send_msg (apiserv
, msg
);
2403 ospf_apiserver_clients_notify_new_if (struct ospf_interface
*oi
)
2407 msg
= new_msg_new_if (0, oi
->address
->u
.prefix4
, oi
->area
->area_id
);
2410 ospf_apiserver_clients_notify_all (msg
);
2416 ospf_apiserver_clients_notify_del_if (struct ospf_interface
*oi
)
2420 msg
= new_msg_del_if (0, oi
->address
->u
.prefix4
);
2423 ospf_apiserver_clients_notify_all (msg
);
2429 ospf_apiserver_clients_notify_ism_change (struct ospf_interface
*oi
)
2432 struct in_addr ifaddr
= { 0L };
2433 struct in_addr area_id
= { 0L };
2440 ifaddr
= oi
->address
->u
.prefix4
;
2444 area_id
= oi
->area
->area_id
;
2447 msg
= new_msg_ism_change (0, ifaddr
, area_id
, oi
->ifp
->status
);
2450 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2454 ospf_apiserver_clients_notify_all (msg
);
2459 ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor
*nbr
)
2462 struct in_addr ifaddr
= { 0L };
2463 struct in_addr nbraddr
= { 0L };
2469 ifaddr
= nbr
->oi
->address
->u
.prefix4
;
2472 nbraddr
= nbr
->address
.u
.prefix4
;
2474 msg
= new_msg_nsm_change (0, ifaddr
, nbraddr
, nbr
->router_id
, nbr
->state
);
2477 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2481 ospf_apiserver_clients_notify_all (msg
);
2486 apiserver_clients_lsa_change_notify (u_char msgtype
, struct ospf_lsa
*lsa
)
2489 struct listnode
*node
, *nnode
;
2490 struct ospf_apiserver
*apiserv
;
2492 /* Default area for AS-External and Opaque11 LSAs */
2493 struct in_addr area_id
= { 0L };
2495 /* Default interface for non Opaque9 LSAs */
2496 struct in_addr ifaddr
= { 0L };
2500 area_id
= lsa
->area
->area_id
;
2502 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
)
2505 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2508 /* Prepare message that can be sent to clients that have a matching
2510 msg
= new_msg_lsa_change_notify (msgtype
, 0L, /* no sequence number */
2512 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2515 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2519 /* Now send message to all clients with a matching filter */
2520 for (ALL_LIST_ELEMENTS (apiserver_list
, node
, nnode
, apiserv
))
2522 struct lsa_filter_type
*filter
;
2527 /* Check filter for this client. */
2528 filter
= apiserv
->filter
;
2530 /* Check area IDs in case of non AS-E LSAs.
2531 * If filter has areas (num_areas > 0),
2532 * then one of the areas must match the area ID of this LSA. */
2534 i
= filter
->num_areas
;
2535 if ((lsa
->data
->type
== OSPF_AS_EXTERNAL_LSA
) ||
2536 (lsa
->data
->type
== OSPF_OPAQUE_AS_LSA
))
2543 area
= (u_int32_t
*) (filter
+ 1);
2546 if (*area
== area_id
.s_addr
)
2561 /* Area match. Check LSA type. */
2562 mask
= ntohs (filter
->typemask
);
2564 if (mask
& Power2
[lsa
->data
->type
])
2566 /* Type also matches. Check origin. */
2567 if ((filter
->origin
== ANY_ORIGIN
) ||
2568 (filter
->origin
== IS_LSA_SELF (lsa
)))
2570 ospf_apiserver_send_msg (apiserv
, msg
);
2575 /* Free message since it is not used anymore */
2580 /* -------------------------------------------------------------
2581 * Followings are hooks invoked when LSAs are updated or deleted
2582 * -------------------------------------------------------------
2587 apiserver_notify_clients_lsa (u_char msgtype
, struct ospf_lsa
*lsa
)
2590 /* default area for AS-External and Opaque11 LSAs */
2591 struct in_addr area_id
= { 0L };
2593 /* default interface for non Opaque9 LSAs */
2594 struct in_addr ifaddr
= { 0L };
2596 /* Only notify this update if the LSA's age is smaller than
2597 MAXAGE. Otherwise clients would see LSA updates with max age just
2598 before they are deleted from the LSDB. LSA delete messages have
2599 MAXAGE too but should not be filtered. */
2600 if (IS_LSA_MAXAGE(lsa
) && (msgtype
== MSG_LSA_UPDATE_NOTIFY
)) {
2606 area_id
= lsa
->area
->area_id
;
2608 if (lsa
->data
->type
== OSPF_OPAQUE_LINK_LSA
)
2610 ifaddr
= lsa
->oi
->address
->u
.prefix4
;
2612 msg
= new_msg_lsa_change_notify (msgtype
, 0L, /* no sequence number */
2614 lsa
->flags
& OSPF_LSA_SELF
, lsa
->data
);
2617 zlog_warn ("notify_clients_lsa: msg_new failed");
2620 /* Notify all clients that new LSA is added/updated */
2621 apiserver_clients_lsa_change_notify (msgtype
, lsa
);
2623 /* Clients made their own copies of msg so we can free msg here */
2630 ospf_apiserver_lsa_update (struct ospf_lsa
*lsa
)
2632 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY
, lsa
);
2636 ospf_apiserver_lsa_delete (struct ospf_lsa
*lsa
)
2638 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY
, lsa
);
2641 #endif /* SUPPORT_OSPF_API */