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
38 #include "sockunion.h" /* for inet_aton() */
41 #include <sys/types.h>
43 #include "ospfd/ospfd.h" /* for "struct thread_master" */
44 #include "ospfd/ospf_interface.h"
45 #include "ospfd/ospf_ism.h"
46 #include "ospfd/ospf_asbr.h"
47 #include "ospfd/ospf_lsa.h"
48 #include "ospfd/ospf_lsdb.h"
49 #include "ospfd/ospf_neighbor.h"
50 #include "ospfd/ospf_nsm.h"
51 #include "ospfd/ospf_flood.h"
52 #include "ospfd/ospf_packet.h"
53 #include "ospfd/ospf_spf.h"
54 #include "ospfd/ospf_dump.h"
55 #include "ospfd/ospf_route.h"
56 #include "ospfd/ospf_ase.h"
57 #include "ospfd/ospf_zebra.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 *
81 ospf_apiserver_if_lookup_by_addr (struct in_addr address)
83 struct listnode *node, *nnode;
84 struct ospf_interface *oi;
87 if (!(ospf = ospf_lookup ()))
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 *
99 ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
101 struct listnode *node, *nnode;
102 struct ospf_interface *oi;
105 if (!(ospf = ospf_lookup ()))
108 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
115 /* -----------------------------------------------------------
117 * -----------------------------------------------------------
121 ospf_apiserver_getport (void)
123 struct servent *sp = getservbyname ("ospfapi", "tcp");
125 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
128 /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
130 ospf_apiserver_init (void)
135 /* Create new socket for synchronous messages. */
136 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
141 /* Schedule new thread that handles accepted connections. */
142 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
144 /* Initialize list that keeps track of all connections. */
145 apiserver_list = list_new ();
147 /* Register opaque-independent call back functions. These functions
148 are invoked on ISM, NSM changes and LSA update and LSA deletes */
150 ospf_register_opaque_functab (0 /* all LSAs */,
151 0 /* all opaque types */,
152 ospf_apiserver_new_if,
153 ospf_apiserver_del_if,
154 ospf_apiserver_ism_change,
155 ospf_apiserver_nsm_change,
159 NULL, /* ospf_apiserver_show_info */
160 NULL, /* originator_func */
161 NULL, /* ospf_apiserver_lsa_refresher */
162 ospf_apiserver_lsa_update,
163 ospf_apiserver_lsa_delete);
166 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
175 /* Terminate OSPF API module. */
177 ospf_apiserver_term (void)
179 struct ospf_apiserver *apiserv;
181 /* Unregister wildcard [0/0] type */
182 ospf_delete_opaque_functab (0 /* all LSAs */,
183 0 /* all opaque types */);
186 * Free all client instances. ospf_apiserver_free removes the node
187 * from the list, so we examine the head of the list anew each time.
189 while ( apiserver_list &&
190 (apiserv = listgetdata (listhead (apiserver_list))) != NULL)
191 ospf_apiserver_free (apiserv);
193 /* Free client list itself */
195 list_delete (apiserver_list);
197 /* Free wildcard list */
201 static struct ospf_apiserver *
202 lookup_apiserver (u_char lsa_type, u_char opaque_type)
204 struct listnode *n1, *n2;
205 struct registered_opaque_type *r;
206 struct ospf_apiserver *apiserv, *found = NULL;
208 /* XXX: this approaches O(n**2) */
209 for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv))
211 for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r))
212 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
222 static struct ospf_apiserver *
223 lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
225 struct lsa_header *lsah = lsa->data;
226 struct ospf_apiserver *found = NULL;
228 if (IS_OPAQUE_LSA (lsah->type))
230 found = lookup_apiserver (lsah->type,
231 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
236 /* -----------------------------------------------------------
237 * Followings are functions to manage client connections.
238 * -----------------------------------------------------------
241 ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
243 if (IS_DEBUG_OSPF_EVENT)
244 zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", (void *)lsa,
245 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", (void *)lsa,
254 dump_lsa_key (lsa), lsa->lsdb->total);
258 /* Allocate new connection structure. */
259 struct ospf_apiserver *
260 ospf_apiserver_new (int fd_sync, int fd_async)
262 struct ospf_apiserver *new =
263 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
266 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
268 new->fd_sync = fd_sync;
269 new->fd_async = fd_async;
271 /* list of registered opaque types that application uses */
272 new->opaque_types = list_new ();
274 /* Initialize temporary strage for LSA instances to be refreshed. */
275 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
276 ospf_lsdb_init (&new->reserve);
278 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
279 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
281 new->out_sync_fifo = msg_fifo_new ();
282 new->out_async_fifo = msg_fifo_new ();
283 new->t_sync_read = NULL;
284 #ifdef USE_ASYNC_READ
285 new->t_async_read = NULL;
286 #endif /* USE_ASYNC_READ */
287 new->t_sync_write = NULL;
288 new->t_async_write = NULL;
290 new->filter->typemask = 0; /* filter all LSAs */
291 new->filter->origin = ANY_ORIGIN;
292 new->filter->num_areas = 0;
298 ospf_apiserver_event (enum event event, int fd,
299 struct ospf_apiserver *apiserv)
303 case OSPF_APISERVER_ACCEPT:
304 (void)thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
306 case OSPF_APISERVER_SYNC_READ:
307 apiserv->t_sync_read =
308 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
310 #ifdef USE_ASYNC_READ
311 case OSPF_APISERVER_ASYNC_READ:
312 apiserv->t_async_read =
313 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
315 #endif /* USE_ASYNC_READ */
316 case OSPF_APISERVER_SYNC_WRITE:
317 if (!apiserv->t_sync_write)
319 apiserv->t_sync_write =
320 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
323 case OSPF_APISERVER_ASYNC_WRITE:
324 if (!apiserv->t_async_write)
326 apiserv->t_async_write =
327 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
333 /* Free instance. First unregister all opaque types used by
334 application, flush opaque LSAs injected by application
335 from network and close connection. */
337 ospf_apiserver_free (struct ospf_apiserver *apiserv)
339 struct listnode *node;
341 /* Cancel read and write threads. */
342 if (apiserv->t_sync_read)
344 thread_cancel (apiserv->t_sync_read);
346 #ifdef USE_ASYNC_READ
347 if (apiserv->t_async_read)
349 thread_cancel (apiserv->t_async_read);
351 #endif /* USE_ASYNC_READ */
352 if (apiserv->t_sync_write)
354 thread_cancel (apiserv->t_sync_write);
357 if (apiserv->t_async_write)
359 thread_cancel (apiserv->t_async_write);
362 /* Unregister all opaque types that application registered
363 and flush opaque LSAs if still in LSDB. */
365 while ((node = listhead (apiserv->opaque_types)) != NULL)
367 struct registered_opaque_type *regtype = listgetdata(node);
369 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
370 regtype->opaque_type);
374 /* Close connections to OSPFd. */
375 if (apiserv->fd_sync > 0)
377 close (apiserv->fd_sync);
380 if (apiserv->fd_async > 0)
382 close (apiserv->fd_async);
386 msg_fifo_free (apiserv->out_sync_fifo);
387 msg_fifo_free (apiserv->out_async_fifo);
389 /* Clear temporary strage for LSA instances to be refreshed. */
390 ospf_lsdb_delete_all (&apiserv->reserve);
391 ospf_lsdb_cleanup (&apiserv->reserve);
393 /* Remove from the list of active clients. */
394 listnode_delete (apiserver_list, apiserv);
396 if (IS_DEBUG_OSPF_EVENT)
397 zlog_debug ("API: Delete apiserv(%p), total#(%d)",
398 (void *)apiserv, apiserver_list->count);
400 /* And free instance. */
401 XFREE (MTYPE_OSPF_APISERVER, apiserv);
405 ospf_apiserver_read (struct thread *thread)
407 struct ospf_apiserver *apiserv;
413 apiserv = THREAD_ARG (thread);
414 fd = THREAD_FD (thread);
416 if (fd == apiserv->fd_sync)
418 event = OSPF_APISERVER_SYNC_READ;
419 apiserv->t_sync_read = NULL;
421 if (IS_DEBUG_OSPF_EVENT)
422 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
423 inet_ntoa (apiserv->peer_sync.sin_addr),
424 ntohs (apiserv->peer_sync.sin_port));
426 #ifdef USE_ASYNC_READ
427 else if (fd == apiserv->fd_async)
429 event = OSPF_APISERVER_ASYNC_READ;
430 apiserv->t_async_read = NULL;
432 if (IS_DEBUG_OSPF_EVENT)
433 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
434 inet_ntoa (apiserv->peer_async.sin_addr),
435 ntohs (apiserv->peer_async.sin_port));
437 #endif /* USE_ASYNC_READ */
440 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
441 ospf_apiserver_free (apiserv);
445 /* Read message from fd. */
450 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
452 /* Perform cleanup. */
453 ospf_apiserver_free (apiserv);
457 if (IS_DEBUG_OSPF_EVENT)
460 /* Dispatch to corresponding message handler. */
461 rc = ospf_apiserver_handle_msg (apiserv, msg);
463 /* Prepare for next message, add read thread. */
464 ospf_apiserver_event (event, fd, apiserv);
473 ospf_apiserver_sync_write (struct thread *thread)
475 struct ospf_apiserver *apiserv;
480 apiserv = THREAD_ARG (thread);
482 fd = THREAD_FD (thread);
484 apiserv->t_sync_write = NULL;
487 if (fd != apiserv->fd_sync)
489 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
493 if (IS_DEBUG_OSPF_EVENT)
494 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
495 inet_ntoa (apiserv->peer_sync.sin_addr),
496 ntohs (apiserv->peer_sync.sin_port));
498 /* Check whether there is really a message in the fifo. */
499 msg = msg_fifo_pop (apiserv->out_sync_fifo);
502 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
506 if (IS_DEBUG_OSPF_EVENT)
509 rc = msg_write (fd, msg);
511 /* Once a message is dequeued, it should be freed anyway. */
517 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
522 /* If more messages are in sync message fifo, schedule write thread. */
523 if (msg_fifo_head (apiserv->out_sync_fifo))
525 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
533 /* Perform cleanup and disconnect with peer */
534 ospf_apiserver_free (apiserv);
542 ospf_apiserver_async_write (struct thread *thread)
544 struct ospf_apiserver *apiserv;
549 apiserv = THREAD_ARG (thread);
551 fd = THREAD_FD (thread);
553 apiserv->t_async_write = NULL;
556 if (fd != apiserv->fd_async)
558 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
562 if (IS_DEBUG_OSPF_EVENT)
563 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
564 inet_ntoa (apiserv->peer_async.sin_addr),
565 ntohs (apiserv->peer_async.sin_port));
567 /* Check whether there is really a message in the fifo. */
568 msg = msg_fifo_pop (apiserv->out_async_fifo);
571 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
575 if (IS_DEBUG_OSPF_EVENT)
578 rc = msg_write (fd, msg);
580 /* Once a message is dequeued, it should be freed anyway. */
586 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
591 /* If more messages are in async message fifo, schedule write thread. */
592 if (msg_fifo_head (apiserv->out_async_fifo))
594 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
602 /* Perform cleanup and disconnect with peer */
603 ospf_apiserver_free (apiserv);
611 ospf_apiserver_serv_sock_family (unsigned short port, int family)
617 memset (&su, 0, sizeof (union sockunion));
618 su.sa.sa_family = family;
620 /* Make new socket */
621 accept_sock = sockunion_stream_socket (&su);
625 /* This is a server, so reuse address and port */
626 sockopt_reuseaddr (accept_sock);
627 sockopt_reuseport (accept_sock);
629 /* Bind socket to address and given port. */
630 rc = sockunion_bind (accept_sock, &su, port, NULL);
633 close (accept_sock); /* Close socket */
637 /* Listen socket under queue length 3. */
638 rc = listen (accept_sock, 3);
641 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
642 safe_strerror (errno));
643 close (accept_sock); /* Close socket */
650 /* Accept connection request from external applications. For each
651 accepted connection allocate own connection instance. */
653 ospf_apiserver_accept (struct thread *thread)
659 struct ospf_apiserver *apiserv;
660 struct sockaddr_in peer_async;
661 struct sockaddr_in peer_sync;
662 unsigned int peerlen;
665 /* THREAD_ARG (thread) is NULL */
666 accept_sock = THREAD_FD (thread);
668 /* Keep hearing on socket for further connections. */
669 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
671 memset (&su, 0, sizeof (union sockunion));
672 /* Accept connection for synchronous messages */
673 new_sync_sock = sockunion_accept (accept_sock, &su);
674 if (new_sync_sock < 0)
676 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
680 /* Get port address and port number of peer to make reverse connection.
681 The reverse channel uses the port number of the peer port+1. */
683 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
684 peerlen = sizeof (struct sockaddr_in);
686 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
689 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
690 close (new_sync_sock);
694 if (IS_DEBUG_OSPF_EVENT)
695 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
696 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
698 /* Create new socket for asynchronous messages. */
699 peer_async = peer_sync;
700 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
702 /* Check if remote port number to make reverse connection is valid one. */
703 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
705 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
706 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
707 close (new_sync_sock);
711 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
712 if (new_async_sock < 0)
714 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
715 close (new_sync_sock);
719 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
720 sizeof (struct sockaddr_in));
724 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
725 close (new_sync_sock);
726 close (new_async_sock);
730 #ifdef USE_ASYNC_READ
731 #else /* USE_ASYNC_READ */
732 /* Make the asynchronous channel write-only. */
733 ret = shutdown (new_async_sock, SHUT_RD);
736 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno));
737 close (new_sync_sock);
738 close (new_async_sock);
741 #endif /* USE_ASYNC_READ */
743 /* Allocate new server-side connection structure */
744 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
746 /* Add to active connection list */
747 listnode_add (apiserver_list, apiserv);
748 apiserv->peer_sync = peer_sync;
749 apiserv->peer_async = peer_async;
751 /* And add read threads for new connection */
752 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
753 #ifdef USE_ASYNC_READ
754 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
755 #endif /* USE_ASYNC_READ */
757 if (IS_DEBUG_OSPF_EVENT)
758 zlog_debug ("API: New apiserv(%p), total#(%d)",
759 (void *)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 XCALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
939 regtype->lsa_type = lsa_type;
940 regtype->opaque_type = opaque_type;
942 /* Add to list of registered opaque types */
943 listnode_add (apiserv->opaque_types, regtype);
945 if (IS_DEBUG_OSPF_EVENT)
946 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
947 " apiserv(%p), total#(%d)",
948 lsa_type, opaque_type, (void *)apiserv,
949 listcount (apiserv->opaque_types));
955 ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
956 u_char lsa_type, u_char opaque_type)
958 struct listnode *node, *nnode;
959 struct registered_opaque_type *regtype;
961 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
963 /* Check if we really registered this opaque type */
964 if (regtype->lsa_type == lsa_type &&
965 regtype->opaque_type == opaque_type)
968 /* Yes, we registered this opaque type. Flush
969 all existing opaque LSAs of this type */
971 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
972 ospf_delete_opaque_functab (lsa_type, opaque_type);
974 /* Remove from list of registered opaque types */
975 listnode_delete (apiserv->opaque_types, regtype);
977 if (IS_DEBUG_OSPF_EVENT)
978 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
979 " from apiserv(%p), total#(%d)",
980 lsa_type, opaque_type, (void *)apiserv,
981 listcount (apiserv->opaque_types));
987 /* Opaque type is not registered */
988 zlog_warn ("Failed to unregister opaque type [%d/%d]",
989 lsa_type, opaque_type);
990 return OSPF_API_OPAQUETYPENOTREGISTERED;
995 apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
996 u_char lsa_type, u_char opaque_type)
998 struct listnode *node, *nnode;
999 struct registered_opaque_type *regtype;
1001 /* XXX: how many types are there? if few, why not just a bitmap? */
1002 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
1004 /* Check if we really registered this opaque type */
1005 if (regtype->lsa_type == lsa_type &&
1006 regtype->opaque_type == opaque_type)
1008 /* Yes registered */
1012 /* Not registered */
1017 ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1020 struct msg_register_opaque_type *rmsg;
1025 /* Extract parameters from register opaque type message */
1026 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1028 lsa_type = rmsg->lsatype;
1029 opaque_type = rmsg->opaquetype;
1031 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1033 /* Send a reply back to client including return code */
1034 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1038 /* Now inform application about opaque types that are ready */
1041 case OSPF_OPAQUE_LINK_LSA:
1042 ospf_apiserver_notify_ready_type9 (apiserv);
1044 case OSPF_OPAQUE_AREA_LSA:
1045 ospf_apiserver_notify_ready_type10 (apiserv);
1047 case OSPF_OPAQUE_AS_LSA:
1048 ospf_apiserver_notify_ready_type11 (apiserv);
1056 /* Notify specific client about all opaque types 9 that are ready. */
1058 ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1060 struct listnode *node, *nnode;
1061 struct listnode *node2, *nnode2;
1063 struct ospf_interface *oi;
1064 struct registered_opaque_type *r;
1066 ospf = ospf_lookup ();
1068 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
1070 /* Check if this interface is indeed ready for type 9 */
1071 if (!ospf_apiserver_is_ready_type9 (oi))
1074 /* Check for registered opaque type 9 types */
1075 /* XXX: loop-de-loop - optimise me */
1076 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
1080 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1083 /* Yes, this opaque type is ready */
1084 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1086 oi->address->u.prefix4);
1089 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1091 /* Cannot allocate new message. What should we do? */
1092 ospf_apiserver_free (apiserv);
1096 ospf_apiserver_send_msg (apiserv, msg);
1107 /* Notify specific client about all opaque types 10 that are ready. */
1109 ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1111 struct listnode *node, *nnode;
1112 struct listnode *node2, *nnode2;
1114 struct ospf_area *area;
1116 ospf = ospf_lookup ();
1118 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1120 struct registered_opaque_type *r;
1122 if (!ospf_apiserver_is_ready_type10 (area))
1127 /* Check for registered opaque type 10 types */
1128 /* XXX: loop in loop - optimise me */
1129 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
1133 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1135 /* Yes, this opaque type is ready */
1137 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1138 r->opaque_type, area->area_id);
1141 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1143 /* Cannot allocate new message. What should we do? */
1144 ospf_apiserver_free (apiserv);
1148 ospf_apiserver_send_msg (apiserv, msg);
1158 /* Notify specific client about all opaque types 11 that are ready */
1160 ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1162 struct listnode *node, *nnode;
1164 struct registered_opaque_type *r;
1166 ospf = ospf_lookup ();
1168 /* Can type 11 be originated? */
1169 if (!ospf_apiserver_is_ready_type11 (ospf))
1172 /* Check for registered opaque type 11 types */
1173 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
1176 struct in_addr noarea_id = { .s_addr = 0L };
1178 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1180 /* Yes, this opaque type is ready */
1181 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1182 r->opaque_type, noarea_id);
1186 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1188 /* Cannot allocate new message. What should we do? */
1189 ospf_apiserver_free (apiserv);
1193 ospf_apiserver_send_msg (apiserv, msg);
1203 ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1206 struct msg_unregister_opaque_type *umsg;
1211 /* Extract parameters from unregister opaque type message */
1212 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1214 ltype = umsg->lsatype;
1215 otype = umsg->opaquetype;
1217 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1219 /* Send a reply back to client including return code */
1220 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1226 /* -----------------------------------------------------------
1227 * Following are functions for event (filter) registration.
1228 * -----------------------------------------------------------
1231 ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1234 struct msg_register_event *rmsg;
1238 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1240 /* Get request sequence number */
1241 seqnum = msg_get_seq (msg);
1243 /* Free existing filter in apiserv. */
1244 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1245 /* Alloc new space for filter. */
1247 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1248 ntohs (msg->hdr.msglen));
1249 if (apiserv->filter)
1252 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1257 rc = OSPF_API_NOMEMORY;
1259 /* Send a reply back to client with return code */
1260 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1265 /* -----------------------------------------------------------
1266 * Followings are functions for LSDB synchronization.
1267 * -----------------------------------------------------------
1271 apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1273 struct ospf_apiserver *apiserv;
1278 struct ospf_apiserver *apiserv;
1279 struct lsa_filter_type *filter;
1288 param = (struct param_t *) p_arg;
1289 apiserv = param->apiserv;
1290 seqnum = (u_int32_t) int_arg;
1292 /* Check origin in filter. */
1293 if ((param->filter->origin == ANY_ORIGIN) ||
1294 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1297 /* Default area for AS-External and Opaque11 LSAs */
1298 struct in_addr area_id = { .s_addr = 0L };
1300 /* Default interface for non Opaque9 LSAs */
1301 struct in_addr ifaddr = { .s_addr = 0L };
1305 area_id = lsa->area->area_id;
1307 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1309 ifaddr = lsa->oi->address->u.prefix4;
1312 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1315 lsa->flags & OSPF_LSA_SELF, lsa->data);
1318 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1320 /* Cannot allocate new message. What should we do? */
1321 /* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1327 ospf_apiserver_send_msg (apiserv, msg);
1337 ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1340 struct listnode *node, *nnode;
1343 struct msg_sync_lsdb *smsg;
1344 struct ospf_apiserver_param_t
1346 struct ospf_apiserver *apiserv;
1347 struct lsa_filter_type *filter;
1350 struct route_node *rn;
1351 struct ospf_lsa *lsa;
1353 struct ospf_area *area;
1355 ospf = ospf_lookup ();
1357 /* Get request sequence number */
1358 seqnum = msg_get_seq (msg);
1360 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1362 /* Set parameter struct. */
1363 param.apiserv = apiserv;
1364 param.filter = &smsg->filter;
1366 /* Remember mask. */
1367 mask = ntohs (smsg->filter.typemask);
1369 /* Iterate over all areas. */
1370 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
1373 u_int32_t *area_id = NULL;
1375 /* Compare area_id with area_ids in sync request. */
1376 if ((i = smsg->filter.num_areas) > 0)
1378 /* Let area_id point to the list of area IDs,
1379 * which is at the end of smsg->filter. */
1380 area_id = (u_int32_t *) (&smsg->filter + 1);
1383 if (*area_id == area->area_id.s_addr)
1396 /* If area was found, then i>0 here. */
1399 /* Check msg type. */
1400 if (mask & Power2[OSPF_ROUTER_LSA])
1401 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1402 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1403 if (mask & Power2[OSPF_NETWORK_LSA])
1404 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1405 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1406 if (mask & Power2[OSPF_SUMMARY_LSA])
1407 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1408 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1409 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
1410 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1411 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1412 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
1413 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1414 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1415 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
1416 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1417 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1421 /* For AS-external LSAs */
1424 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
1425 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1426 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1429 /* For AS-external opaque LSAs */
1432 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
1433 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1434 apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
1437 /* Send a reply back to client with return code */
1438 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1443 /* -----------------------------------------------------------
1444 * Followings are functions to originate or update LSA
1445 * from an application.
1446 * -----------------------------------------------------------
1449 /* Create a new internal opaque LSA by taking prototype and filling in
1450 missing fields such as age, sequence number, advertising router,
1451 checksum and so on. The interface parameter is used for type 9
1452 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1456 ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1457 struct ospf_interface *oi,
1458 struct lsa_header *protolsa)
1461 struct lsa_header *newlsa;
1462 struct ospf_lsa *new = NULL;
1463 u_char options = 0x0;
1468 ospf = ospf_lookup();
1471 /* Create a stream for internal opaque LSA */
1472 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1474 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1478 newlsa = (struct lsa_header *) STREAM_DATA (s);
1480 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1481 have to set options? */
1485 options = LSA_OPTIONS_GET (area);
1486 options |= LSA_OPTIONS_NSSA_GET (area);
1489 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1491 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1493 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1494 protolsa->type, inet_ntoa (protolsa->id));
1497 /* Set opaque-LSA header fields. */
1498 lsa_header_set (s, options, protolsa->type, protolsa->id,
1501 /* Set opaque-LSA body fields. */
1502 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1503 ntohs (protolsa->length) - sizeof (struct lsa_header));
1505 /* Determine length of LSA. */
1506 length = stream_get_endp (s);
1507 newlsa->length = htons (length);
1509 /* Create OSPF LSA. */
1510 if ((new = ospf_lsa_new ()) == NULL)
1512 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1517 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1519 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1520 ospf_lsa_unlock (&new);
1528 SET_FLAG (new->flags, OSPF_LSA_SELF);
1529 memcpy (new->data, newlsa, length);
1537 ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1539 /* Type 9 opaque LSA can be originated if there is at least one
1540 active opaque-capable neighbor attached to the outgoing
1543 return (ospf_nbr_count_opaque_capable (oi) > 0);
1547 ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1549 /* Type 10 opaque LSA can be originated if there is at least one
1550 interface belonging to the area that has an active opaque-capable
1552 struct listnode *node, *nnode;
1553 struct ospf_interface *oi;
1555 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
1556 /* Is there an active neighbor attached to this interface? */
1557 if (ospf_apiserver_is_ready_type9 (oi))
1560 /* No active neighbor in area */
1565 ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1567 /* Type 11 opaque LSA can be originated if there is at least one interface
1568 that has an active opaque-capable neighbor. */
1569 struct listnode *node, *nnode;
1570 struct ospf_interface *oi;
1572 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
1573 /* Is there an active neighbor attached to this interface? */
1574 if (ospf_apiserver_is_ready_type9 (oi))
1577 /* No active neighbor at all */
1583 ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1586 struct msg_originate_request *omsg;
1587 struct lsa_header *data;
1588 struct ospf_lsa *new;
1589 struct ospf_lsa *old;
1590 struct ospf_area *area = NULL;
1591 struct ospf_interface *oi = NULL;
1592 struct ospf_lsdb *lsdb = NULL;
1594 int lsa_type, opaque_type;
1598 ospf = ospf_lookup();
1600 /* Extract opaque LSA data from message */
1601 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1604 /* Determine interface for type9 or area for type10 LSAs. */
1607 case OSPF_OPAQUE_LINK_LSA:
1608 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1611 zlog_warn ("apiserver_originate: unknown interface %s",
1612 inet_ntoa (omsg->ifaddr));
1613 rc = OSPF_API_NOSUCHINTERFACE;
1619 case OSPF_OPAQUE_AREA_LSA:
1620 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
1623 zlog_warn ("apiserver_originate: unknown area %s",
1624 inet_ntoa (omsg->area_id));
1625 rc = OSPF_API_NOSUCHAREA;
1630 case OSPF_OPAQUE_AS_LSA:
1634 /* We can only handle opaque types here */
1635 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1637 rc = OSPF_API_ILLEGALLSATYPE;
1641 /* Check if we registered this opaque type */
1642 lsa_type = data->type;
1643 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1645 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1647 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1648 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1652 /* Make sure that the neighbors are ready before we can originate */
1655 case OSPF_OPAQUE_LINK_LSA:
1656 ready = ospf_apiserver_is_ready_type9 (oi);
1658 case OSPF_OPAQUE_AREA_LSA:
1659 ready = ospf_apiserver_is_ready_type10 (area);
1661 case OSPF_OPAQUE_AS_LSA:
1662 ready = ospf_apiserver_is_ready_type11 (ospf);
1670 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1671 rc = OSPF_API_NOTREADY;
1675 /* Create OSPF's internal opaque LSA representation */
1676 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1679 rc = OSPF_API_NOMEMORY; /* XXX */
1683 /* Determine if LSA is new or an update for an existing one. */
1684 old = ospf_lsdb_lookup (lsdb, new);
1688 /* New LSA install in LSDB. */
1689 rc = ospf_apiserver_originate1 (new);
1694 * Keep the new LSA instance in the "waiting place" until the next
1695 * refresh timing. If several LSA update requests for the same LSID
1696 * have issued by peer, the last one takes effect.
1698 new->lsdb = &apiserv->reserve;
1699 ospf_lsdb_add (&apiserv->reserve, new);
1701 /* Kick the scheduler function. */
1702 ospf_opaque_lsa_refresh_schedule (old);
1707 /* Send a reply back to client with return code */
1708 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1713 /* -----------------------------------------------------------
1714 * Flood an LSA within its flooding scope.
1715 * -----------------------------------------------------------
1718 /* XXX We can probably use ospf_flood_through instead of this function
1719 but then we need the neighbor parameter. If we set nbr to
1720 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1723 ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1727 switch (lsa->data->type)
1729 case OSPF_OPAQUE_LINK_LSA:
1730 /* Increment counters? XXX */
1732 /* Flood LSA through local network. */
1733 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1735 case OSPF_OPAQUE_AREA_LSA:
1736 /* Update LSA origination count. */
1738 lsa->area->ospf->lsa_originate_count++;
1740 /* Flood LSA through area. */
1741 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1743 case OSPF_OPAQUE_AS_LSA:
1747 ospf = ospf_lookup();
1750 /* Increment counters? XXX */
1752 /* Flood LSA through AS. */
1753 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
1760 ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1764 ospf = ospf_lookup();
1767 /* Install this LSA into LSDB. */
1768 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
1770 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1774 /* Flood LSA within scope */
1778 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1779 * parameter, and thus it does not cause SIGSEGV error.
1781 ospf_flood_through (NULL /*nbr */ , lsa);
1784 ospf_apiserver_flood_opaque_lsa (lsa);
1791 /* Opaque LSAs of type 9 on a specific interface can now be
1792 originated. Tell clients that registered type 9. */
1794 ospf_apiserver_lsa9_originator (void *arg)
1796 struct ospf_interface *oi;
1798 oi = (struct ospf_interface *) arg;
1799 if (listcount (apiserver_list) > 0) {
1800 ospf_apiserver_clients_notify_ready_type9 (oi);
1806 ospf_apiserver_lsa10_originator (void *arg)
1808 struct ospf_area *area;
1810 area = (struct ospf_area *) arg;
1811 if (listcount (apiserver_list) > 0) {
1812 ospf_apiserver_clients_notify_ready_type10 (area);
1818 ospf_apiserver_lsa11_originator (void *arg)
1822 ospf = (struct ospf *) arg;
1823 if (listcount (apiserver_list) > 0) {
1824 ospf_apiserver_clients_notify_ready_type11 (ospf);
1830 /* Periodically refresh opaque LSAs so that they do not expire in
1833 ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1835 struct ospf_apiserver *apiserv;
1836 struct ospf_lsa *new = NULL;
1839 ospf = ospf_lookup();
1842 apiserv = lookup_apiserver_by_lsa (lsa);
1845 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1846 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1849 if (IS_LSA_MAXAGE (lsa))
1851 ospf_opaque_lsa_flush_schedule (lsa);
1855 /* Check if updated version of LSA instance has already prepared. */
1856 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1859 /* This is a periodic refresh, driven by core OSPF mechanism. */
1860 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1863 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1869 /* This is a forcible refresh, requested by OSPF-API client. */
1870 ospf_lsdb_delete (&apiserv->reserve, new);
1874 /* Increment sequence number */
1875 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1877 /* New LSA is in same area. */
1878 new->area = lsa->area;
1879 SET_FLAG (new->flags, OSPF_LSA_SELF);
1881 /* Install LSA into LSDB. */
1882 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
1884 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1885 ospf_lsa_unlock (&new);
1889 /* Flood updated LSA through interface, area or AS */
1892 ospf_flood_through (NULL /*nbr */ , new);
1894 ospf_apiserver_flood_opaque_lsa (new);
1896 /* Debug logging. */
1897 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1899 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
1900 new->data->type, inet_ntoa (new->data->id));
1901 ospf_lsa_header_dump (new->data);
1909 /* -----------------------------------------------------------
1910 * Followings are functions to delete LSAs
1911 * -----------------------------------------------------------
1915 ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1918 struct msg_delete_request *dmsg;
1919 struct ospf_lsa *old;
1920 struct ospf_area *area = NULL;
1922 int lsa_type, opaque_type;
1926 ospf = ospf_lookup();
1929 /* Extract opaque LSA from message */
1930 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1932 /* Lookup area for link-local and area-local opaque LSAs */
1933 switch (dmsg->lsa_type)
1935 case OSPF_OPAQUE_LINK_LSA:
1936 case OSPF_OPAQUE_AREA_LSA:
1937 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
1940 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1941 inet_ntoa (dmsg->area_id));
1942 rc = OSPF_API_NOSUCHAREA;
1946 case OSPF_OPAQUE_AS_LSA:
1947 /* AS-external opaque LSAs have no designated area */
1952 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1954 rc = OSPF_API_ILLEGALLSATYPE;
1958 /* Check if we registered this opaque type */
1959 lsa_type = dmsg->lsa_type;
1960 opaque_type = dmsg->opaque_type;
1962 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1964 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1965 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1969 /* opaque_id is in network byte order */
1970 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1971 ntohl (dmsg->opaque_id)));
1974 * Even if the target LSA has once scheduled to flush, it remains in
1975 * the LSDB until it is finally handled by the maxage remover thread.
1976 * Therefore, the lookup function below may return non-NULL result.
1978 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
1981 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1982 dmsg->lsa_type, inet_ntoa (id));
1983 rc = OSPF_API_NOSUCHLSA;
1987 /* Schedule flushing of LSA from LSDB */
1988 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1989 ospf_opaque_lsa_flush_schedule (old);
1993 /* Send reply back to client including return code */
1994 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1998 /* Flush self-originated opaque LSA */
2000 apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2001 void *p_arg, int int_arg)
2005 struct ospf_apiserver *apiserv;
2014 param = (struct param_t *) p_arg;
2016 /* If LSA matches type and opaque type then delete it */
2017 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2018 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2020 ospf_opaque_lsa_flush_schedule (lsa);
2025 /* Delete self-originated opaque LSAs of a given opaque type. This
2026 function is called when an application unregisters a given opaque
2027 type or a connection to an application closes and all those opaque
2028 LSAs need to be flushed the LSDB. */
2030 ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2031 u_char lsa_type, u_char opaque_type)
2035 struct ospf_apiserver *apiserv;
2039 struct listnode *node, *nnode;
2041 struct ospf_area *area;
2043 ospf = ospf_lookup();
2046 /* Set parameter struct. */
2047 param.apiserv = apiserv;
2048 param.lsa_type = lsa_type;
2049 param.opaque_type = opaque_type;
2053 struct route_node *rn;
2054 struct ospf_lsa *lsa;
2056 case OSPF_OPAQUE_LINK_LSA:
2057 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
2058 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2059 apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0);
2061 case OSPF_OPAQUE_AREA_LSA:
2062 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
2063 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2064 apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0);
2066 case OSPF_OPAQUE_AS_LSA:
2067 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2068 apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0);
2077 /* -----------------------------------------------------------
2078 * Followings are callback functions to handle opaque types
2079 * -----------------------------------------------------------
2083 ospf_apiserver_new_if (struct interface *ifp)
2085 struct ospf_interface *oi;
2087 /* For some strange reason it seems possible that we are invoked
2088 with an interface that has no name. This seems to happen during
2089 initialization. Return if this happens */
2091 if (ifp->name[0] == '\0') {
2092 /* interface has empty name */
2093 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2097 /* zlog_warn for debugging */
2098 zlog_warn ("ospf_apiserver_new_if");
2099 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2102 if (ifp->name[0] == '\0') {
2103 /* interface has empty name */
2104 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2108 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2111 /* This interface is known to Zebra but not to OSPF daemon yet. */
2112 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2119 /* New interface added to OSPF, tell clients about it */
2120 if (listcount (apiserver_list) > 0) {
2121 ospf_apiserver_clients_notify_new_if (oi);
2127 ospf_apiserver_del_if (struct interface *ifp)
2129 struct ospf_interface *oi;
2131 /* zlog_warn for debugging */
2132 zlog_warn ("ospf_apiserver_del_if");
2133 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2136 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2139 /* This interface is known to Zebra but not to OSPF daemon
2140 anymore. No need to tell clients about it */
2144 /* Interface deleted, tell clients about it */
2145 if (listcount (apiserver_list) > 0) {
2146 ospf_apiserver_clients_notify_del_if (oi);
2152 ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2154 /* Tell clients about interface change */
2156 /* zlog_warn for debugging */
2157 zlog_warn ("ospf_apiserver_ism_change");
2158 if (listcount (apiserver_list) > 0) {
2159 ospf_apiserver_clients_notify_ism_change (oi);
2162 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2163 zlog_warn ("old_state=%d", old_state);
2164 zlog_warn ("oi->state=%d", oi->state);
2168 ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2170 /* Neighbor status changed, tell clients about it */
2171 zlog_warn ("ospf_apiserver_nsm_change");
2172 if (listcount (apiserver_list) > 0) {
2173 ospf_apiserver_clients_notify_nsm_change (nbr);
2178 ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2182 struct lsa_header header;
2183 u_char data[1]; /* opaque data have variable length. This is start
2186 struct opaque_lsa *olsa;
2189 olsa = (struct opaque_lsa *) lsa->data;
2191 if (VALID_OPAQUE_INFO_LEN (lsa->data))
2192 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2196 /* Output information about opaque LSAs */
2200 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2202 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2204 vty_out (vty, " Opaque data: ");
2206 for (i = 0; i < opaquelen; i++)
2208 vty_out (vty, "0x%x ", olsa->data[i]);
2210 vty_out (vty, "%s", VTY_NEWLINE);
2215 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
2217 VALID_OPAQUE_INFO_LEN (lsa->
2218 data) ? "" : "(Invalid length?)");
2219 zlog_debug (" Opaque data: ");
2221 for (i = 0; i < opaquelen; i++)
2223 zlog_debug ("0x%x ", olsa->data[i]);
2230 /* -----------------------------------------------------------
2231 * Followings are functions to notify clients about events
2232 * -----------------------------------------------------------
2235 /* Send a message to all clients. This is useful for messages
2236 that need to be notified to all clients (such as interface
2240 ospf_apiserver_clients_notify_all (struct msg *msg)
2242 struct listnode *node, *nnode;
2243 struct ospf_apiserver *apiserv;
2245 /* Send message to all clients */
2246 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
2247 ospf_apiserver_send_msg (apiserv, msg);
2250 /* An interface is now ready to accept opaque LSAs. Notify all
2251 clients that registered to use this opaque type */
2253 ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2255 struct listnode *node, *nnode;
2257 struct ospf_apiserver *apiserv;
2262 zlog_warn ("Interface has no address?");
2266 if (!ospf_apiserver_is_ready_type9 (oi))
2268 zlog_warn ("Interface not ready for type 9?");
2272 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
2274 struct listnode *node2, *nnode2;
2275 struct registered_opaque_type *r;
2277 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
2279 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2281 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2283 oi->address->u.prefix4);
2287 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2289 /* Cannot allocate new message. What should we do? */
2290 ospf_apiserver_free (apiserv);
2295 ospf_apiserver_send_msg (apiserv, msg);
2306 ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2308 struct listnode *node, *nnode;
2310 struct ospf_apiserver *apiserv;
2314 if (!ospf_apiserver_is_ready_type10 (area))
2316 zlog_warn ("Area not ready for type 10?");
2320 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
2322 struct listnode *node2, *nnode2;
2323 struct registered_opaque_type *r;
2325 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
2327 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2329 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2330 r->opaque_type, area->area_id);
2334 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2336 /* Cannot allocate new message. What should we do? */
2337 ospf_apiserver_free (apiserv);
2342 ospf_apiserver_send_msg (apiserv, msg);
2354 ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2356 struct listnode *node, *nnode;
2358 struct in_addr id_null = { .s_addr = 0L };
2359 struct ospf_apiserver *apiserv;
2363 if (!ospf_apiserver_is_ready_type11 (top))
2365 zlog_warn ("AS not ready for type 11?");
2369 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
2371 struct listnode *node2, *nnode2;
2372 struct registered_opaque_type *r;
2374 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
2376 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2378 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2379 r->opaque_type, id_null);
2383 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2385 /* Cannot allocate new message. What should we do? */
2386 ospf_apiserver_free (apiserv);
2391 ospf_apiserver_send_msg (apiserv, msg);
2402 ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2406 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2409 ospf_apiserver_clients_notify_all (msg);
2415 ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2419 msg = new_msg_del_if (0, oi->address->u.prefix4);
2422 ospf_apiserver_clients_notify_all (msg);
2428 ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2431 struct in_addr ifaddr = { .s_addr = 0L };
2432 struct in_addr area_id = { .s_addr = 0L };
2439 ifaddr = oi->address->u.prefix4;
2443 area_id = oi->area->area_id;
2446 msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
2449 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2453 ospf_apiserver_clients_notify_all (msg);
2458 ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2461 struct in_addr ifaddr = { .s_addr = 0L };
2462 struct in_addr nbraddr = { .s_addr = 0L };
2468 ifaddr = nbr->oi->address->u.prefix4;
2471 nbraddr = nbr->address.u.prefix4;
2473 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2476 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2480 ospf_apiserver_clients_notify_all (msg);
2485 apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2488 struct listnode *node, *nnode;
2489 struct ospf_apiserver *apiserv;
2491 /* Default area for AS-External and Opaque11 LSAs */
2492 struct in_addr area_id = { .s_addr = 0L };
2494 /* Default interface for non Opaque9 LSAs */
2495 struct in_addr ifaddr = { .s_addr = 0L };
2499 area_id = lsa->area->area_id;
2501 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2504 ifaddr = lsa->oi->address->u.prefix4;
2507 /* Prepare message that can be sent to clients that have a matching
2509 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2511 lsa->flags & OSPF_LSA_SELF, lsa->data);
2514 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2518 /* Now send message to all clients with a matching filter */
2519 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
2521 struct lsa_filter_type *filter;
2526 /* Check filter for this client. */
2527 filter = apiserv->filter;
2529 /* Check area IDs in case of non AS-E LSAs.
2530 * If filter has areas (num_areas > 0),
2531 * then one of the areas must match the area ID of this LSA. */
2533 i = filter->num_areas;
2534 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2535 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2542 area = (u_int32_t *) (filter + 1);
2545 if (*area == area_id.s_addr)
2560 /* Area match. Check LSA type. */
2561 mask = ntohs (filter->typemask);
2563 if (mask & Power2[lsa->data->type])
2565 /* Type also matches. Check origin. */
2566 if ((filter->origin == ANY_ORIGIN) ||
2567 (filter->origin == IS_LSA_SELF (lsa)))
2569 ospf_apiserver_send_msg (apiserv, msg);
2574 /* Free message since it is not used anymore */
2579 /* -------------------------------------------------------------
2580 * Followings are hooks invoked when LSAs are updated or deleted
2581 * -------------------------------------------------------------
2586 apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2589 /* default area for AS-External and Opaque11 LSAs */
2590 struct in_addr area_id = { .s_addr = 0L };
2592 /* default interface for non Opaque9 LSAs */
2593 struct in_addr ifaddr = { .s_addr = 0L };
2595 /* Only notify this update if the LSA's age is smaller than
2596 MAXAGE. Otherwise clients would see LSA updates with max age just
2597 before they are deleted from the LSDB. LSA delete messages have
2598 MAXAGE too but should not be filtered. */
2599 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2605 area_id = lsa->area->area_id;
2607 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2609 ifaddr = lsa->oi->address->u.prefix4;
2611 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2613 lsa->flags & OSPF_LSA_SELF, lsa->data);
2616 zlog_warn ("notify_clients_lsa: msg_new failed");
2619 /* Notify all clients that new LSA is added/updated */
2620 apiserver_clients_lsa_change_notify (msgtype, lsa);
2622 /* Clients made their own copies of msg so we can free msg here */
2629 ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2631 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2635 ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2637 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2640 #endif /* SUPPORT_OSPF_API */