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