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