back to topotato report
topotato coverage report
Current view: top level - ospfd - ospf_apiserver.c (source / functions) Hit Total Coverage
Test: test_ospf_topo1.py::OSPFTopo1Test Lines: 25 1256 2.0 %
Date: 2023-02-24 18:38:32 Functions: 7 71 9.9 %

          Line data    Source code
       1             : /*
       2             :  * Server side of OSPF API.
       3             :  * Copyright (C) 2001, 2002 Ralph Keller
       4             :  * Copyright (c) 2022, LabN Consulting, L.L.C.
       5             :  *
       6             :  * This file is part of GNU Zebra.
       7             :  *
       8             :  * GNU Zebra is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published
      10             :  * by the Free Software Foundation; either version 2, or (at your
      11             :  * option) any later version.
      12             :  *
      13             :  * GNU Zebra is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License along
      19             :  * with this program; see the file COPYING; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #ifdef SUPPORT_OSPF_API
      26             : 
      27             : #include "linklist.h"
      28             : #include "prefix.h"
      29             : #include "if.h"
      30             : #include "table.h"
      31             : #include "memory.h"
      32             : #include "command.h"
      33             : #include "vty.h"
      34             : #include "stream.h"
      35             : #include "log.h"
      36             : #include "thread.h"
      37             : #include "hash.h"
      38             : #include "sockunion.h" /* for inet_aton() */
      39             : #include "buffer.h"
      40             : 
      41             : #include <sys/types.h>
      42             : 
      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"
      58             : #include "ospfd/ospf_errors.h"
      59             : #include "ospfd/ospf_memory.h"
      60             : 
      61             : #include "ospfd/ospf_api.h"
      62             : #include "ospfd/ospf_apiserver.h"
      63             : 
      64          12 : DEFINE_MTYPE_STATIC(OSPFD, APISERVER, "API Server");
      65          12 : DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
      66             : 
      67             : /* This is an implementation of an API to the OSPF daemon that allows
      68             :  * external applications to access the OSPF daemon through socket
      69             :  * connections. The application can use this API to inject its own
      70             :  * opaque LSAs and flood them to other OSPF daemons. Other OSPF
      71             :  * daemons then receive these LSAs and inform applications through the
      72             :  * API by sending a corresponding message. The application can also
      73             :  * register to receive all LSA types (in addition to opaque types) and
      74             :  * use this information to reconstruct the OSPF's LSDB. The OSPF
      75             :  * daemon supports multiple applications concurrently.  */
      76             : 
      77             : /* List of all active connections. */
      78             : struct list *apiserver_list;
      79             : 
      80             : /* -----------------------------------------------------------
      81             :  * Functions to lookup interfaces
      82             :  * -----------------------------------------------------------
      83             :  */
      84             : 
      85           0 : struct ospf_interface *ospf_apiserver_if_lookup_by_addr(struct in_addr address)
      86             : {
      87           0 :         struct listnode *node, *nnode;
      88           0 :         struct ospf_interface *oi;
      89           0 :         struct ospf *ospf = NULL;
      90             : 
      91           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
      92           0 :         if (!ospf)
      93             :                 return NULL;
      94             : 
      95           0 :         for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
      96           0 :                 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
      97           0 :                         if (IPV4_ADDR_SAME(&address, &oi->address->u.prefix4))
      98           0 :                                 return oi;
      99             : 
     100             :         return NULL;
     101             : }
     102             : 
     103           0 : struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
     104             : {
     105           0 :         struct listnode *node, *nnode;
     106           0 :         struct ospf_interface *oi;
     107           0 :         struct ospf *ospf = NULL;
     108             : 
     109           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
     110           0 :         if (!ospf)
     111             :                 return NULL;
     112             : 
     113           0 :         for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
     114           0 :                 if (oi->ifp == ifp)
     115           0 :                         return oi;
     116             : 
     117             :         return NULL;
     118             : }
     119             : 
     120             : /* -----------------------------------------------------------
     121             :  * Initialization
     122             :  * -----------------------------------------------------------
     123             :  */
     124             : 
     125           0 : unsigned short ospf_apiserver_getport(void)
     126             : {
     127           0 :         struct servent *sp = getservbyname("ospfapi", "tcp");
     128             : 
     129           0 :         return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
     130             : }
     131             : 
     132             : /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
     133           0 : int ospf_apiserver_init(void)
     134             : {
     135           0 :         int fd;
     136           0 :         int rc = -1;
     137             : 
     138             :         /* Create new socket for synchronous messages. */
     139           0 :         fd = ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET);
     140             : 
     141           0 :         if (fd < 0)
     142           0 :                 goto out;
     143             : 
     144             :         /* Schedule new thread that handles accepted connections. */
     145           0 :         ospf_apiserver_event(OSPF_APISERVER_ACCEPT, fd, NULL);
     146             : 
     147             :         /* Initialize list that keeps track of all connections. */
     148           0 :         apiserver_list = list_new();
     149             : 
     150             :         /* Register opaque-independent call back functions. These functions
     151             :            are invoked on ISM, NSM changes and LSA update and LSA deletes */
     152           0 :         rc = ospf_register_opaque_functab(
     153             :                 0 /* all LSAs */, 0 /* all opaque types */,
     154             :                 ospf_apiserver_new_if, ospf_apiserver_del_if,
     155             :                 ospf_apiserver_ism_change, ospf_apiserver_nsm_change, NULL,
     156             :                 NULL, NULL, NULL, /* ospf_apiserver_show_info */
     157             :                 NULL,             /* originator_func */
     158             :                 NULL,             /* ospf_apiserver_lsa_refresher */
     159             :                 ospf_apiserver_lsa_update, ospf_apiserver_lsa_delete);
     160           0 :         if (rc != 0) {
     161           0 :                 flog_warn(
     162             :                         EC_OSPF_OPAQUE_REGISTRATION,
     163             :                         "ospf_apiserver_init: Failed to register opaque type [0/0]");
     164             :         }
     165             : 
     166             :         rc = 0;
     167             : 
     168           0 : out:
     169           0 :         return rc;
     170             : }
     171             : 
     172             : /* Terminate OSPF API module. */
     173           0 : void ospf_apiserver_term(void)
     174             : {
     175           0 :         struct ospf_apiserver *apiserv;
     176             : 
     177             :         /* Unregister wildcard [0/0] type */
     178           0 :         ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */);
     179             : 
     180             :         /*
     181             :          * Free all client instances.  ospf_apiserver_free removes the node
     182             :          * from the list, so we examine the head of the list anew each time.
     183             :          */
     184           0 :         while (apiserver_list
     185           0 :                && (apiserv = listgetdata(listhead(apiserver_list))) != NULL)
     186           0 :                 ospf_apiserver_free(apiserv);
     187             : 
     188             :         /* Free client list itself */
     189           0 :         if (apiserver_list)
     190           0 :                 list_delete(&apiserver_list);
     191             : 
     192             :         /* Free wildcard list */
     193             :         /* XXX  */
     194           0 : }
     195             : 
     196           0 : static struct ospf_apiserver *lookup_apiserver(uint8_t lsa_type,
     197             :                                                uint8_t opaque_type)
     198             : {
     199           0 :         struct listnode *n1, *n2;
     200           0 :         struct registered_opaque_type *r;
     201           0 :         struct ospf_apiserver *apiserv, *found = NULL;
     202             : 
     203             :         /* XXX: this approaches O(n**2) */
     204           0 :         for (ALL_LIST_ELEMENTS_RO(apiserver_list, n1, apiserv)) {
     205           0 :                 for (ALL_LIST_ELEMENTS_RO(apiserv->opaque_types, n2, r))
     206           0 :                         if (r->lsa_type == lsa_type
     207           0 :                             && r->opaque_type == opaque_type) {
     208           0 :                                 found = apiserv;
     209           0 :                                 goto out;
     210             :                         }
     211             :         }
     212           0 : out:
     213           0 :         return found;
     214             : }
     215             : 
     216           0 : static struct ospf_apiserver *lookup_apiserver_by_lsa(struct ospf_lsa *lsa)
     217             : {
     218           0 :         struct lsa_header *lsah = lsa->data;
     219           0 :         struct ospf_apiserver *found = NULL;
     220             : 
     221           0 :         if (IS_OPAQUE_LSA(lsah->type)) {
     222           0 :                 found = lookup_apiserver(
     223           0 :                         lsah->type, GET_OPAQUE_TYPE(ntohl(lsah->id.s_addr)));
     224             :         }
     225           0 :         return found;
     226             : }
     227             : 
     228             : /* -----------------------------------------------------------
     229             :  * Following are functions to manage client connections.
     230             :  * -----------------------------------------------------------
     231             :  */
     232           0 : static int ospf_apiserver_new_lsa_hook(struct ospf_lsa *lsa)
     233             : {
     234           0 :         if (IS_DEBUG_OSPF_EVENT)
     235           0 :                 zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
     236             :                            (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total);
     237           0 :         return 0;
     238             : }
     239             : 
     240           0 : static int ospf_apiserver_del_lsa_hook(struct ospf_lsa *lsa)
     241             : {
     242           0 :         if (IS_DEBUG_OSPF_EVENT)
     243           0 :                 zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
     244             :                            (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total);
     245           0 :         return 0;
     246             : }
     247             : 
     248             : /* Allocate new connection structure. */
     249           0 : struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async)
     250             : {
     251           0 :         struct ospf_apiserver *new =
     252           0 :                 XMALLOC(MTYPE_APISERVER, sizeof(struct ospf_apiserver));
     253             : 
     254           0 :         new->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER,
     255             :                               sizeof(struct lsa_filter_type));
     256             : 
     257           0 :         new->fd_sync = fd_sync;
     258           0 :         new->fd_async = fd_async;
     259             : 
     260             :         /* list of registered opaque types that application uses */
     261           0 :         new->opaque_types = list_new();
     262             : 
     263             :         /* Initialize temporary strage for LSA instances to be refreshed. */
     264           0 :         memset(&new->reserve, 0, sizeof(struct ospf_lsdb));
     265           0 :         ospf_lsdb_init(&new->reserve);
     266             : 
     267           0 :         new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
     268           0 :         new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
     269             : 
     270           0 :         new->out_sync_fifo = msg_fifo_new();
     271           0 :         new->out_async_fifo = msg_fifo_new();
     272           0 :         new->t_sync_read = NULL;
     273             : #ifdef USE_ASYNC_READ
     274             :         new->t_async_read = NULL;
     275             : #endif /* USE_ASYNC_READ */
     276           0 :         new->t_sync_write = NULL;
     277           0 :         new->t_async_write = NULL;
     278             : 
     279           0 :         new->filter->typemask = 0; /* filter all LSAs */
     280           0 :         new->filter->origin = ANY_ORIGIN;
     281           0 :         new->filter->num_areas = 0;
     282             : 
     283           0 :         return new;
     284             : }
     285             : 
     286           0 : void ospf_apiserver_event(enum ospf_apiserver_event event, int fd,
     287             :                           struct ospf_apiserver *apiserv)
     288             : {
     289           0 :         switch (event) {
     290           0 :         case OSPF_APISERVER_ACCEPT:
     291           0 :                 (void)thread_add_read(master, ospf_apiserver_accept, apiserv,
     292             :                                       fd, NULL);
     293           0 :                 break;
     294           0 :         case OSPF_APISERVER_SYNC_READ:
     295           0 :                 apiserv->t_sync_read = NULL;
     296           0 :                 thread_add_read(master, ospf_apiserver_read, apiserv, fd,
     297             :                                 &apiserv->t_sync_read);
     298           0 :                 break;
     299             : #ifdef USE_ASYNC_READ
     300             :         case OSPF_APISERVER_ASYNC_READ:
     301             :                 apiserv->t_async_read = NULL;
     302             :                 thread_add_read(master, ospf_apiserver_read, apiserv, fd,
     303             :                                 &apiserv->t_async_read);
     304             :                 break;
     305             : #endif /* USE_ASYNC_READ */
     306           0 :         case OSPF_APISERVER_SYNC_WRITE:
     307           0 :                 thread_add_write(master, ospf_apiserver_sync_write, apiserv, fd,
     308             :                                  &apiserv->t_sync_write);
     309           0 :                 break;
     310           0 :         case OSPF_APISERVER_ASYNC_WRITE:
     311           0 :                 thread_add_write(master, ospf_apiserver_async_write, apiserv,
     312             :                                  fd, &apiserv->t_async_write);
     313           0 :                 break;
     314             :         }
     315           0 : }
     316             : 
     317             : /* Free instance. First unregister all opaque types used by
     318             :    application, flush opaque LSAs injected by application
     319             :    from network and close connection. */
     320           0 : void ospf_apiserver_free(struct ospf_apiserver *apiserv)
     321             : {
     322           0 :         struct listnode *node;
     323             : 
     324             :         /* Cancel read and write threads. */
     325           0 :         THREAD_OFF(apiserv->t_sync_read);
     326             : #ifdef USE_ASYNC_READ
     327             :         THREAD_OFF(apiserv->t_async_read);
     328             : #endif /* USE_ASYNC_READ */
     329           0 :         THREAD_OFF(apiserv->t_sync_write);
     330           0 :         THREAD_OFF(apiserv->t_async_write);
     331             : 
     332             :         /* Unregister all opaque types that application registered
     333             :            and flush opaque LSAs if still in LSDB. */
     334             : 
     335           0 :         while ((node = listhead(apiserv->opaque_types)) != NULL) {
     336           0 :                 struct registered_opaque_type *regtype = listgetdata(node);
     337             : 
     338           0 :                 ospf_apiserver_unregister_opaque_type(
     339           0 :                         apiserv, regtype->lsa_type, regtype->opaque_type);
     340             :         }
     341             : 
     342             :         /* Close connections to OSPFd. */
     343           0 :         if (apiserv->fd_sync > 0) {
     344           0 :                 close(apiserv->fd_sync);
     345             :         }
     346             : 
     347           0 :         if (apiserv->fd_async > 0) {
     348           0 :                 close(apiserv->fd_async);
     349             :         }
     350             : 
     351             :         /* Free fifos */
     352           0 :         msg_fifo_free(apiserv->out_sync_fifo);
     353           0 :         msg_fifo_free(apiserv->out_async_fifo);
     354             : 
     355             :         /* Clear temporary strage for LSA instances to be refreshed. */
     356           0 :         ospf_lsdb_delete_all(&apiserv->reserve);
     357           0 :         ospf_lsdb_cleanup(&apiserv->reserve);
     358             : 
     359             :         /* Remove from the list of active clients. */
     360           0 :         listnode_delete(apiserver_list, apiserv);
     361             : 
     362           0 :         if (IS_DEBUG_OSPF_EVENT)
     363           0 :                 zlog_debug("API: Delete apiserv(%p), total#(%d)",
     364             :                            (void *)apiserv, apiserver_list->count);
     365             : 
     366             :         /* And free instance. */
     367           0 :         XFREE(MTYPE_APISERVER, apiserv);
     368           0 : }
     369             : 
     370           0 : void ospf_apiserver_read(struct thread *thread)
     371             : {
     372           0 :         struct ospf_apiserver *apiserv;
     373           0 :         struct msg *msg;
     374           0 :         int fd;
     375           0 :         enum ospf_apiserver_event event;
     376             : 
     377           0 :         apiserv = THREAD_ARG(thread);
     378           0 :         fd = THREAD_FD(thread);
     379             : 
     380           0 :         if (fd == apiserv->fd_sync) {
     381           0 :                 event = OSPF_APISERVER_SYNC_READ;
     382           0 :                 apiserv->t_sync_read = NULL;
     383             : 
     384           0 :                 if (IS_DEBUG_OSPF_EVENT)
     385           0 :                         zlog_debug("API: %s: Peer: %pI4/%u", __func__,
     386             :                                    &apiserv->peer_sync.sin_addr,
     387             :                                    ntohs(apiserv->peer_sync.sin_port));
     388             :         }
     389             : #ifdef USE_ASYNC_READ
     390             :         else if (fd == apiserv->fd_async) {
     391             :                 event = OSPF_APISERVER_ASYNC_READ;
     392             :                 apiserv->t_async_read = NULL;
     393             : 
     394             :                 if (IS_DEBUG_OSPF_EVENT)
     395             :                         zlog_debug("API: %s: Peer: %pI4/%u", __func__,
     396             :                                    &apiserv->peer_async.sin_addr,
     397             :                                    ntohs(apiserv->peer_async.sin_port));
     398             :         }
     399             : #endif /* USE_ASYNC_READ */
     400             :         else {
     401           0 :                 zlog_warn("%s: Unknown fd(%d)", __func__, fd);
     402           0 :                 ospf_apiserver_free(apiserv);
     403           0 :                 return;
     404             :         }
     405             : 
     406             :         /* Read message from fd. */
     407           0 :         msg = msg_read(fd);
     408           0 :         if (msg == NULL) {
     409           0 :                 zlog_warn("%s: read failed on fd=%d, closing connection",
     410             :                           __func__, fd);
     411             : 
     412             :                 /* Perform cleanup. */
     413           0 :                 ospf_apiserver_free(apiserv);
     414           0 :                 return;
     415             :         }
     416             : 
     417           0 :         if (IS_DEBUG_OSPF_EVENT)
     418           0 :                 msg_print(msg);
     419             : 
     420             :         /* Dispatch to corresponding message handler. */
     421           0 :         ospf_apiserver_handle_msg(apiserv, msg);
     422             : 
     423             :         /* Prepare for next message, add read thread. */
     424           0 :         ospf_apiserver_event(event, fd, apiserv);
     425             : 
     426           0 :         msg_free(msg);
     427             : }
     428             : 
     429           0 : void ospf_apiserver_sync_write(struct thread *thread)
     430             : {
     431           0 :         struct ospf_apiserver *apiserv;
     432           0 :         struct msg *msg;
     433           0 :         int fd;
     434           0 :         int rc = -1;
     435             : 
     436           0 :         apiserv = THREAD_ARG(thread);
     437           0 :         assert(apiserv);
     438           0 :         fd = THREAD_FD(thread);
     439             : 
     440           0 :         apiserv->t_sync_write = NULL;
     441             : 
     442             :         /* Sanity check */
     443           0 :         if (fd != apiserv->fd_sync) {
     444           0 :                 zlog_warn("%s: Unknown fd=%d", __func__, fd);
     445           0 :                 goto out;
     446             :         }
     447             : 
     448           0 :         if (IS_DEBUG_OSPF_EVENT)
     449           0 :                 zlog_debug("API: %s: Peer: %pI4/%u", __func__,
     450             :                            &apiserv->peer_sync.sin_addr,
     451             :                            ntohs(apiserv->peer_sync.sin_port));
     452             : 
     453             :         /* Check whether there is really a message in the fifo. */
     454           0 :         msg = msg_fifo_pop(apiserv->out_sync_fifo);
     455           0 :         if (!msg) {
     456           0 :                 zlog_warn("API: %s: No message in Sync-FIFO?", __func__);
     457           0 :                 return;
     458             :         }
     459             : 
     460           0 :         if (IS_DEBUG_OSPF_EVENT)
     461           0 :                 msg_print(msg);
     462             : 
     463           0 :         rc = msg_write(fd, msg);
     464             : 
     465             :         /* Once a message is dequeued, it should be freed anyway. */
     466           0 :         msg_free(msg);
     467             : 
     468           0 :         if (rc < 0) {
     469           0 :                 zlog_warn("%s: write failed on fd=%d", __func__, fd);
     470           0 :                 goto out;
     471             :         }
     472             : 
     473             : 
     474             :         /* If more messages are in sync message fifo, schedule write thread. */
     475           0 :         if (msg_fifo_head(apiserv->out_sync_fifo)) {
     476           0 :                 ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE,
     477             :                                      apiserv->fd_sync, apiserv);
     478             :         }
     479             : 
     480           0 : out:
     481             : 
     482           0 :         if (rc < 0) {
     483             :                 /* Perform cleanup and disconnect with peer */
     484           0 :                 ospf_apiserver_free(apiserv);
     485             :         }
     486             : }
     487             : 
     488             : 
     489           0 : void ospf_apiserver_async_write(struct thread *thread)
     490             : {
     491           0 :         struct ospf_apiserver *apiserv;
     492           0 :         struct msg *msg;
     493           0 :         int fd;
     494           0 :         int rc = -1;
     495             : 
     496           0 :         apiserv = THREAD_ARG(thread);
     497           0 :         assert(apiserv);
     498           0 :         fd = THREAD_FD(thread);
     499             : 
     500           0 :         apiserv->t_async_write = NULL;
     501             : 
     502             :         /* Sanity check */
     503           0 :         if (fd != apiserv->fd_async) {
     504           0 :                 zlog_warn("%s: Unknown fd=%d", __func__, fd);
     505           0 :                 goto out;
     506             :         }
     507             : 
     508           0 :         if (IS_DEBUG_OSPF_EVENT)
     509           0 :                 zlog_debug("API: %s: Peer: %pI4/%u", __func__,
     510             :                            &apiserv->peer_async.sin_addr,
     511             :                            ntohs(apiserv->peer_async.sin_port));
     512             : 
     513             :         /* Check whether there is really a message in the fifo. */
     514           0 :         msg = msg_fifo_pop(apiserv->out_async_fifo);
     515           0 :         if (!msg) {
     516           0 :                 zlog_warn("API: %s: No message in Async-FIFO?", __func__);
     517           0 :                 return;
     518             :         }
     519             : 
     520           0 :         if (IS_DEBUG_OSPF_EVENT)
     521           0 :                 msg_print(msg);
     522             : 
     523           0 :         rc = msg_write(fd, msg);
     524             : 
     525             :         /* Once a message is dequeued, it should be freed anyway. */
     526           0 :         msg_free(msg);
     527             : 
     528           0 :         if (rc < 0) {
     529           0 :                 zlog_warn("%s: write failed on fd=%d", __func__, fd);
     530           0 :                 goto out;
     531             :         }
     532             : 
     533             : 
     534             :         /* If more messages are in async message fifo, schedule write thread. */
     535           0 :         if (msg_fifo_head(apiserv->out_async_fifo)) {
     536           0 :                 ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE,
     537             :                                      apiserv->fd_async, apiserv);
     538             :         }
     539             : 
     540           0 : out:
     541             : 
     542           0 :         if (rc < 0) {
     543             :                 /* Perform cleanup and disconnect with peer */
     544           0 :                 ospf_apiserver_free(apiserv);
     545             :         }
     546             : }
     547             : 
     548             : 
     549           0 : int ospf_apiserver_serv_sock_family(unsigned short port, int family)
     550             : {
     551           0 :         union sockunion su;
     552           0 :         int accept_sock;
     553           0 :         int rc;
     554             : 
     555           0 :         memset(&su, 0, sizeof(union sockunion));
     556           0 :         su.sa.sa_family = family;
     557             : 
     558             :         /* Make new socket */
     559           0 :         accept_sock = sockunion_stream_socket(&su);
     560           0 :         if (accept_sock < 0)
     561             :                 return accept_sock;
     562             : 
     563             :         /* This is a server, so reuse address and port */
     564           0 :         sockopt_reuseaddr(accept_sock);
     565           0 :         sockopt_reuseport(accept_sock);
     566             : 
     567             :         /* Bind socket to address and given port. */
     568           0 :         rc = sockunion_bind(accept_sock, &su, port, NULL);
     569           0 :         if (rc < 0) {
     570           0 :                 close(accept_sock); /* Close socket */
     571           0 :                 return rc;
     572             :         }
     573             : 
     574             :         /* Listen socket under queue length 3. */
     575           0 :         rc = listen(accept_sock, 3);
     576           0 :         if (rc < 0) {
     577           0 :                 zlog_warn("%s: listen: %s", __func__, safe_strerror(errno));
     578           0 :                 close(accept_sock); /* Close socket */
     579           0 :                 return rc;
     580             :         }
     581             :         return accept_sock;
     582             : }
     583             : 
     584             : 
     585             : /* Accept connection request from external applications. For each
     586             :    accepted connection allocate own connection instance. */
     587           0 : void ospf_apiserver_accept(struct thread *thread)
     588             : {
     589           0 :         int accept_sock;
     590           0 :         int new_sync_sock;
     591           0 :         int new_async_sock;
     592           0 :         union sockunion su;
     593           0 :         struct ospf_apiserver *apiserv;
     594           0 :         struct sockaddr_in peer_async;
     595           0 :         struct sockaddr_in peer_sync;
     596           0 :         unsigned int peerlen;
     597           0 :         int ret;
     598             : 
     599             :         /* THREAD_ARG (thread) is NULL */
     600           0 :         accept_sock = THREAD_FD(thread);
     601             : 
     602             :         /* Keep hearing on socket for further connections. */
     603           0 :         ospf_apiserver_event(OSPF_APISERVER_ACCEPT, accept_sock, NULL);
     604             : 
     605           0 :         memset(&su, 0, sizeof(union sockunion));
     606             :         /* Accept connection for synchronous messages */
     607           0 :         new_sync_sock = sockunion_accept(accept_sock, &su);
     608           0 :         if (new_sync_sock < 0) {
     609           0 :                 zlog_warn("%s: accept: %s", __func__, safe_strerror(errno));
     610           0 :                 return;
     611             :         }
     612             : 
     613             :         /* Get port address and port number of peer to make reverse connection.
     614             :            The reverse channel uses the port number of the peer port+1. */
     615             : 
     616           0 :         memset(&peer_sync, 0, sizeof(peer_sync));
     617           0 :         peerlen = sizeof(struct sockaddr_in);
     618             : 
     619           0 :         ret = getpeername(new_sync_sock, (struct sockaddr *)&peer_sync,
     620             :                           &peerlen);
     621           0 :         if (ret < 0) {
     622           0 :                 zlog_warn("%s: getpeername: %s", __func__,
     623             :                           safe_strerror(errno));
     624           0 :                 close(new_sync_sock);
     625           0 :                 return;
     626             :         }
     627             : 
     628           0 :         if (IS_DEBUG_OSPF_EVENT)
     629           0 :                 zlog_debug("API: %s: New peer: %pI4/%u", __func__,
     630             :                            &peer_sync.sin_addr, ntohs(peer_sync.sin_port));
     631             : 
     632             :         /* Create new socket for asynchronous messages. */
     633           0 :         peer_async = peer_sync;
     634           0 :         peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
     635             : 
     636             :         /* Check if remote port number to make reverse connection is valid one.
     637             :          */
     638           0 :         if (ntohs(peer_async.sin_port) == ospf_apiserver_getport()) {
     639           0 :                 zlog_warn("API: %s: Peer(%pI4/%u): Invalid async port number?",
     640             :                           __func__, &peer_async.sin_addr,
     641             :                           ntohs(peer_async.sin_port));
     642           0 :                 close(new_sync_sock);
     643           0 :                 return;
     644             :         }
     645             : 
     646           0 :         new_async_sock = socket(AF_INET, SOCK_STREAM, 0);
     647           0 :         if (new_async_sock < 0) {
     648           0 :                 zlog_warn("%s: socket: %s", __func__, safe_strerror(errno));
     649           0 :                 close(new_sync_sock);
     650           0 :                 return;
     651             :         }
     652             : 
     653           0 :         ret = connect(new_async_sock, (struct sockaddr *)&peer_async,
     654             :                       sizeof(struct sockaddr_in));
     655             : 
     656           0 :         if (ret < 0) {
     657           0 :                 zlog_warn("%s: connect: %s", __func__, safe_strerror(errno));
     658           0 :                 close(new_sync_sock);
     659           0 :                 close(new_async_sock);
     660           0 :                 return;
     661             :         }
     662             : 
     663             : #ifdef USE_ASYNC_READ
     664             : #else  /* USE_ASYNC_READ */
     665             :         /* Make the asynchronous channel write-only. */
     666           0 :         ret = shutdown(new_async_sock, SHUT_RD);
     667           0 :         if (ret < 0) {
     668           0 :                 zlog_warn("%s: shutdown: %s", __func__, safe_strerror(errno));
     669           0 :                 close(new_sync_sock);
     670           0 :                 close(new_async_sock);
     671           0 :                 return;
     672             :         }
     673             : #endif /* USE_ASYNC_READ */
     674             : 
     675             :         /* Allocate new server-side connection structure */
     676           0 :         apiserv = ospf_apiserver_new(new_sync_sock, new_async_sock);
     677             : 
     678             :         /* Add to active connection list */
     679           0 :         listnode_add(apiserver_list, apiserv);
     680           0 :         apiserv->peer_sync = peer_sync;
     681           0 :         apiserv->peer_async = peer_async;
     682             : 
     683             :         /* And add read threads for new connection */
     684           0 :         ospf_apiserver_event(OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
     685             : #ifdef USE_ASYNC_READ
     686             :         ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ, new_async_sock,
     687             :                              apiserv);
     688             : #endif /* USE_ASYNC_READ */
     689             : 
     690           0 :         if (IS_DEBUG_OSPF_EVENT)
     691           0 :                 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv,
     692             :                            apiserver_list->count);
     693             : }
     694             : 
     695             : 
     696             : /* -----------------------------------------------------------
     697             :  * Send reply with return code to client application
     698             :  * -----------------------------------------------------------
     699             :  */
     700             : 
     701           0 : static int ospf_apiserver_send_msg(struct ospf_apiserver *apiserv,
     702             :                                    struct msg *msg)
     703             : {
     704           0 :         struct msg_fifo *fifo;
     705           0 :         struct msg *msg2;
     706           0 :         enum ospf_apiserver_event event;
     707           0 :         int fd;
     708             : 
     709           0 :         switch (msg->hdr.msgtype) {
     710           0 :         case MSG_REPLY:
     711           0 :                 fifo = apiserv->out_sync_fifo;
     712           0 :                 fd = apiserv->fd_sync;
     713           0 :                 event = OSPF_APISERVER_SYNC_WRITE;
     714           0 :                 break;
     715           0 :         case MSG_READY_NOTIFY:
     716             :         case MSG_LSA_UPDATE_NOTIFY:
     717             :         case MSG_LSA_DELETE_NOTIFY:
     718             :         case MSG_NEW_IF:
     719             :         case MSG_DEL_IF:
     720             :         case MSG_ISM_CHANGE:
     721             :         case MSG_NSM_CHANGE:
     722             :         case MSG_REACHABLE_CHANGE:
     723             :         case MSG_ROUTER_ID_CHANGE:
     724           0 :                 fifo = apiserv->out_async_fifo;
     725           0 :                 fd = apiserv->fd_async;
     726           0 :                 event = OSPF_APISERVER_ASYNC_WRITE;
     727           0 :                 break;
     728           0 :         default:
     729           0 :                 zlog_warn("%s: Unknown message type %d", __func__,
     730             :                           msg->hdr.msgtype);
     731           0 :                 return -1;
     732             :         }
     733             : 
     734             :         /* Make a copy of the message and put in the fifo. Once the fifo
     735             :            gets drained by the write thread, the message will be freed. */
     736             :         /* NB: Given "msg" is untouched in this function. */
     737           0 :         msg2 = msg_dup(msg);
     738             : 
     739             :         /* Enqueue message into corresponding fifo queue */
     740           0 :         msg_fifo_push(fifo, msg2);
     741             : 
     742             :         /* Schedule write thread */
     743           0 :         ospf_apiserver_event(event, fd, apiserv);
     744           0 :         return 0;
     745             : }
     746             : 
     747           0 : int ospf_apiserver_send_reply(struct ospf_apiserver *apiserv, uint32_t seqnr,
     748             :                               uint8_t rc)
     749             : {
     750           0 :         struct msg *msg = new_msg_reply(seqnr, rc);
     751           0 :         int ret;
     752             : 
     753           0 :         if (!msg) {
     754           0 :                 zlog_warn("%s: msg_new failed", __func__);
     755             : #ifdef NOTYET
     756             :                 /* Cannot allocate new message. What should we do? */
     757             :                 ospf_apiserver_free(apiserv);
     758             : #endif
     759           0 :                 return -1;
     760             :         }
     761             : 
     762           0 :         ret = ospf_apiserver_send_msg(apiserv, msg);
     763           0 :         msg_free(msg);
     764           0 :         return ret;
     765             : }
     766             : 
     767             : 
     768             : /* -----------------------------------------------------------
     769             :  * Generic message dispatching handler function
     770             :  * -----------------------------------------------------------
     771             :  */
     772             : 
     773           0 : int ospf_apiserver_handle_msg(struct ospf_apiserver *apiserv, struct msg *msg)
     774             : {
     775           0 :         int rc;
     776             : 
     777             :         /* Call corresponding message handler function. */
     778           0 :         switch (msg->hdr.msgtype) {
     779           0 :         case MSG_REGISTER_OPAQUETYPE:
     780           0 :                 rc = ospf_apiserver_handle_register_opaque_type(apiserv, msg);
     781           0 :                 break;
     782           0 :         case MSG_UNREGISTER_OPAQUETYPE:
     783           0 :                 rc = ospf_apiserver_handle_unregister_opaque_type(apiserv, msg);
     784           0 :                 break;
     785           0 :         case MSG_REGISTER_EVENT:
     786           0 :                 rc = ospf_apiserver_handle_register_event(apiserv, msg);
     787           0 :                 break;
     788           0 :         case MSG_SYNC_LSDB:
     789           0 :                 rc = ospf_apiserver_handle_sync_lsdb(apiserv, msg);
     790           0 :                 break;
     791           0 :         case MSG_ORIGINATE_REQUEST:
     792           0 :                 rc = ospf_apiserver_handle_originate_request(apiserv, msg);
     793           0 :                 break;
     794           0 :         case MSG_DELETE_REQUEST:
     795           0 :                 rc = ospf_apiserver_handle_delete_request(apiserv, msg);
     796           0 :                 break;
     797           0 :         case MSG_SYNC_REACHABLE:
     798           0 :                 rc = ospf_apiserver_handle_sync_reachable(apiserv, msg);
     799           0 :                 break;
     800           0 :         case MSG_SYNC_ISM:
     801           0 :                 rc = ospf_apiserver_handle_sync_ism(apiserv, msg);
     802           0 :                 break;
     803           0 :         case MSG_SYNC_NSM:
     804           0 :                 rc = ospf_apiserver_handle_sync_nsm(apiserv, msg);
     805           0 :                 break;
     806           0 :         case MSG_SYNC_ROUTER_ID:
     807           0 :                 rc = ospf_apiserver_handle_sync_router_id(apiserv, msg);
     808           0 :                 break;
     809           0 :         default:
     810           0 :                 zlog_warn("%s: Unknown message type: %d", __func__,
     811             :                           msg->hdr.msgtype);
     812           0 :                 rc = -1;
     813             :         }
     814           0 :         return rc;
     815             : }
     816             : 
     817             : 
     818             : /* -----------------------------------------------------------
     819             :  * Following are functions for opaque type registration
     820             :  * -----------------------------------------------------------
     821             :  */
     822             : 
     823           0 : int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv,
     824             :                                         uint8_t lsa_type, uint8_t opaque_type)
     825             : {
     826           0 :         struct registered_opaque_type *regtype;
     827           0 :         int (*originator_func)(void *arg);
     828           0 :         int rc;
     829             : 
     830           0 :         switch (lsa_type) {
     831             :         case OSPF_OPAQUE_LINK_LSA:
     832             :                 originator_func = ospf_apiserver_lsa9_originator;
     833             :                 break;
     834           0 :         case OSPF_OPAQUE_AREA_LSA:
     835           0 :                 originator_func = ospf_apiserver_lsa10_originator;
     836           0 :                 break;
     837           0 :         case OSPF_OPAQUE_AS_LSA:
     838           0 :                 originator_func = ospf_apiserver_lsa11_originator;
     839           0 :                 break;
     840           0 :         default:
     841           0 :                 zlog_warn("%s: lsa_type(%d)", __func__, lsa_type);
     842           0 :                 return OSPF_API_ILLEGALLSATYPE;
     843             :         }
     844             : 
     845             : 
     846             :         /* Register opaque function table */
     847             :         /* NB: Duplicated registration will be detected inside the function. */
     848           0 :         rc = ospf_register_opaque_functab(
     849             :                 lsa_type, opaque_type, NULL, /* ospf_apiserver_new_if */
     850             :                 NULL,                        /* ospf_apiserver_del_if */
     851             :                 NULL,                        /* ospf_apiserver_ism_change */
     852             :                 NULL,                        /* ospf_apiserver_nsm_change */
     853             :                 NULL, NULL, NULL, ospf_apiserver_show_info, originator_func,
     854             :                 ospf_apiserver_lsa_refresher,
     855             :                 NULL, /* ospf_apiserver_lsa_update */
     856             :                 NULL /* ospf_apiserver_lsa_delete */);
     857             : 
     858           0 :         if (rc != 0) {
     859           0 :                 flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
     860             :                           "Failed to register opaque type [%d/%d]", lsa_type,
     861             :                           opaque_type);
     862           0 :                 return OSPF_API_OPAQUETYPEINUSE;
     863             :         }
     864             : 
     865             :         /* Remember the opaque type that application registers so when
     866             :            connection shuts down, we can flush all LSAs of this opaque
     867             :            type. */
     868             : 
     869           0 :         regtype =
     870           0 :                 XCALLOC(MTYPE_APISERVER, sizeof(struct registered_opaque_type));
     871           0 :         regtype->lsa_type = lsa_type;
     872           0 :         regtype->opaque_type = opaque_type;
     873             : 
     874             :         /* Add to list of registered opaque types */
     875           0 :         listnode_add(apiserv->opaque_types, regtype);
     876             : 
     877           0 :         if (IS_DEBUG_OSPF_EVENT)
     878           0 :                 zlog_debug(
     879             :                         "API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)",
     880             :                         lsa_type, opaque_type, (void *)apiserv,
     881             :                         listcount(apiserv->opaque_types));
     882             : 
     883             :         return 0;
     884             : }
     885             : 
     886           0 : int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver *apiserv,
     887             :                                           uint8_t lsa_type, uint8_t opaque_type)
     888             : {
     889           0 :         struct listnode *node, *nnode;
     890           0 :         struct registered_opaque_type *regtype;
     891             : 
     892           0 :         for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) {
     893             :                 /* Check if we really registered this opaque type */
     894           0 :                 if (regtype->lsa_type == lsa_type
     895           0 :                     && regtype->opaque_type == opaque_type) {
     896             : 
     897             :                         /* Yes, we registered this opaque type. Flush
     898             :                            all existing opaque LSAs of this type */
     899             : 
     900           0 :                         ospf_apiserver_flush_opaque_lsa(apiserv, lsa_type,
     901             :                                                         opaque_type);
     902           0 :                         ospf_delete_opaque_functab(lsa_type, opaque_type);
     903             : 
     904             :                         /* Remove from list of registered opaque types */
     905           0 :                         listnode_delete(apiserv->opaque_types, regtype);
     906             : 
     907           0 :                         if (IS_DEBUG_OSPF_EVENT)
     908           0 :                                 zlog_debug(
     909             :                                         "API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)",
     910             :                                         lsa_type, opaque_type, (void *)apiserv,
     911             :                                         listcount(apiserv->opaque_types));
     912             : 
     913           0 :                         return 0;
     914             :                 }
     915             :         }
     916             : 
     917             :         /* Opaque type is not registered */
     918           0 :         zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type,
     919             :                   opaque_type);
     920           0 :         return OSPF_API_OPAQUETYPENOTREGISTERED;
     921             : }
     922             : 
     923             : 
     924           0 : static int apiserver_is_opaque_type_registered(struct ospf_apiserver *apiserv,
     925             :                                                uint8_t lsa_type,
     926             :                                                uint8_t opaque_type)
     927             : {
     928           0 :         struct listnode *node, *nnode;
     929           0 :         struct registered_opaque_type *regtype;
     930             : 
     931             :         /* XXX: how many types are there? if few, why not just a bitmap? */
     932           0 :         for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) {
     933             :                 /* Check if we really registered this opaque type */
     934           0 :                 if (regtype->lsa_type == lsa_type
     935           0 :                     && regtype->opaque_type == opaque_type) {
     936             :                         /* Yes registered */
     937             :                         return 1;
     938             :                 }
     939             :         }
     940             :         /* Not registered */
     941             :         return 0;
     942             : }
     943             : 
     944           0 : int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver *apiserv,
     945             :                                                struct msg *msg)
     946             : {
     947           0 :         struct msg_register_opaque_type *rmsg;
     948           0 :         uint8_t lsa_type;
     949           0 :         uint8_t opaque_type;
     950           0 :         int rc = 0;
     951             : 
     952             :         /* Extract parameters from register opaque type message */
     953           0 :         rmsg = (struct msg_register_opaque_type *)STREAM_DATA(msg->s);
     954             : 
     955           0 :         lsa_type = rmsg->lsatype;
     956           0 :         opaque_type = rmsg->opaquetype;
     957             : 
     958           0 :         rc = ospf_apiserver_register_opaque_type(apiserv, lsa_type,
     959             :                                                  opaque_type);
     960             : 
     961             :         /* Send a reply back to client including return code */
     962           0 :         rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
     963           0 :         if (rc < 0)
     964           0 :                 goto out;
     965             : 
     966             :         /* Now inform application about opaque types that are ready */
     967           0 :         switch (lsa_type) {
     968           0 :         case OSPF_OPAQUE_LINK_LSA:
     969           0 :                 ospf_apiserver_notify_ready_type9(apiserv);
     970           0 :                 break;
     971           0 :         case OSPF_OPAQUE_AREA_LSA:
     972           0 :                 ospf_apiserver_notify_ready_type10(apiserv);
     973           0 :                 break;
     974           0 :         case OSPF_OPAQUE_AS_LSA:
     975           0 :                 ospf_apiserver_notify_ready_type11(apiserv);
     976           0 :                 break;
     977             :         }
     978           0 : out:
     979           0 :         return rc;
     980             : }
     981             : 
     982             : 
     983             : /* Notify specific client about all opaque types 9 that are ready. */
     984           0 : void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv)
     985             : {
     986           0 :         struct listnode *node, *nnode;
     987           0 :         struct listnode *node2, *nnode2;
     988           0 :         struct ospf *ospf;
     989           0 :         struct ospf_interface *oi;
     990           0 :         struct registered_opaque_type *r;
     991             : 
     992           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
     993             : 
     994           0 :         for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
     995             :                 /* Check if this interface is indeed ready for type 9 */
     996           0 :                 if (!ospf_apiserver_is_ready_type9(oi))
     997             :                         continue;
     998             : 
     999             :                 /* Check for registered opaque type 9 types */
    1000             :                 /* XXX: loop-de-loop - optimise me */
    1001           0 :                 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
    1002             :                                        r)) {
    1003           0 :                         struct msg *msg;
    1004             : 
    1005           0 :                         if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
    1006             : 
    1007             :                                 /* Yes, this opaque type is ready */
    1008           0 :                                 msg = new_msg_ready_notify(
    1009           0 :                                         0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
    1010           0 :                                         oi->address->u.prefix4);
    1011           0 :                                 if (!msg) {
    1012           0 :                                         zlog_warn("%s: msg_new failed",
    1013             :                                                   __func__);
    1014             : #ifdef NOTYET
    1015             :                                         /* Cannot allocate new message. What
    1016             :                                          * should we do? */
    1017             :                                         ospf_apiserver_free(apiserv);
    1018             : #endif
    1019           0 :                                         goto out;
    1020             :                                 }
    1021           0 :                                 ospf_apiserver_send_msg(apiserv, msg);
    1022           0 :                                 msg_free(msg);
    1023             :                         }
    1024             :                 }
    1025             :         }
    1026             : 
    1027           0 : out:
    1028           0 :         return;
    1029             : }
    1030             : 
    1031             : 
    1032             : /* Notify specific client about all opaque types 10 that are ready. */
    1033           0 : void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv)
    1034             : {
    1035           0 :         struct listnode *node, *nnode;
    1036           0 :         struct listnode *node2, *nnode2;
    1037           0 :         struct ospf *ospf;
    1038           0 :         struct ospf_area *area;
    1039             : 
    1040           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1041             : 
    1042           0 :         for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
    1043           0 :                 struct registered_opaque_type *r;
    1044             : 
    1045           0 :                 if (!ospf_apiserver_is_ready_type10(area)) {
    1046             :                         continue;
    1047             :                 }
    1048             : 
    1049             :                 /* Check for registered opaque type 10 types */
    1050             :                 /* XXX: loop in loop - optimise me */
    1051           0 :                 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
    1052             :                                        r)) {
    1053           0 :                         struct msg *msg;
    1054             : 
    1055           0 :                         if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
    1056             :                                 /* Yes, this opaque type is ready */
    1057           0 :                                 msg = new_msg_ready_notify(
    1058           0 :                                         0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
    1059             :                                         area->area_id);
    1060           0 :                                 if (!msg) {
    1061           0 :                                         zlog_warn("%s: msg_new failed",
    1062             :                                                   __func__);
    1063             : #ifdef NOTYET
    1064             :                                         /* Cannot allocate new message. What
    1065             :                                          * should we do? */
    1066             :                                         ospf_apiserver_free(apiserv);
    1067             : #endif
    1068           0 :                                         goto out;
    1069             :                                 }
    1070           0 :                                 ospf_apiserver_send_msg(apiserv, msg);
    1071           0 :                                 msg_free(msg);
    1072             :                         }
    1073             :                 }
    1074             :         }
    1075             : 
    1076           0 : out:
    1077           0 :         return;
    1078             : }
    1079             : 
    1080             : /* Notify specific client about all opaque types 11 that are ready */
    1081           0 : void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv)
    1082             : {
    1083           0 :         struct listnode *node, *nnode;
    1084           0 :         struct ospf *ospf;
    1085           0 :         struct registered_opaque_type *r;
    1086             : 
    1087           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1088             : 
    1089             :         /* Can type 11 be originated? */
    1090           0 :         if (!ospf_apiserver_is_ready_type11(ospf))
    1091             :                 goto out;
    1092             : 
    1093             :         /* Check for registered opaque type 11 types */
    1094           0 :         for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, r)) {
    1095           0 :                 struct msg *msg;
    1096           0 :                 struct in_addr noarea_id = {.s_addr = 0L};
    1097             : 
    1098           0 :                 if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
    1099             :                         /* Yes, this opaque type is ready */
    1100           0 :                         msg = new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA,
    1101           0 :                                                    r->opaque_type, noarea_id);
    1102             : 
    1103           0 :                         if (!msg) {
    1104           0 :                                 zlog_warn("%s: msg_new failed", __func__);
    1105             : #ifdef NOTYET
    1106             :                                 /* Cannot allocate new message. What should we
    1107             :                                  * do? */
    1108             :                                 ospf_apiserver_free(apiserv);
    1109             : #endif
    1110           0 :                                 goto out;
    1111             :                         }
    1112           0 :                         ospf_apiserver_send_msg(apiserv, msg);
    1113           0 :                         msg_free(msg);
    1114             :                 }
    1115             :         }
    1116             : 
    1117           0 : out:
    1118           0 :         return;
    1119             : }
    1120             : 
    1121           0 : int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver *apiserv,
    1122             :                                                  struct msg *msg)
    1123             : {
    1124           0 :         struct msg_unregister_opaque_type *umsg;
    1125           0 :         uint8_t ltype;
    1126           0 :         uint8_t otype;
    1127           0 :         int rc = 0;
    1128             : 
    1129             :         /* Extract parameters from unregister opaque type message */
    1130           0 :         umsg = (struct msg_unregister_opaque_type *)STREAM_DATA(msg->s);
    1131             : 
    1132           0 :         ltype = umsg->lsatype;
    1133           0 :         otype = umsg->opaquetype;
    1134             : 
    1135           0 :         rc = ospf_apiserver_unregister_opaque_type(apiserv, ltype, otype);
    1136             : 
    1137             :         /* Send a reply back to client including return code */
    1138           0 :         rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
    1139             : 
    1140           0 :         return rc;
    1141             : }
    1142             : 
    1143             : 
    1144             : /* -----------------------------------------------------------
    1145             :  * Following are functions for event (filter) registration.
    1146             :  * -----------------------------------------------------------
    1147             :  */
    1148           0 : int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
    1149             :                                          struct msg *msg)
    1150             : {
    1151           0 :         struct msg_register_event *rmsg;
    1152           0 :         int rc;
    1153           0 :         uint32_t seqnum;
    1154           0 :         size_t size;
    1155             : 
    1156           0 :         rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
    1157             : 
    1158             :         /* Get request sequence number */
    1159           0 :         seqnum = msg_get_seq(msg);
    1160             : 
    1161             :         /* Free existing filter in apiserv. */
    1162           0 :         XFREE(MTYPE_APISERVER_MSGFILTER, apiserv->filter);
    1163             :         /* Alloc new space for filter. */
    1164           0 :         size = ntohs(msg->hdr.msglen);
    1165           0 :         if (size < OSPF_MAX_LSA_SIZE) {
    1166             : 
    1167           0 :                 apiserv->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER, size);
    1168             : 
    1169             :                 /* copy it over. */
    1170           0 :                 memcpy(apiserv->filter, &rmsg->filter, size);
    1171           0 :                 rc = OSPF_API_OK;
    1172             :         } else
    1173             :                 rc = OSPF_API_NOMEMORY;
    1174             : 
    1175             :         /* Send a reply back to client with return code */
    1176           0 :         rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
    1177           0 :         return rc;
    1178             : }
    1179             : 
    1180             : 
    1181             : /* -----------------------------------------------------------
    1182             :  * Following are functions for LSDB synchronization.
    1183             :  * -----------------------------------------------------------
    1184             :  */
    1185             : 
    1186           0 : static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg,
    1187             :                                    int int_arg)
    1188             : {
    1189           0 :         struct ospf_apiserver *apiserv;
    1190           0 :         int seqnum;
    1191           0 :         struct msg *msg;
    1192           0 :         struct param_t {
    1193             :                 struct ospf_apiserver *apiserv;
    1194             :                 struct lsa_filter_type *filter;
    1195             :         } * param;
    1196           0 :         int rc = -1;
    1197             : 
    1198             :         /* Sanity check */
    1199           0 :         assert(lsa->data);
    1200           0 :         assert(p_arg);
    1201             : 
    1202           0 :         param = (struct param_t *)p_arg;
    1203           0 :         apiserv = param->apiserv;
    1204           0 :         seqnum = (uint32_t)int_arg;
    1205             : 
    1206             :         /* Check origin in filter. */
    1207           0 :         if ((param->filter->origin == ANY_ORIGIN)
    1208           0 :             || (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) {
    1209             : 
    1210             :                 /* Default area for AS-External and Opaque11 LSAs */
    1211           0 :                 struct in_addr area_id = {.s_addr = 0L};
    1212             : 
    1213             :                 /* Default interface for non Opaque9 LSAs */
    1214           0 :                 struct in_addr ifaddr = {.s_addr = 0L};
    1215             : 
    1216           0 :                 if (lsa->area) {
    1217           0 :                         area_id = lsa->area->area_id;
    1218             :                 }
    1219           0 :                 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
    1220           0 :                         ifaddr = lsa->oi->address->u.prefix4;
    1221             :                 }
    1222             : 
    1223           0 :                 msg = new_msg_lsa_change_notify(
    1224             :                         MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id,
    1225           0 :                         lsa->flags & OSPF_LSA_SELF, lsa->data);
    1226           0 :                 if (!msg) {
    1227           0 :                         zlog_warn("%s: new_msg_update failed", __func__);
    1228             : #ifdef NOTYET
    1229             :                         /* Cannot allocate new message. What should we do? */
    1230             :                         /*        ospf_apiserver_free (apiserv);*/ /* Do nothing
    1231             :                                                                       here XXX
    1232             :                                                                       */
    1233             : #endif
    1234           0 :                         goto out;
    1235             :                 }
    1236             : 
    1237             :                 /* Send LSA */
    1238           0 :                 ospf_apiserver_send_msg(apiserv, msg);
    1239           0 :                 msg_free(msg);
    1240             :         }
    1241             :         rc = 0;
    1242             : 
    1243           0 : out:
    1244           0 :         return rc;
    1245             : }
    1246             : 
    1247           0 : int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
    1248             :                                     struct msg *msg)
    1249             : {
    1250           0 :         struct listnode *node, *nnode;
    1251           0 :         uint32_t seqnum;
    1252           0 :         int rc = 0;
    1253           0 :         struct msg_sync_lsdb *smsg;
    1254           0 :         struct ospf_apiserver_param_t {
    1255             :                 struct ospf_apiserver *apiserv;
    1256             :                 struct lsa_filter_type *filter;
    1257             :         } param;
    1258           0 :         uint16_t mask;
    1259           0 :         struct route_node *rn;
    1260           0 :         struct ospf_lsa *lsa;
    1261           0 :         struct ospf *ospf;
    1262           0 :         struct ospf_area *area;
    1263             : 
    1264           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1265             : 
    1266             :         /* Get request sequence number */
    1267           0 :         seqnum = msg_get_seq(msg);
    1268             :         /* Set sync msg. */
    1269           0 :         smsg = (struct msg_sync_lsdb *)STREAM_DATA(msg->s);
    1270             : 
    1271             :         /* Set parameter struct. */
    1272           0 :         param.apiserv = apiserv;
    1273           0 :         param.filter = &smsg->filter;
    1274             : 
    1275             :         /* Remember mask. */
    1276           0 :         mask = ntohs(smsg->filter.typemask);
    1277             : 
    1278             :         /* Iterate over all areas. */
    1279           0 :         for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
    1280           0 :                 int i;
    1281           0 :                 uint32_t *area_id = NULL;
    1282             : 
    1283             :                 /* Compare area_id with area_ids in sync request. */
    1284           0 :                 if ((i = smsg->filter.num_areas) > 0) {
    1285             :                         /* Let area_id point to the list of area IDs,
    1286             :                          * which is at the end of smsg->filter. */
    1287           0 :                         area_id = (uint32_t *)(&smsg->filter + 1);
    1288           0 :                         while (i) {
    1289           0 :                                 if (*area_id == area->area_id.s_addr) {
    1290             :                                         break;
    1291             :                                 }
    1292           0 :                                 i--;
    1293           0 :                                 area_id++;
    1294             :                         }
    1295             :                 } else {
    1296             :                         i = 1;
    1297             :                 }
    1298             : 
    1299             :                 /* If area was found, then i>0 here. */
    1300           0 :                 if (i) {
    1301             :                         /* Check msg type. */
    1302           0 :                         if (mask & Power2[OSPF_ROUTER_LSA])
    1303           0 :                                 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
    1304           0 :                                         apiserver_sync_callback(
    1305             :                                                 lsa, (void *)&param, seqnum);
    1306           0 :                         if (mask & Power2[OSPF_NETWORK_LSA])
    1307           0 :                                 LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
    1308           0 :                                         apiserver_sync_callback(
    1309             :                                                 lsa, (void *)&param, seqnum);
    1310           0 :                         if (mask & Power2[OSPF_SUMMARY_LSA])
    1311           0 :                                 LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
    1312           0 :                                         apiserver_sync_callback(
    1313             :                                                 lsa, (void *)&param, seqnum);
    1314           0 :                         if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
    1315           0 :                                 LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
    1316           0 :                                         apiserver_sync_callback(
    1317             :                                                 lsa, (void *)&param, seqnum);
    1318           0 :                         if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
    1319           0 :                                 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
    1320           0 :                                         apiserver_sync_callback(
    1321             :                                                 lsa, (void *)&param, seqnum);
    1322           0 :                         if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
    1323           0 :                                 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
    1324           0 :                                         apiserver_sync_callback(
    1325             :                                                 lsa, (void *)&param, seqnum);
    1326             :                 }
    1327             :         }
    1328             : 
    1329             :         /* For AS-external LSAs */
    1330           0 :         if (ospf->lsdb) {
    1331           0 :                 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
    1332           0 :                         LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
    1333           0 :                                 apiserver_sync_callback(lsa, (void *)&param,
    1334             :                                                         seqnum);
    1335             :         }
    1336             : 
    1337             :         /* For AS-external opaque LSAs */
    1338           0 :         if (ospf->lsdb) {
    1339           0 :                 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
    1340           0 :                         LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
    1341           0 :                                 apiserver_sync_callback(lsa, (void *)&param,
    1342             :                                                         seqnum);
    1343             :         }
    1344             : 
    1345             :         /* Send a reply back to client with return code */
    1346           0 :         rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
    1347           0 :         return rc;
    1348             : }
    1349             : 
    1350             : /*
    1351             :  * -----------------------------------------------------------
    1352             :  * Followings are functions for synchronization.
    1353             :  * -----------------------------------------------------------
    1354             :  */
    1355             : 
    1356           0 : int ospf_apiserver_handle_sync_reachable(struct ospf_apiserver *apiserv,
    1357             :                                          struct msg *msg)
    1358             : {
    1359           0 :         struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1360           0 :         struct route_table *rt = ospf->all_rtrs;
    1361           0 :         uint32_t seqnum = msg_get_seq(msg);
    1362           0 :         struct in_addr *a, *abuf;
    1363           0 :         struct msg_reachable_change *areach;
    1364           0 :         struct msg *amsg;
    1365           0 :         uint mcount, count;
    1366           0 :         int _rc, rc = 0;
    1367             : 
    1368           0 :         if (!rt)
    1369           0 :                 goto out;
    1370             : 
    1371             :         /* send all adds based on current reachable routers */
    1372           0 :         a = abuf = XCALLOC(MTYPE_APISERVER, sizeof(struct in_addr) * rt->count);
    1373           0 :         for (struct route_node *rn = route_top(rt); rn; rn = route_next(rn))
    1374           0 :                 if (listhead((struct list *)rn->info))
    1375           0 :                         *a++ = rn->p.u.prefix4;
    1376             : 
    1377           0 :         assert((a - abuf) <= (long)rt->count);
    1378           0 :         count = (a - abuf);
    1379             : 
    1380           0 :         a = abuf;
    1381           0 :         while (count && !rc) {
    1382           0 :                 amsg = new_msg_reachable_change(seqnum, count, a, 0, NULL);
    1383           0 :                 areach = (struct msg_reachable_change *)STREAM_DATA(amsg->s);
    1384           0 :                 mcount = ntohs(areach->nadd) + ntohs(areach->nremove);
    1385           0 :                 assert(mcount <= count);
    1386           0 :                 a = a + mcount;
    1387           0 :                 count -= mcount;
    1388           0 :                 rc = ospf_apiserver_send_msg(apiserv, amsg);
    1389           0 :                 msg_free(amsg);
    1390             :         }
    1391           0 :         XFREE(MTYPE_APISERVER, abuf);
    1392             : 
    1393           0 : out:
    1394             :         /* Send a reply back to client with return code */
    1395           0 :         _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
    1396           0 :         rc = rc ? rc : _rc;
    1397           0 :         apiserv->reachable_sync = !rc;
    1398           0 :         return rc;
    1399             : }
    1400             : 
    1401           0 : int ospf_apiserver_handle_sync_ism(struct ospf_apiserver *apiserv,
    1402             :                                    struct msg *msg)
    1403             : {
    1404           0 :         struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1405           0 :         struct listnode *anode, *inode;
    1406           0 :         struct ospf_area *area;
    1407           0 :         struct ospf_interface *oi;
    1408           0 :         struct msg *m;
    1409           0 :         uint32_t seqnum = msg_get_seq(msg);
    1410           0 :         int _rc, rc = 0;
    1411             : 
    1412             :         /* walk all areas */
    1413           0 :         for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
    1414             :                 /* walk all interfaces */
    1415           0 :                 for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi)) {
    1416           0 :                         m = new_msg_ism_change(seqnum, oi->address->u.prefix4,
    1417           0 :                                                area->area_id, oi->state);
    1418           0 :                         rc = ospf_apiserver_send_msg(apiserv, m);
    1419           0 :                         msg_free(m);
    1420           0 :                         if (rc)
    1421             :                                 break;
    1422             :                 }
    1423           0 :                 if (rc)
    1424             :                         break;
    1425             :         }
    1426             :         /* Send a reply back to client with return code */
    1427           0 :         _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
    1428           0 :         return rc ? rc : _rc;
    1429             : }
    1430             : 
    1431             : 
    1432           0 : int ospf_apiserver_handle_sync_nsm(struct ospf_apiserver *apiserv,
    1433             :                                    struct msg *msg)
    1434             : {
    1435           0 :         struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1436           0 :         struct listnode *anode, *inode;
    1437           0 :         struct ospf_area *area;
    1438           0 :         struct ospf_interface *oi;
    1439           0 :         struct ospf_neighbor *nbr;
    1440           0 :         struct route_node *rn;
    1441           0 :         struct msg *m;
    1442           0 :         uint32_t seqnum = msg_get_seq(msg);
    1443           0 :         int _rc, rc = 0;
    1444             : 
    1445             :         /* walk all areas */
    1446           0 :         for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
    1447             :                 /* walk all interfaces */
    1448           0 :                 for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi)) {
    1449             :                         /* walk all neighbors */
    1450           0 :                         for (rn = route_top(oi->nbrs); rn;
    1451           0 :                              rn = route_next(rn)) {
    1452           0 :                                 nbr = rn->info;
    1453           0 :                                 if (!nbr)
    1454           0 :                                         continue;
    1455           0 :                                 m = new_msg_nsm_change(
    1456           0 :                                         seqnum, oi->address->u.prefix4,
    1457           0 :                                         nbr->src, nbr->router_id, nbr->state);
    1458           0 :                                 rc = ospf_apiserver_send_msg(apiserv, m);
    1459           0 :                                 msg_free(m);
    1460           0 :                                 if (rc)
    1461             :                                         break;
    1462             :                         }
    1463           0 :                         if (rc)
    1464             :                                 break;
    1465             :                 }
    1466           0 :                 if (rc)
    1467             :                         break;
    1468             :         }
    1469             :         /* Send a reply back to client with return code */
    1470           0 :         _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
    1471           0 :         return rc ? rc : _rc;
    1472             : }
    1473             : 
    1474             : 
    1475           0 : int ospf_apiserver_handle_sync_router_id(struct ospf_apiserver *apiserv,
    1476             :                                          struct msg *msg)
    1477             : {
    1478           0 :         struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1479           0 :         uint32_t seqnum = msg_get_seq(msg);
    1480           0 :         struct msg *m;
    1481           0 :         int _rc, rc = 0;
    1482             : 
    1483           0 :         m = new_msg_router_id_change(seqnum, ospf->router_id);
    1484           0 :         rc = ospf_apiserver_send_msg(apiserv, m);
    1485           0 :         msg_free(m);
    1486             : 
    1487             :         /* Send a reply back to client with return code */
    1488           0 :         _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
    1489           0 :         return rc ? rc : _rc;
    1490             : }
    1491             : 
    1492             : /* -----------------------------------------------------------
    1493             :  * Following are functions to originate or update LSA
    1494             :  * from an application.
    1495             :  * -----------------------------------------------------------
    1496             :  */
    1497             : 
    1498             : /* Create a new internal opaque LSA by taking prototype and filling in
    1499             :    missing fields such as age, sequence number, advertising router,
    1500             :    checksum and so on. The interface parameter is used for type 9
    1501             :    LSAs, area parameter for type 10. Type 11 LSAs do neither need area
    1502             :    nor interface. */
    1503             : 
    1504           0 : struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
    1505             :                                                struct ospf_interface *oi,
    1506             :                                                struct lsa_header *protolsa)
    1507             : {
    1508           0 :         struct stream *s;
    1509           0 :         struct lsa_header *newlsa;
    1510           0 :         struct ospf_lsa *new = NULL;
    1511           0 :         uint8_t options = 0x0;
    1512           0 :         uint16_t length;
    1513             : 
    1514           0 :         struct ospf *ospf;
    1515             : 
    1516           0 :         if (oi && oi->ospf)
    1517             :                 ospf = oi->ospf;
    1518             :         else
    1519           0 :                 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1520             : 
    1521           0 :         assert(ospf);
    1522             : 
    1523             :         /* Create a stream for internal opaque LSA */
    1524           0 :         if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
    1525           0 :                 zlog_warn("%s: stream_new failed", __func__);
    1526           0 :                 return NULL;
    1527             :         }
    1528             : 
    1529           0 :         newlsa = (struct lsa_header *)STREAM_DATA(s);
    1530             : 
    1531             :         /* XXX If this is a link-local LSA or an AS-external LSA, how do we
    1532             :            have to set options? */
    1533             : 
    1534           0 :         if (area) {
    1535           0 :                 options = LSA_OPTIONS_GET(area);
    1536           0 :                 options |= LSA_OPTIONS_NSSA_GET(area);
    1537             :         }
    1538             : 
    1539           0 :         options |= OSPF_OPTION_O; /* Don't forget to set option bit */
    1540             : 
    1541           0 :         if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
    1542           0 :                 zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
    1543             :                            protolsa->type, &protolsa->id);
    1544             :         }
    1545             : 
    1546             :         /* Set opaque-LSA header fields. */
    1547           0 :         lsa_header_set(s, options, protolsa->type, protolsa->id,
    1548             :                        ospf->router_id);
    1549             : 
    1550             :         /* Set opaque-LSA body fields. */
    1551           0 :         stream_put(s, ((uint8_t *)protolsa) + sizeof(struct lsa_header),
    1552           0 :                    ntohs(protolsa->length) - sizeof(struct lsa_header));
    1553             : 
    1554             :         /* Determine length of LSA. */
    1555           0 :         length = stream_get_endp(s);
    1556           0 :         newlsa->length = htons(length);
    1557             : 
    1558             :         /* Create OSPF LSA. */
    1559           0 :         new = ospf_lsa_new_and_data(length);
    1560             : 
    1561           0 :         new->area = area;
    1562           0 :         new->oi = oi;
    1563           0 :         new->vrf_id = ospf->vrf_id;
    1564             : 
    1565           0 :         SET_FLAG(new->flags, OSPF_LSA_SELF);
    1566           0 :         memcpy(new->data, newlsa, length);
    1567           0 :         stream_free(s);
    1568             : 
    1569           0 :         return new;
    1570             : }
    1571             : 
    1572             : 
    1573           0 : int ospf_apiserver_is_ready_type9(struct ospf_interface *oi)
    1574             : {
    1575             :         /* We can always handle getting opaque's even if we can't flood them */
    1576           0 :         return 1;
    1577             : }
    1578             : 
    1579           0 : int ospf_apiserver_is_ready_type10(struct ospf_area *area)
    1580             : {
    1581             :         /* We can always handle getting opaque's even if we can't flood them */
    1582           0 :         return 1;
    1583             : }
    1584             : 
    1585           0 : int ospf_apiserver_is_ready_type11(struct ospf *ospf)
    1586             : {
    1587             :         /* We can always handle getting opaque's even if we can't flood them */
    1588           0 :         return 1;
    1589             : }
    1590             : 
    1591             : 
    1592           0 : int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
    1593             :                                             struct msg *msg)
    1594             : {
    1595           0 :         struct msg_originate_request *omsg;
    1596           0 :         struct lsa_header *data;
    1597           0 :         struct ospf_lsa *new;
    1598           0 :         struct ospf_lsa *old;
    1599           0 :         struct ospf_area *area = NULL;
    1600           0 :         struct ospf_interface *oi = NULL;
    1601           0 :         struct ospf_lsdb *lsdb = NULL;
    1602           0 :         struct ospf *ospf;
    1603           0 :         int lsa_type, opaque_type;
    1604           0 :         int ready = 0;
    1605           0 :         int rc = 0;
    1606             : 
    1607           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1608             : 
    1609             :         /* Extract opaque LSA data from message */
    1610           0 :         omsg = (struct msg_originate_request *)STREAM_DATA(msg->s);
    1611           0 :         data = &omsg->data;
    1612             : 
    1613             :         /* Determine interface for type9 or area for type10 LSAs. */
    1614           0 :         switch (data->type) {
    1615           0 :         case OSPF_OPAQUE_LINK_LSA:
    1616           0 :                 oi = ospf_apiserver_if_lookup_by_addr(omsg->ifaddr);
    1617           0 :                 if (!oi) {
    1618           0 :                         zlog_warn("%s: unknown interface %pI4", __func__,
    1619             :                                   &omsg->ifaddr);
    1620           0 :                         rc = OSPF_API_NOSUCHINTERFACE;
    1621           0 :                         goto out;
    1622             :                 }
    1623           0 :                 area = oi->area;
    1624           0 :                 lsdb = area->lsdb;
    1625           0 :                 break;
    1626           0 :         case OSPF_OPAQUE_AREA_LSA:
    1627           0 :                 area = ospf_area_lookup_by_area_id(ospf, omsg->area_id);
    1628           0 :                 if (!area) {
    1629           0 :                         zlog_warn("%s: unknown area %pI4", __func__,
    1630             :                                   &omsg->area_id);
    1631           0 :                         rc = OSPF_API_NOSUCHAREA;
    1632           0 :                         goto out;
    1633             :                 }
    1634           0 :                 lsdb = area->lsdb;
    1635           0 :                 break;
    1636           0 :         case OSPF_OPAQUE_AS_LSA:
    1637           0 :                 lsdb = ospf->lsdb;
    1638           0 :                 break;
    1639           0 :         default:
    1640             :                 /* We can only handle opaque types here */
    1641           0 :                 zlog_warn("%s: Cannot originate non-opaque LSA type %d",
    1642             :                           __func__, data->type);
    1643           0 :                 rc = OSPF_API_ILLEGALLSATYPE;
    1644           0 :                 goto out;
    1645             :         }
    1646             : 
    1647             :         /* Check if we registered this opaque type */
    1648           0 :         lsa_type = data->type;
    1649           0 :         opaque_type = GET_OPAQUE_TYPE(ntohl(data->id.s_addr));
    1650             : 
    1651           0 :         if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
    1652             :                                                  opaque_type)) {
    1653           0 :                 zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
    1654             :                           __func__, lsa_type, opaque_type);
    1655           0 :                 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
    1656           0 :                 goto out;
    1657             :         }
    1658             : 
    1659             :         /* Make sure that the neighbors are ready before we can originate */
    1660           0 :         switch (data->type) {
    1661             :         case OSPF_OPAQUE_LINK_LSA:
    1662             :                 ready = ospf_apiserver_is_ready_type9(oi);
    1663             :                 break;
    1664             :         case OSPF_OPAQUE_AREA_LSA:
    1665             :                 ready = ospf_apiserver_is_ready_type10(area);
    1666             :                 break;
    1667             :         case OSPF_OPAQUE_AS_LSA:
    1668             :                 ready = ospf_apiserver_is_ready_type11(ospf);
    1669             :                 break;
    1670             :         default:
    1671             :                 break;
    1672             :         }
    1673             : 
    1674           0 :         if (!ready) {
    1675           0 :                 zlog_warn("Neighbors not ready to originate type %d",
    1676             :                           data->type);
    1677           0 :                 rc = OSPF_API_NOTREADY;
    1678           0 :                 goto out;
    1679             :         }
    1680             : 
    1681             :         /* Create OSPF's internal opaque LSA representation */
    1682           0 :         new = ospf_apiserver_opaque_lsa_new(area, oi, data);
    1683           0 :         if (!new) {
    1684           0 :                 rc = OSPF_API_NOMEMORY; /* XXX */
    1685           0 :                 goto out;
    1686             :         }
    1687             : 
    1688             :         /* Determine if LSA is new or an update for an existing one. */
    1689           0 :         old = ospf_lsdb_lookup(lsdb, new);
    1690             : 
    1691           0 :         if (!old || !ospf_opaque_is_owned(old)) {
    1692             :                 /* New LSA install in LSDB. */
    1693           0 :                 rc = ospf_apiserver_originate1(new, old);
    1694             :         } else {
    1695             :                 /*
    1696             :                  * Keep the new LSA instance in the "waiting place" until the
    1697             :                  * next
    1698             :                  * refresh timing. If several LSA update requests for the same
    1699             :                  * LSID
    1700             :                  * have issued by peer, the last one takes effect.
    1701             :                  */
    1702           0 :                 new->lsdb = &apiserv->reserve;
    1703           0 :                 ospf_lsdb_add(&apiserv->reserve, new);
    1704             : 
    1705             :                 /* Kick the scheduler function. */
    1706           0 :                 ospf_opaque_lsa_refresh_schedule(old);
    1707             :         }
    1708             : 
    1709           0 : out:
    1710             : 
    1711             :         /* Send a reply back to client with return code */
    1712           0 :         rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
    1713           0 :         return rc;
    1714             : }
    1715             : 
    1716             : 
    1717             : /* -----------------------------------------------------------
    1718             :  * Flood an LSA within its flooding scope.
    1719             :  * -----------------------------------------------------------
    1720             :  */
    1721             : 
    1722             : /* XXX We can probably use ospf_flood_through instead of this function
    1723             :    but then we need the neighbor parameter. If we set nbr to
    1724             :    NULL then ospf_flood_through crashes due to dereferencing NULL. */
    1725             : 
    1726           0 : void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa)
    1727             : {
    1728           0 :         assert(lsa);
    1729             : 
    1730           0 :         switch (lsa->data->type) {
    1731           0 :         case OSPF_OPAQUE_LINK_LSA:
    1732             :                 /* Increment counters? XXX */
    1733             : 
    1734             :                 /* Flood LSA through local network. */
    1735           0 :                 ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
    1736           0 :                 break;
    1737           0 :         case OSPF_OPAQUE_AREA_LSA:
    1738             :                 /* Update LSA origination count. */
    1739           0 :                 assert(lsa->area);
    1740           0 :                 lsa->area->ospf->lsa_originate_count++;
    1741             : 
    1742             :                 /* Flood LSA through area. */
    1743           0 :                 ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
    1744           0 :                 break;
    1745           0 :         case OSPF_OPAQUE_AS_LSA: {
    1746           0 :                 struct ospf *ospf;
    1747             : 
    1748           0 :                 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1749           0 :                 assert(ospf);
    1750             : 
    1751             :                 /* Increment counters? XXX */
    1752             : 
    1753             :                 /* Flood LSA through AS. */
    1754           0 :                 ospf_flood_through_as(ospf, NULL /*nbr */, lsa);
    1755           0 :                 break;
    1756             :         }
    1757             :         }
    1758           0 : }
    1759             : 
    1760           0 : int ospf_apiserver_originate1(struct ospf_lsa *lsa, struct ospf_lsa *old)
    1761             : {
    1762           0 :         struct ospf *ospf;
    1763             : 
    1764           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1765           0 :         assert(ospf);
    1766             : 
    1767           0 :         if (old) {
    1768             :                 /*
    1769             :                  * An old LSA exists that we didn't originate it in this
    1770             :                  * session. Dump it, but increment past it's seqnum.
    1771             :                  */
    1772           0 :                 assert(!ospf_opaque_is_owned(old));
    1773           0 :                 if (IS_LSA_MAX_SEQ(old)) {
    1774           0 :                         flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
    1775             :                                   "%s: old LSA at maxseq", __func__);
    1776           0 :                         return -1;
    1777             :                 }
    1778           0 :                 lsa->data->ls_seqnum = lsa_seqnum_increment(old);
    1779           0 :                 ospf_discard_from_db(ospf, old->lsdb, old);
    1780             :         }
    1781             : 
    1782             :         /* Install this LSA into LSDB. */
    1783           0 :         if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
    1784           0 :                 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
    1785             :                           "%s: ospf_lsa_install failed", __func__);
    1786           0 :                 return -1;
    1787             :         }
    1788             : 
    1789             : /* Flood LSA within scope */
    1790             : 
    1791             : #ifdef NOTYET
    1792             :         /*
    1793             :          * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
    1794             :          *     parameter, and thus it does not cause SIGSEGV error.
    1795             :          */
    1796             :         ospf_flood_through(NULL /*nbr */, lsa);
    1797             : #else  /* NOTYET */
    1798             : 
    1799           0 :         ospf_apiserver_flood_opaque_lsa(lsa);
    1800             : #endif /* NOTYET */
    1801             : 
    1802           0 :         return 0;
    1803             : }
    1804             : 
    1805             : 
    1806             : /* Opaque LSAs of type 9 on a specific interface can now be
    1807             :    originated. Tell clients that registered type 9. */
    1808           0 : int ospf_apiserver_lsa9_originator(void *arg)
    1809             : {
    1810           0 :         struct ospf_interface *oi;
    1811             : 
    1812           0 :         oi = (struct ospf_interface *)arg;
    1813           0 :         if (listcount(apiserver_list) > 0) {
    1814           0 :                 ospf_apiserver_clients_notify_ready_type9(oi);
    1815             :         }
    1816           0 :         return 0;
    1817             : }
    1818             : 
    1819           0 : int ospf_apiserver_lsa10_originator(void *arg)
    1820             : {
    1821           0 :         struct ospf_area *area;
    1822             : 
    1823           0 :         area = (struct ospf_area *)arg;
    1824           0 :         if (listcount(apiserver_list) > 0) {
    1825           0 :                 ospf_apiserver_clients_notify_ready_type10(area);
    1826             :         }
    1827           0 :         return 0;
    1828             : }
    1829             : 
    1830           0 : int ospf_apiserver_lsa11_originator(void *arg)
    1831             : {
    1832           0 :         struct ospf *ospf;
    1833             : 
    1834           0 :         ospf = (struct ospf *)arg;
    1835           0 :         if (listcount(apiserver_list) > 0) {
    1836           0 :                 ospf_apiserver_clients_notify_ready_type11(ospf);
    1837             :         }
    1838           0 :         return 0;
    1839             : }
    1840             : 
    1841             : 
    1842             : /* Periodically refresh opaque LSAs so that they do not expire in
    1843             :    other routers. */
    1844           0 : struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
    1845             : {
    1846           0 :         struct ospf_apiserver *apiserv;
    1847           0 :         struct ospf_lsa *new = NULL;
    1848           0 :         struct ospf *ospf;
    1849             : 
    1850           0 :         assert(lsa);
    1851             : 
    1852           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1853           0 :         assert(ospf);
    1854             : 
    1855           0 :         apiserv = lookup_apiserver_by_lsa(lsa);
    1856           0 :         if (!apiserv) {
    1857           0 :                 zlog_warn("%s: LSA[%s]: No apiserver?", __func__,
    1858             :                           dump_lsa_key(lsa));
    1859           0 :                 lsa->data->ls_age =
    1860           0 :                         htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
    1861           0 :                 goto out;
    1862             :         }
    1863             : 
    1864           0 :         if (IS_LSA_MAXAGE(lsa)) {
    1865           0 :                 ospf_opaque_lsa_flush_schedule(lsa);
    1866           0 :                 goto out;
    1867             :         }
    1868             : 
    1869             :         /* Check if updated version of LSA instance has already prepared. */
    1870           0 :         new = ospf_lsdb_lookup(&apiserv->reserve, lsa);
    1871           0 :         if (!new) {
    1872             :                 /* This is a periodic refresh, driven by core OSPF mechanism. */
    1873           0 :                 new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi,
    1874             :                                                     lsa->data);
    1875           0 :                 if (!new) {
    1876           0 :                         zlog_warn("%s: Cannot create a new LSA?", __func__);
    1877           0 :                         goto out;
    1878             :                 }
    1879             :         } else {
    1880             :                 /* This is a forcible refresh, requested by OSPF-API client. */
    1881           0 :                 ospf_lsdb_delete(&apiserv->reserve, new);
    1882           0 :                 new->lsdb = NULL;
    1883             :         }
    1884             : 
    1885             :         /* Increment sequence number */
    1886           0 :         new->data->ls_seqnum = lsa_seqnum_increment(lsa);
    1887             : 
    1888             :         /* New LSA is in same area. */
    1889           0 :         new->area = lsa->area;
    1890           0 :         SET_FLAG(new->flags, OSPF_LSA_SELF);
    1891             : 
    1892             :         /* Install LSA into LSDB. */
    1893           0 :         if (ospf_lsa_install(ospf, new->oi, new) == NULL) {
    1894           0 :                 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
    1895             :                           "%s: ospf_lsa_install failed", __func__);
    1896           0 :                 ospf_lsa_unlock(&new);
    1897           0 :                 goto out;
    1898             :         }
    1899             : 
    1900             : /* Flood updated LSA through interface, area or AS */
    1901             : 
    1902             : #ifdef NOTYET
    1903             :         ospf_flood_through(NULL /*nbr */, new);
    1904             : #endif /* NOTYET */
    1905           0 :         ospf_apiserver_flood_opaque_lsa(new);
    1906             : 
    1907             :         /* Debug logging. */
    1908           0 :         if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
    1909           0 :                 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
    1910             :                            new->data->type, &new->data->id);
    1911           0 :                 ospf_lsa_header_dump(new->data);
    1912             :         }
    1913             : 
    1914           0 : out:
    1915           0 :         return new;
    1916             : }
    1917             : 
    1918             : 
    1919             : /* -----------------------------------------------------------
    1920             :  * Following are functions to delete LSAs
    1921             :  * -----------------------------------------------------------
    1922             :  */
    1923             : 
    1924           0 : int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
    1925             :                                          struct msg *msg)
    1926             : {
    1927           0 :         struct msg_delete_request *dmsg;
    1928           0 :         struct ospf_lsa *old;
    1929           0 :         struct ospf_area *area = NULL;
    1930           0 :         struct ospf_interface *oi = NULL;
    1931           0 :         struct in_addr id;
    1932           0 :         int lsa_type, opaque_type;
    1933           0 :         int rc = 0;
    1934           0 :         struct ospf *ospf;
    1935             : 
    1936           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1937           0 :         assert(ospf);
    1938             : 
    1939             :         /* Extract opaque LSA from message */
    1940           0 :         dmsg = (struct msg_delete_request *)STREAM_DATA(msg->s);
    1941             : 
    1942             :         /* Lookup area for link-local and area-local opaque LSAs */
    1943           0 :         switch (dmsg->lsa_type) {
    1944           0 :         case OSPF_OPAQUE_LINK_LSA:
    1945           0 :                 oi = ospf_apiserver_if_lookup_by_addr(dmsg->addr);
    1946           0 :                 if (!oi) {
    1947           0 :                         zlog_warn("%s: unknown interface %pI4", __func__,
    1948             :                                   &dmsg->addr);
    1949           0 :                         rc = OSPF_API_NOSUCHINTERFACE;
    1950           0 :                         goto out;
    1951             :                 }
    1952           0 :                 area = oi->area;
    1953           0 :                 break;
    1954           0 :         case OSPF_OPAQUE_AREA_LSA:
    1955           0 :                 area = ospf_area_lookup_by_area_id(ospf, dmsg->addr);
    1956           0 :                 if (!area) {
    1957           0 :                         zlog_warn("%s: unknown area %pI4", __func__,
    1958             :                                   &dmsg->addr);
    1959           0 :                         rc = OSPF_API_NOSUCHAREA;
    1960           0 :                         goto out;
    1961             :                 }
    1962             :                 break;
    1963             :         case OSPF_OPAQUE_AS_LSA:
    1964             :                 /* AS-external opaque LSAs have no designated area */
    1965             :                 area = NULL;
    1966             :                 break;
    1967           0 :         default:
    1968           0 :                 zlog_warn("%s: Cannot delete non-opaque LSA type %d", __func__,
    1969             :                           dmsg->lsa_type);
    1970           0 :                 rc = OSPF_API_ILLEGALLSATYPE;
    1971           0 :                 goto out;
    1972             :         }
    1973             : 
    1974             :         /* Check if we registered this opaque type */
    1975           0 :         lsa_type = dmsg->lsa_type;
    1976           0 :         opaque_type = dmsg->opaque_type;
    1977             : 
    1978           0 :         if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
    1979             :                                                  opaque_type)) {
    1980           0 :                 zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
    1981             :                           __func__, lsa_type, opaque_type);
    1982           0 :                 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
    1983           0 :                 goto out;
    1984             :         }
    1985             : 
    1986             :         /* opaque_id is in network byte order */
    1987           0 :         id.s_addr = htonl(
    1988             :                 SET_OPAQUE_LSID(dmsg->opaque_type, ntohl(dmsg->opaque_id)));
    1989             : 
    1990             :         /*
    1991             :          * Even if the target LSA has once scheduled to flush, it remains in
    1992             :          * the LSDB until it is finally handled by the maxage remover thread.
    1993             :          * Therefore, the lookup function below may return non-NULL result.
    1994             :          */
    1995           0 :         old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id);
    1996           0 :         if (!old) {
    1997           0 :                 zlog_warn("%s: LSA[Type%d:%pI4] not in LSDB", __func__,
    1998             :                           dmsg->lsa_type, &id);
    1999           0 :                 rc = OSPF_API_NOSUCHLSA;
    2000           0 :                 goto out;
    2001             :         }
    2002             : 
    2003           0 :         if (IS_DEL_ZERO_LEN_LSA(dmsg)) {
    2004             :                 /* minimize the size of the withdrawal: */
    2005           0 :                 old->opaque_zero_len_delete = 1;
    2006             :         }
    2007             : 
    2008             :         /* Schedule flushing of LSA from LSDB */
    2009             :         /* NB: Multiple scheduling will produce a warning message, but harmless.
    2010             :          */
    2011           0 :         ospf_opaque_lsa_flush_schedule(old);
    2012             : 
    2013           0 : out:
    2014             : 
    2015             :         /* Send reply back to client including return code */
    2016           0 :         rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
    2017           0 :         return rc;
    2018             : }
    2019             : 
    2020             : /* Flush self-originated opaque LSA */
    2021           0 : static int apiserver_flush_opaque_type_callback(struct ospf_lsa *lsa,
    2022             :                                                 void *p_arg, int int_arg)
    2023             : {
    2024           0 :         struct param_t {
    2025             :                 struct ospf_apiserver *apiserv;
    2026             :                 uint8_t lsa_type;
    2027             :                 uint8_t opaque_type;
    2028             :         } * param;
    2029             : 
    2030             :         /* Sanity check */
    2031           0 :         assert(lsa->data);
    2032           0 :         assert(p_arg);
    2033           0 :         param = (struct param_t *)p_arg;
    2034             : 
    2035             :         /* If LSA matches type and opaque type then delete it */
    2036           0 :         if (IS_LSA_SELF(lsa) && lsa->data->type == param->lsa_type
    2037           0 :             && GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
    2038           0 :                        == param->opaque_type) {
    2039           0 :                 ospf_opaque_lsa_flush_schedule(lsa);
    2040             :         }
    2041           0 :         return 0;
    2042             : }
    2043             : 
    2044             : /* Delete self-originated opaque LSAs of a given opaque type. This
    2045             :    function is called when an application unregisters a given opaque
    2046             :    type or a connection to an application closes and all those opaque
    2047             :    LSAs need to be flushed the LSDB. */
    2048           0 : void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
    2049             :                                      uint8_t lsa_type, uint8_t opaque_type)
    2050             : {
    2051           0 :         struct param_t {
    2052             :                 struct ospf_apiserver *apiserv;
    2053             :                 uint8_t lsa_type;
    2054             :                 uint8_t opaque_type;
    2055             :         } param;
    2056           0 :         struct listnode *node, *nnode;
    2057           0 :         struct ospf *ospf;
    2058           0 :         struct ospf_area *area;
    2059             : 
    2060           0 :         ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    2061           0 :         assert(ospf);
    2062             : 
    2063             :         /* Set parameter struct. */
    2064           0 :         param.apiserv = apiserv;
    2065           0 :         param.lsa_type = lsa_type;
    2066           0 :         param.opaque_type = opaque_type;
    2067             : 
    2068           0 :         switch (lsa_type) {
    2069           0 :                 struct route_node *rn;
    2070           0 :                 struct ospf_lsa *lsa;
    2071             : 
    2072           0 :         case OSPF_OPAQUE_LINK_LSA:
    2073           0 :                 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
    2074           0 :                         LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
    2075           0 :                                 apiserver_flush_opaque_type_callback(
    2076             :                                         lsa, (void *)&param, 0);
    2077             :                 break;
    2078           0 :         case OSPF_OPAQUE_AREA_LSA:
    2079           0 :                 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
    2080           0 :                         LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
    2081           0 :                                 apiserver_flush_opaque_type_callback(
    2082             :                                         lsa, (void *)&param, 0);
    2083             :                 break;
    2084           0 :         case OSPF_OPAQUE_AS_LSA:
    2085           0 :                 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf), rn, lsa)
    2086           0 :                         apiserver_flush_opaque_type_callback(lsa,
    2087             :                                                              (void *)&param, 0);
    2088             :                 break;
    2089             :         default:
    2090             :                 break;
    2091             :         }
    2092           0 :         return;
    2093             : }
    2094             : 
    2095             : 
    2096             : /* -----------------------------------------------------------
    2097             :  * Following are callback functions to handle opaque types
    2098             :  * -----------------------------------------------------------
    2099             :  */
    2100             : 
    2101           0 : int ospf_apiserver_new_if(struct interface *ifp)
    2102             : {
    2103           0 :         struct ospf_interface *oi;
    2104             : 
    2105             :         /* For some strange reason it seems possible that we are invoked
    2106             :            with an interface that has no name. This seems to happen during
    2107             :            initialization. Return if this happens */
    2108             : 
    2109           0 :         if (ifp->name[0] == '\0') {
    2110             :                 /* interface has empty name */
    2111           0 :                 zlog_warn("%s: interface has no name?", __func__);
    2112           0 :                 return 0;
    2113             :         }
    2114             : 
    2115             :         /* zlog_warn for debugging */
    2116           0 :         zlog_warn("ospf_apiserver_new_if");
    2117           0 :         zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
    2118             :                   ifp->ifindex);
    2119             : 
    2120           0 :         if (ifp->name[0] == '\0') {
    2121             :                 /* interface has empty name */
    2122           0 :                 zlog_warn("%s: interface has no name?", __func__);
    2123           0 :                 return 0;
    2124             :         }
    2125             : 
    2126           0 :         oi = ospf_apiserver_if_lookup_by_ifp(ifp);
    2127             : 
    2128           0 :         if (!oi) {
    2129             :                 /* This interface is known to Zebra but not to OSPF daemon yet.
    2130             :                  */
    2131           0 :                 zlog_warn("%s: interface %s not known to OSPFd?", __func__,
    2132             :                           ifp->name);
    2133           0 :                 return 0;
    2134             :         }
    2135             : 
    2136           0 :         assert(oi);
    2137             : 
    2138             :         /* New interface added to OSPF, tell clients about it */
    2139           0 :         if (listcount(apiserver_list) > 0) {
    2140           0 :                 ospf_apiserver_clients_notify_new_if(oi);
    2141             :         }
    2142             :         return 0;
    2143             : }
    2144             : 
    2145           0 : int ospf_apiserver_del_if(struct interface *ifp)
    2146             : {
    2147           0 :         struct ospf_interface *oi;
    2148             : 
    2149             :         /* zlog_warn for debugging */
    2150           0 :         zlog_warn("%s ifp name=%s status=%d index=%d", __func__, ifp->name,
    2151             :                   ifp->status, ifp->ifindex);
    2152             : 
    2153           0 :         oi = ospf_apiserver_if_lookup_by_ifp(ifp);
    2154             : 
    2155           0 :         if (!oi) {
    2156             :                 /* This interface is known to Zebra but not to OSPF daemon
    2157             :                    anymore. No need to tell clients about it */
    2158           0 :                 zlog_warn("ifp name=%s not known to OSPFd", ifp->name);
    2159           0 :                 return 0;
    2160             :         }
    2161             : 
    2162             :         /* Interface deleted, tell clients about it */
    2163           0 :         if (listcount(apiserver_list) > 0) {
    2164           0 :                 ospf_apiserver_clients_notify_del_if(oi);
    2165             :         }
    2166             :         return 0;
    2167             : }
    2168             : 
    2169           0 : void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state)
    2170             : {
    2171             :         /* Tell clients about interface change */
    2172             : 
    2173             :         /* zlog_warn for debugging */
    2174           0 :         zlog_warn("%s", __func__);
    2175           0 :         if (listcount(apiserver_list) > 0) {
    2176           0 :                 ospf_apiserver_clients_notify_ism_change(oi);
    2177             :         }
    2178             : 
    2179           0 :         zlog_warn("%s oi->ifp->name=%s old_state=%d oi->state=%d", __func__,
    2180             :                   oi->ifp->name, old_state, oi->state);
    2181           0 : }
    2182             : 
    2183           0 : void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
    2184             : {
    2185             :         /* Neighbor status changed, tell clients about it */
    2186           0 :         zlog_warn("%s", __func__);
    2187           0 :         if (listcount(apiserver_list) > 0) {
    2188           0 :                 ospf_apiserver_clients_notify_nsm_change(nbr);
    2189             :         }
    2190           0 : }
    2191             : 
    2192           0 : void ospf_apiserver_show_info(struct vty *vty, struct json_object *json,
    2193             :                               struct ospf_lsa *lsa)
    2194             : {
    2195           0 :         struct opaque_lsa {
    2196             :                 struct lsa_header header;
    2197             :                 uint8_t data[1]; /* opaque data have variable length. This is
    2198             :                                    start
    2199             :                                    address */
    2200             :         };
    2201           0 :         struct opaque_lsa *olsa;
    2202           0 :         int opaquelen;
    2203             : 
    2204           0 :         olsa = (struct opaque_lsa *)lsa->data;
    2205             : 
    2206           0 :         if (VALID_OPAQUE_INFO_LEN(lsa->data))
    2207           0 :                 opaquelen = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE;
    2208             :         else
    2209             :                 opaquelen = 0;
    2210             : 
    2211             :         /* Output information about opaque LSAs */
    2212           0 :         if (json)
    2213           0 :                 json_object_string_addf(json, "opaqueData", "%*pHXn",
    2214           0 :                                         (int)opaquelen, olsa->data);
    2215           0 :         else if (vty != NULL) {
    2216           0 :                 int i;
    2217           0 :                 vty_out(vty,
    2218             :                         "  Added using OSPF API: %u octets of opaque data %s\n",
    2219             :                         opaquelen,
    2220           0 :                         VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
    2221             :                                                          : "(Invalid length?)");
    2222           0 :                 vty_out(vty, "  Opaque data: ");
    2223             : 
    2224           0 :                 for (i = 0; i < opaquelen; i++) {
    2225           0 :                         vty_out(vty, "0x%x ", olsa->data[i]);
    2226             :                 }
    2227           0 :                 vty_out(vty, "\n");
    2228             :         } else {
    2229           0 :                 int i;
    2230           0 :                 zlog_debug(
    2231             :                         "    Added using OSPF API: %u octets of opaque data %s",
    2232             :                         opaquelen,
    2233             :                         VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
    2234             :                                                          : "(Invalid length?)");
    2235           0 :                 zlog_debug("    Opaque data: ");
    2236             : 
    2237           0 :                 for (i = 0; i < opaquelen; i++) {
    2238           0 :                         zlog_debug("0x%x ", olsa->data[i]);
    2239             :                 }
    2240             :         }
    2241           0 :         return;
    2242             : }
    2243             : 
    2244             : /* -----------------------------------------------------------
    2245             :  * Following are functions to notify clients about events
    2246             :  * -----------------------------------------------------------
    2247             :  */
    2248             : 
    2249             : /* Send a message to all clients. This is useful for messages
    2250             :    that need to be notified to all clients (such as interface
    2251             :    changes) */
    2252             : 
    2253           4 : void ospf_apiserver_clients_notify_all(struct msg *msg)
    2254             : {
    2255           4 :         struct listnode *node, *nnode;
    2256           4 :         struct ospf_apiserver *apiserv;
    2257             : 
    2258             :         /* Send message to all clients */
    2259           8 :         for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv))
    2260           0 :                 ospf_apiserver_send_msg(apiserv, msg);
    2261           4 : }
    2262             : 
    2263             : /* An interface is now ready to accept opaque LSAs. Notify all
    2264             :    clients that registered to use this opaque type */
    2265           0 : void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi)
    2266             : {
    2267           0 :         struct listnode *node, *nnode;
    2268           0 :         struct msg *msg;
    2269           0 :         struct ospf_apiserver *apiserv;
    2270             : 
    2271           0 :         assert(oi);
    2272           0 :         if (!oi->address) {
    2273           0 :                 zlog_warn("Interface has no address?");
    2274           0 :                 return;
    2275             :         }
    2276             : 
    2277           0 :         if (!ospf_apiserver_is_ready_type9(oi)) {
    2278             :                 zlog_warn("Interface not ready for type 9?");
    2279             :                 return;
    2280             :         }
    2281             : 
    2282           0 :         for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
    2283           0 :                 struct listnode *node2, *nnode2;
    2284           0 :                 struct registered_opaque_type *r;
    2285             : 
    2286           0 :                 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
    2287             :                                        r)) {
    2288           0 :                         if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
    2289           0 :                                 msg = new_msg_ready_notify(
    2290           0 :                                         0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
    2291           0 :                                         oi->address->u.prefix4);
    2292           0 :                                 if (!msg) {
    2293           0 :                                         zlog_warn(
    2294             :                                                 "%s: new_msg_ready_notify failed",
    2295             :                                                 __func__);
    2296             : #ifdef NOTYET
    2297             :                                         /* Cannot allocate new message. What
    2298             :                                          * should we do? */
    2299             :                                         ospf_apiserver_free(apiserv);
    2300             : #endif
    2301           0 :                                         goto out;
    2302             :                                 }
    2303             : 
    2304           0 :                                 ospf_apiserver_send_msg(apiserv, msg);
    2305           0 :                                 msg_free(msg);
    2306             :                         }
    2307             :                 }
    2308             :         }
    2309             : 
    2310           0 : out:
    2311             :         return;
    2312             : }
    2313             : 
    2314           0 : void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area)
    2315             : {
    2316           0 :         struct listnode *node, *nnode;
    2317           0 :         struct msg *msg;
    2318           0 :         struct ospf_apiserver *apiserv;
    2319             : 
    2320           0 :         assert(area);
    2321             : 
    2322           0 :         if (!ospf_apiserver_is_ready_type10(area)) {
    2323             :                 zlog_warn("Area not ready for type 10?");
    2324             :                 return;
    2325             :         }
    2326             : 
    2327           0 :         for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
    2328           0 :                 struct listnode *node2, *nnode2;
    2329           0 :                 struct registered_opaque_type *r;
    2330             : 
    2331           0 :                 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
    2332             :                                        r)) {
    2333           0 :                         if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
    2334           0 :                                 msg = new_msg_ready_notify(
    2335           0 :                                         0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
    2336             :                                         area->area_id);
    2337           0 :                                 if (!msg) {
    2338           0 :                                         zlog_warn(
    2339             :                                                 "%s: new_msg_ready_nofity failed",
    2340             :                                                 __func__);
    2341             : #ifdef NOTYET
    2342             :                                         /* Cannot allocate new message. What
    2343             :                                          * should we do? */
    2344             :                                         ospf_apiserver_free(apiserv);
    2345             : #endif
    2346           0 :                                         goto out;
    2347             :                                 }
    2348             : 
    2349           0 :                                 ospf_apiserver_send_msg(apiserv, msg);
    2350           0 :                                 msg_free(msg);
    2351             :                         }
    2352             :                 }
    2353             :         }
    2354             : 
    2355           0 : out:
    2356             :         return;
    2357             : }
    2358             : 
    2359             : 
    2360           0 : void ospf_apiserver_clients_notify_ready_type11(struct ospf *top)
    2361             : {
    2362           0 :         struct listnode *node, *nnode;
    2363           0 :         struct msg *msg;
    2364           0 :         struct in_addr id_null = {.s_addr = 0L};
    2365           0 :         struct ospf_apiserver *apiserv;
    2366             : 
    2367           0 :         assert(top);
    2368             : 
    2369           0 :         if (!ospf_apiserver_is_ready_type11(top)) {
    2370             :                 zlog_warn("AS not ready for type 11?");
    2371             :                 return;
    2372             :         }
    2373             : 
    2374           0 :         for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
    2375           0 :                 struct listnode *node2, *nnode2;
    2376           0 :                 struct registered_opaque_type *r;
    2377             : 
    2378           0 :                 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
    2379             :                                        r)) {
    2380           0 :                         if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
    2381           0 :                                 msg = new_msg_ready_notify(
    2382           0 :                                         0, OSPF_OPAQUE_AS_LSA, r->opaque_type,
    2383             :                                         id_null);
    2384           0 :                                 if (!msg) {
    2385           0 :                                         zlog_warn(
    2386             :                                                 "%s: new_msg_ready_notify failed",
    2387             :                                                 __func__);
    2388             : #ifdef NOTYET
    2389             :                                         /* Cannot allocate new message. What
    2390             :                                          * should we do? */
    2391             :                                         ospf_apiserver_free(apiserv);
    2392             : #endif
    2393           0 :                                         goto out;
    2394             :                                 }
    2395             : 
    2396           0 :                                 ospf_apiserver_send_msg(apiserv, msg);
    2397           0 :                                 msg_free(msg);
    2398             :                         }
    2399             :                 }
    2400             :         }
    2401             : 
    2402           0 : out:
    2403             :         return;
    2404             : }
    2405             : 
    2406           0 : void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi)
    2407             : {
    2408           0 :         struct msg *msg;
    2409             : 
    2410           0 :         msg = new_msg_new_if(0, oi->address->u.prefix4, oi->area->area_id);
    2411           0 :         if (msg != NULL) {
    2412           0 :                 ospf_apiserver_clients_notify_all(msg);
    2413           0 :                 msg_free(msg);
    2414             :         }
    2415           0 : }
    2416             : 
    2417           0 : void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi)
    2418             : {
    2419           0 :         struct msg *msg;
    2420             : 
    2421           0 :         msg = new_msg_del_if(0, oi->address->u.prefix4);
    2422           0 :         if (msg != NULL) {
    2423           0 :                 ospf_apiserver_clients_notify_all(msg);
    2424           0 :                 msg_free(msg);
    2425             :         }
    2426           0 : }
    2427             : 
    2428           0 : void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi)
    2429             : {
    2430           0 :         struct msg *msg;
    2431           0 :         struct in_addr ifaddr = {.s_addr = 0L};
    2432           0 :         struct in_addr area_id = {.s_addr = 0L};
    2433             : 
    2434           0 :         assert(oi);
    2435           0 :         assert(oi->ifp);
    2436             : 
    2437           0 :         if (oi->address) {
    2438           0 :                 ifaddr = oi->address->u.prefix4;
    2439             :         }
    2440           0 :         if (oi->area) {
    2441           0 :                 area_id = oi->area->area_id;
    2442             :         }
    2443             : 
    2444           0 :         msg = new_msg_ism_change(0, ifaddr, area_id, oi->state);
    2445           0 :         if (!msg) {
    2446           0 :                 zlog_warn("%s: msg_new failed", __func__);
    2447           0 :                 return;
    2448             :         }
    2449             : 
    2450           0 :         ospf_apiserver_clients_notify_all(msg);
    2451           0 :         msg_free(msg);
    2452             : }
    2453             : 
    2454           0 : void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr)
    2455             : {
    2456           0 :         struct msg *msg;
    2457           0 :         struct in_addr ifaddr;
    2458           0 :         struct in_addr nbraddr;
    2459             : 
    2460           0 :         assert(nbr);
    2461             : 
    2462           0 :         ifaddr = nbr->oi->address->u.prefix4;
    2463             : 
    2464           0 :         nbraddr = nbr->address.u.prefix4;
    2465             : 
    2466           0 :         msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id,
    2467           0 :                                  nbr->state);
    2468           0 :         if (!msg) {
    2469           0 :                 zlog_warn("%s: msg_new failed", __func__);
    2470           0 :                 return;
    2471             :         }
    2472             : 
    2473           0 :         ospf_apiserver_clients_notify_all(msg);
    2474           0 :         msg_free(msg);
    2475             : }
    2476             : 
    2477           0 : static int apiserver_clients_lsa_change_notify(uint8_t msgtype,
    2478             :                                                struct ospf_lsa *lsa)
    2479             : {
    2480           0 :         struct msg *msg;
    2481           0 :         struct listnode *node, *nnode;
    2482           0 :         struct ospf_apiserver *apiserv;
    2483             : 
    2484             :         /* Default area for AS-External and Opaque11 LSAs */
    2485           0 :         struct in_addr area_id = {.s_addr = 0L};
    2486             : 
    2487             :         /* Default interface for non Opaque9 LSAs */
    2488           0 :         struct in_addr ifaddr = {.s_addr = 0L};
    2489             : 
    2490           0 :         if (lsa->area) {
    2491           0 :                 area_id = lsa->area->area_id;
    2492             :         }
    2493           0 :         if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
    2494           0 :                 assert(lsa->oi);
    2495           0 :                 ifaddr = lsa->oi->address->u.prefix4;
    2496             :         }
    2497             : 
    2498             :         /* Prepare message that can be sent to clients that have a matching
    2499             :            filter */
    2500           0 :         msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
    2501             :                                         ifaddr, area_id,
    2502           0 :                                         lsa->flags & OSPF_LSA_SELF, lsa->data);
    2503           0 :         if (!msg) {
    2504           0 :                 zlog_warn("%s: msg_new failed", __func__);
    2505           0 :                 return -1;
    2506             :         }
    2507             : 
    2508             :         /* Now send message to all clients with a matching filter */
    2509           0 :         for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
    2510           0 :                 struct lsa_filter_type *filter;
    2511           0 :                 uint16_t mask;
    2512           0 :                 uint32_t *area;
    2513           0 :                 int i;
    2514             : 
    2515             :                 /* Check filter for this client. */
    2516           0 :                 filter = apiserv->filter;
    2517             : 
    2518             :                 /* Check area IDs in case of non AS-E LSAs.
    2519             :                  * If filter has areas (num_areas > 0),
    2520             :                  * then one of the areas must match the area ID of this LSA. */
    2521             : 
    2522           0 :                 i = filter->num_areas;
    2523           0 :                 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA)
    2524           0 :                     || (lsa->data->type == OSPF_OPAQUE_AS_LSA)) {
    2525             :                         i = 0;
    2526             :                 }
    2527             : 
    2528           0 :                 if (i > 0) {
    2529           0 :                         area = (uint32_t *)(filter + 1);
    2530           0 :                         while (i) {
    2531           0 :                                 if (*area == area_id.s_addr) {
    2532             :                                         break;
    2533             :                                 }
    2534           0 :                                 i--;
    2535           0 :                                 area++;
    2536             :                         }
    2537             :                 } else {
    2538             :                         i = 1;
    2539             :                 }
    2540             : 
    2541           0 :                 if (i > 0) {
    2542             :                         /* Area match. Check LSA type. */
    2543           0 :                         mask = ntohs(filter->typemask);
    2544             : 
    2545           0 :                         if (mask & Power2[lsa->data->type]) {
    2546             :                                 /* Type also matches. Check origin. */
    2547           0 :                                 if ((filter->origin == ANY_ORIGIN)
    2548           0 :                                     || (filter->origin == IS_LSA_SELF(lsa))) {
    2549           0 :                                         ospf_apiserver_send_msg(apiserv, msg);
    2550             :                                 }
    2551             :                         }
    2552             :                 }
    2553             :         }
    2554             :         /* Free message since it is not used anymore */
    2555           0 :         msg_free(msg);
    2556             : 
    2557           0 :         return 0;
    2558             : }
    2559             : 
    2560             : 
    2561             : /* -------------------------------------------------------------
    2562             :  * Following are hooks invoked when LSAs are updated or deleted
    2563             :  * -------------------------------------------------------------
    2564             :  */
    2565             : 
    2566             : 
    2567           0 : int ospf_apiserver_lsa_update(struct ospf_lsa *lsa)
    2568             : {
    2569             : 
    2570             :         /* Only notify this update if the LSA's age is smaller than
    2571             :            MAXAGE. Otherwise clients would see LSA updates with max age just
    2572             :            before they are deleted from the LSDB. LSA delete messages have
    2573             :            MAXAGE too but should not be filtered. */
    2574           0 :         if (IS_LSA_MAXAGE(lsa))
    2575           0 :                 return 0;
    2576           0 :         return apiserver_clients_lsa_change_notify(MSG_LSA_UPDATE_NOTIFY, lsa);
    2577             : }
    2578             : 
    2579           0 : int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa)
    2580             : {
    2581           0 :         return apiserver_clients_lsa_change_notify(MSG_LSA_DELETE_NOTIFY, lsa);
    2582             : }
    2583             : 
    2584             : /* -------------------------------------------------------------
    2585             :  * Reachable functions
    2586             :  * -------------------------------------------------------------
    2587             :  */
    2588             : 
    2589           0 : static inline int cmp_route_nodes(struct route_node *orn,
    2590             :                                   struct route_node *nrn)
    2591             : {
    2592           0 :         if (!orn)
    2593             :                 return 1;
    2594           0 :         else if (!nrn)
    2595             :                 return -1;
    2596           0 :         else if (orn->p.u.prefix4.s_addr < nrn->p.u.prefix4.s_addr)
    2597             :                 return -1;
    2598           0 :         else if (orn->p.u.prefix4.s_addr > nrn->p.u.prefix4.s_addr)
    2599             :                 return 1;
    2600             :         else
    2601           0 :                 return 0;
    2602             : }
    2603             : 
    2604          49 : void ospf_apiserver_notify_reachable(struct route_table *ort,
    2605             :                                      struct route_table *nrt)
    2606             : {
    2607          49 :         struct msg *msg;
    2608          49 :         struct msg_reachable_change *areach;
    2609          49 :         struct route_node *orn, *nrn;
    2610          49 :         const uint insz = sizeof(struct in_addr);
    2611          49 :         struct in_addr *abuf = NULL, *dbuf = NULL;
    2612          49 :         struct in_addr *a = NULL, *d = NULL;
    2613          49 :         uint nadd, nremove;
    2614          49 :         int cmp;
    2615             : 
    2616          49 :         if (!ort && !nrt) {
    2617          49 :                 if (IS_DEBUG_OSPF_CLIENT_API)
    2618           0 :                         zlog_debug("%s: no routing tables", __func__);
    2619          49 :                 return;
    2620             :         }
    2621           0 :         if (nrt && nrt->count)
    2622           0 :                 a = abuf = XCALLOC(MTYPE_APISERVER, insz * nrt->count);
    2623           0 :         if (ort && ort->count)
    2624           0 :                 d = dbuf = XCALLOC(MTYPE_APISERVER, insz * ort->count);
    2625             : 
    2626             :         /* walk both tables */
    2627           0 :         orn = ort ? route_top(ort) : NULL;
    2628           0 :         nrn = nrt ? route_top(nrt) : NULL;
    2629           0 :         while (orn || nrn) {
    2630           0 :                 if (orn && !listhead((struct list *)orn->info)) {
    2631           0 :                         orn = route_next(orn);
    2632           0 :                         continue;
    2633             :                 }
    2634           0 :                 if (nrn && !listhead((struct list *)nrn->info)) {
    2635           0 :                         nrn = route_next(nrn);
    2636           0 :                         continue;
    2637             :                 }
    2638           0 :                 cmp = cmp_route_nodes(orn, nrn);
    2639           0 :                 if (!cmp) {
    2640             :                         /* if old == new advance old and new */
    2641           0 :                         if (IS_DEBUG_OSPF_CLIENT_API)
    2642           0 :                                 zlog_debug("keeping router id: %pI4",
    2643             :                                            &orn->p.u.prefix4);
    2644           0 :                         orn = route_next(orn);
    2645           0 :                         nrn = route_next(nrn);
    2646           0 :                 } else if (cmp < 0) {
    2647           0 :                         assert(d != NULL); /* Silence SA warning */
    2648             : 
    2649             :                         /* if old < new, delete old, advance old */
    2650           0 :                         *d++ = orn->p.u.prefix4;
    2651           0 :                         if (IS_DEBUG_OSPF_CLIENT_API)
    2652           0 :                                 zlog_debug("removing router id: %pI4",
    2653             :                                            &orn->p.u.prefix4);
    2654           0 :                         orn = route_next(orn);
    2655             :                 } else {
    2656           0 :                         assert(a != NULL); /* Silence SA warning */
    2657             : 
    2658             :                         /* if new < old, add new, advance new */
    2659           0 :                         *a++ = nrn->p.u.prefix4;
    2660           0 :                         if (IS_DEBUG_OSPF_CLIENT_API)
    2661           0 :                                 zlog_debug("adding router id: %pI4",
    2662             :                                            &nrn->p.u.prefix4);
    2663           0 :                         nrn = route_next(nrn);
    2664             :                 }
    2665             :         }
    2666             : 
    2667           0 :         nadd = abuf ? (a - abuf) : 0;
    2668           0 :         nremove = dbuf ? (d - dbuf) : 0;
    2669             :         a = abuf;
    2670             :         d = dbuf;
    2671             : 
    2672           0 :         while (nadd + nremove) {
    2673           0 :                 msg = new_msg_reachable_change(0, nadd, a, nremove, d);
    2674           0 :                 areach = (struct msg_reachable_change *)STREAM_DATA(msg->s);
    2675             : 
    2676           0 :                 a += ntohs(areach->nadd);
    2677           0 :                 nadd = nadd - ntohs(areach->nadd);
    2678             : 
    2679           0 :                 d += ntohs(areach->nremove);
    2680           0 :                 nremove = nremove - ntohs(areach->nremove);
    2681             : 
    2682           0 :                 if (IS_DEBUG_OSPF_CLIENT_API)
    2683           0 :                         zlog_debug("%s: adding %d removing %d", __func__,
    2684             :                                    ntohs(areach->nadd), ntohs(areach->nremove));
    2685           0 :                 ospf_apiserver_clients_notify_all(msg);
    2686           0 :                 msg_free(msg);
    2687             :         }
    2688           0 :         if (abuf)
    2689           0 :                 XFREE(MTYPE_APISERVER, abuf);
    2690           0 :         if (dbuf)
    2691           0 :                 XFREE(MTYPE_APISERVER, dbuf);
    2692             : }
    2693             : 
    2694             : 
    2695           4 : void ospf_apiserver_clients_notify_router_id_change(struct in_addr router_id)
    2696             : {
    2697           4 :         struct msg *msg;
    2698             : 
    2699           4 :         msg = new_msg_router_id_change(0, router_id);
    2700           4 :         if (!msg) {
    2701           0 :                 zlog_warn("%s: new_msg_router_id_change failed", __func__);
    2702           0 :                 return;
    2703             :         }
    2704             : 
    2705           4 :         ospf_apiserver_clients_notify_all(msg);
    2706           4 :         msg_free(msg);
    2707             : }
    2708             : 
    2709             : 
    2710             : #endif /* SUPPORT_OSPF_API */

Generated by: LCOV version v1.16-topotato