blob: 59bbb013cdbeb5b0ff7768cbbe87e474298a21f0 [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. */
paul68980082003-03-25 05:07:42 +00001493 lsa_header_set (s, options, protolsa->type, protolsa->id,
1494 area->ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001495
1496 /* Set opaque-LSA body fields. */
1497 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1498 ntohs (protolsa->length) - sizeof (struct lsa_header));
1499
1500 /* Determine length of LSA. */
1501 length = stream_get_endp (s);
1502 newlsa->length = htons (length);
1503
1504 /* Create OSPF LSA. */
1505 if ((new = ospf_lsa_new ()) == NULL)
1506 {
1507 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1508 stream_free (s);
1509 return NULL;
1510 }
1511
1512 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1513 {
1514 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1515 ospf_lsa_free (new);
1516 new = NULL;
1517 stream_free (s);
1518 return NULL;
1519 }
1520
1521 new->area = area;
1522 new->oi = oi;
1523
1524 SET_FLAG (new->flags, OSPF_LSA_SELF);
1525 memcpy (new->data, newlsa, length);
1526 stream_free (s);
1527
1528 return new;
1529}
1530
1531
1532int
1533ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1534{
1535 /* Type 9 opaque LSA can be originated if there is at least one
1536 active opaque-capable neighbor attached to the outgoing
1537 interface. */
1538
paula15f45d2003-03-28 01:50:03 +00001539 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001540}
1541
1542int
1543ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1544{
1545 /* Type 10 opaque LSA can be originated if there is at least one
1546 interface belonging to the area that has an active opaque-capable
1547 neighbor. */
1548 listnode node;
1549
1550 for (node = listhead (area->oiflist); node; nextnode (node))
1551 {
1552 struct ospf_interface *oi = getdata (node);
1553
1554 /* Is there an active neighbor attached to this interface? */
1555 if (ospf_apiserver_is_ready_type9 (oi))
1556 {
1557 return 1;
1558 }
1559 }
1560 /* No active neighbor in area */
1561 return 0;
1562}
1563
1564int
1565ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1566{
1567 /* Type 11 opaque LSA can be originated if there is at least one interface
1568 that has an active opaque-capable neighbor. */
1569 listnode node;
1570
1571 for (node = listhead (ospf->oiflist); node; nextnode (node))
1572 {
1573 struct ospf_interface *oi = getdata (node);
1574
1575 /* Is there an active neighbor attached to this interface? */
1576 if (ospf_apiserver_is_ready_type9 (oi))
1577 return 1;
1578 }
1579 /* No active neighbor at all */
1580 return 0;
1581}
1582
1583
1584int
1585ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1586 struct msg *msg)
1587{
1588 struct msg_originate_request *omsg;
1589 struct lsa_header *data;
paula15f45d2003-03-28 01:50:03 +00001590 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001591 struct ospf_lsa *new;
1592 struct ospf_lsa *old;
1593 struct ospf_area *area = NULL;
1594 struct ospf_interface *oi = NULL;
1595 struct ospf_lsdb *lsdb = NULL;
1596 int lsa_type, opaque_type;
1597 int ready = 0;
1598 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001599
1600 ospf = ospf_get ();
1601 assert (ospf);
paul2d33f152003-03-17 01:10:58 +00001602
1603 /* Extract opaque LSA data from message */
1604 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1605 data = &omsg->data;
1606
1607 /* Determine interface for type9 or area for type10 LSAs. */
1608 switch (data->type)
1609 {
1610 case OSPF_OPAQUE_LINK_LSA:
1611 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1612 if (!oi)
1613 {
1614 zlog_warn ("apiserver_originate: unknown interface %s",
1615 inet_ntoa (omsg->ifaddr));
1616 rc = OSPF_API_NOSUCHINTERFACE;
1617 goto out;
1618 }
1619 area = oi->area;
1620 lsdb = area->lsdb;
1621 break;
1622 case OSPF_OPAQUE_AREA_LSA:
paula15f45d2003-03-28 01:50:03 +00001623 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001624 if (!area)
1625 {
1626 zlog_warn ("apiserver_originate: unknown area %s",
1627 inet_ntoa (omsg->area_id));
1628 rc = OSPF_API_NOSUCHAREA;
1629 goto out;
1630 }
1631 lsdb = area->lsdb;
1632 break;
1633 case OSPF_OPAQUE_AS_LSA:
1634 lsdb = ospf_top->lsdb;
1635 break;
1636 default:
1637 /* We can only handle opaque types here */
1638 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1639 data->type);
1640 rc = OSPF_API_ILLEGALLSATYPE;
1641 goto out;
1642 }
1643
1644 /* Check if we registered this opaque type */
1645 lsa_type = data->type;
1646 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1647
1648 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1649 {
1650 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1651 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1652 goto out;
1653 }
1654
1655 /* Make sure that the neighbors are ready before we can originate */
1656 switch (data->type)
1657 {
1658 case OSPF_OPAQUE_LINK_LSA:
1659 ready = ospf_apiserver_is_ready_type9 (oi);
1660 break;
1661 case OSPF_OPAQUE_AREA_LSA:
1662 ready = ospf_apiserver_is_ready_type10 (area);
1663 break;
1664 case OSPF_OPAQUE_AS_LSA:
1665 ready = ospf_apiserver_is_ready_type11 (ospf_top);
1666 break;
1667 default:
1668 break;
1669 }
1670
1671 if (!ready)
1672 {
1673 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1674 rc = OSPF_API_NOTREADY;
1675 goto out;
1676 }
1677
1678 /* Create OSPF's internal opaque LSA representation */
1679 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1680 if (!new)
1681 {
1682 rc = OSPF_API_NOMEMORY; /* XXX */
1683 goto out;
1684 }
1685
1686 /* Determine if LSA is new or an update for an existing one. */
1687 old = ospf_lsdb_lookup (lsdb, new);
1688
1689 if (!old)
1690 {
1691 /* New LSA install in LSDB. */
1692 rc = ospf_apiserver_originate1 (new);
1693 }
1694 else
1695 {
1696 /*
1697 * Keep the new LSA instance in the "waiting place" until the next
1698 * refresh timing. If several LSA update requests for the same LSID
1699 * have issued by peer, the last one takes effect.
1700 */
1701 new->lsdb = &apiserv->reserve;
1702 ospf_lsdb_add (&apiserv->reserve, new);
1703
1704 /* Kick the scheduler function. */
1705 ospf_opaque_lsa_refresh_schedule (old);
1706 }
1707
1708out:
1709
1710 /* Send a reply back to client with return code */
1711 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1712 return rc;
1713}
1714
1715
1716/* -----------------------------------------------------------
1717 * Flood an LSA within its flooding scope.
1718 * -----------------------------------------------------------
1719 */
1720
1721/* XXX We can probably use ospf_flood_through instead of this function
1722 but then we need the neighbor parameter. If we set nbr to
1723 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1724
1725void
1726ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1727{
1728 assert (lsa);
1729
1730 switch (lsa->data->type)
1731 {
1732 case OSPF_OPAQUE_LINK_LSA:
1733 /* Increment counters? XXX */
1734
1735 /* Flood LSA through local network. */
1736 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1737 break;
1738 case OSPF_OPAQUE_AREA_LSA:
1739 /* Update LSA origination count. */
1740 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001741 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001742
1743 /* Flood LSA through area. */
1744 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1745 break;
1746 case OSPF_OPAQUE_AS_LSA:
1747 /* Increment counters? XXX */
1748
1749 /* Flood LSA through AS. */
paula15f45d2003-03-28 01:50:03 +00001750 ospf_flood_through_as (lsa->oi->ospf, NULL /*nbr */ , lsa);
paul2d33f152003-03-17 01:10:58 +00001751 break;
1752 }
1753}
1754
1755int
1756ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1757{
1758 /* Install this LSA into LSDB. */
paula15f45d2003-03-28 01:50:03 +00001759 if (ospf_lsa_install (lsa->oi->ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001760 {
1761 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1762 return -1;
1763 }
1764
1765 /* Flood LSA within scope */
1766
1767#ifdef NOTYET
1768 /*
1769 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1770 * parameter, and thus it does not cause SIGSEGV error.
1771 */
1772 ospf_flood_through (NULL /*nbr */ , lsa);
1773#else /* NOTYET */
1774
1775 ospf_apiserver_flood_opaque_lsa (lsa);
1776#endif /* NOTYET */
1777
1778 return 0;
1779}
1780
1781
1782/* Opaque LSAs of type 9 on a specific interface can now be
1783 originated. Tell clients that registered type 9. */
1784int
1785ospf_apiserver_lsa9_originator (void *arg)
1786{
1787 struct ospf_interface *oi;
1788
1789 oi = (struct ospf_interface *) arg;
1790 if (listcount (apiserver_list) > 0) {
1791 ospf_apiserver_clients_notify_ready_type9 (oi);
1792 }
1793 return 0;
1794}
1795
1796int
1797ospf_apiserver_lsa10_originator (void *arg)
1798{
1799 struct ospf_area *area;
1800
1801 area = (struct ospf_area *) arg;
1802 if (listcount (apiserver_list) > 0) {
1803 ospf_apiserver_clients_notify_ready_type10 (area);
1804 }
1805 return 0;
1806}
1807
1808int
1809ospf_apiserver_lsa11_originator (void *arg)
1810{
1811 struct ospf *ospf;
1812
1813 ospf = (struct ospf *) arg;
1814 if (listcount (apiserver_list) > 0) {
1815 ospf_apiserver_clients_notify_ready_type11 (ospf);
1816 }
1817 return 0;
1818}
1819
1820
1821/* Periodically refresh opaque LSAs so that they do not expire in
1822 other routers. */
1823void
1824ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1825{
1826 struct ospf_apiserver *apiserv;
1827 struct ospf_lsa *new = NULL;
1828
1829 apiserv = lookup_apiserver_by_lsa (lsa);
1830 if (!apiserv)
1831 {
1832 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1833 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1834 }
1835
1836 if (IS_LSA_MAXAGE (lsa))
1837 {
1838 ospf_opaque_lsa_flush_schedule (lsa);
1839 goto out;
1840 }
1841
1842 /* Check if updated version of LSA instance has already prepared. */
1843 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1844 if (!new)
1845 {
1846 /* This is a periodic refresh, driven by core OSPF mechanism. */
1847 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1848 if (!new)
1849 {
1850 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1851 goto out;
1852 }
1853 }
1854 else
1855 {
1856 /* This is a forcible refresh, requested by OSPF-API client. */
1857 ospf_lsdb_delete (&apiserv->reserve, new);
1858 new->lsdb = NULL;
1859 }
1860
1861 /* Increment sequence number */
1862 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1863
1864 /* New LSA is in same area. */
1865 new->area = lsa->area;
1866 SET_FLAG (new->flags, OSPF_LSA_SELF);
1867
1868 /* Install LSA into LSDB. */
paula15f45d2003-03-28 01:50:03 +00001869 if (ospf_lsa_install (new->area->ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001870 {
1871 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1872 ospf_lsa_free (new);
1873 goto out;
1874 }
1875
1876 /* Flood updated LSA through interface, area or AS */
1877
1878#ifdef NOTYET
1879 ospf_flood_through (NULL /*nbr */ , new);
1880#endif /* NOTYET */
1881 ospf_apiserver_flood_opaque_lsa (new);
1882
1883 /* Debug logging. */
1884 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1885 {
1886 zlog_info ("LSA[Type%d:%s]: Refresh Opaque LSA",
1887 new->data->type, inet_ntoa (new->data->id));
1888 ospf_lsa_header_dump (new->data);
1889 }
1890
1891out:
1892 return;
1893}
1894
1895
1896/* -----------------------------------------------------------
1897 * Followings are functions to delete LSAs
1898 * -----------------------------------------------------------
1899 */
1900
1901int
1902ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1903 struct msg *msg)
1904{
1905 struct msg_delete_request *dmsg;
paula15f45d2003-03-28 01:50:03 +00001906 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001907 struct ospf_lsa *old;
1908 struct ospf_area *area = NULL;
1909 struct in_addr id;
1910 int lsa_type, opaque_type;
1911 int rc = 0;
1912
paula15f45d2003-03-28 01:50:03 +00001913 ospf = ospf_get ();
1914 assert(ospf);
1915
paul2d33f152003-03-17 01:10:58 +00001916 /* Extract opaque LSA from message */
1917 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1918
1919 /* Lookup area for link-local and area-local opaque LSAs */
1920 switch (dmsg->lsa_type)
1921 {
1922 case OSPF_OPAQUE_LINK_LSA:
1923 case OSPF_OPAQUE_AREA_LSA:
paula15f45d2003-03-28 01:50:03 +00001924 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001925 if (!area)
1926 {
1927 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1928 inet_ntoa (dmsg->area_id));
1929 rc = OSPF_API_NOSUCHAREA;
1930 goto out;
1931 }
1932 break;
1933 case OSPF_OPAQUE_AS_LSA:
1934 /* AS-external opaque LSAs have no designated area */
1935 area = NULL;
1936 break;
1937 default:
1938 zlog_warn
1939 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1940 dmsg->lsa_type);
1941 rc = OSPF_API_ILLEGALLSATYPE;
1942 goto out;
1943 }
1944
1945 /* Check if we registered this opaque type */
1946 lsa_type = dmsg->lsa_type;
1947 opaque_type = dmsg->opaque_type;
1948
1949 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1950 {
1951 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1952 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1953 goto out;
1954 }
1955
1956 /* opaque_id is in network byte order */
1957 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1958 ntohl (dmsg->opaque_id)));
1959
1960 /*
1961 * Even if the target LSA has once scheduled to flush, it remains in
1962 * the LSDB until it is finally handled by the maxage remover thread.
1963 * Therefore, the lookup function below may return non-NULL result.
1964 */
1965 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf_top->router_id);
1966 if (!old)
1967 {
1968 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1969 dmsg->lsa_type, inet_ntoa (id));
1970 rc = OSPF_API_NOSUCHLSA;
1971 goto out;
1972 }
1973
1974 /* Schedule flushing of LSA from LSDB */
1975 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1976 ospf_opaque_lsa_flush_schedule (old);
1977
1978out:
1979
1980 /* Send reply back to client including return code */
1981 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1982 return rc;
1983}
1984
1985/* Flush self-originated opaque LSA */
1986int
1987apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
1988 void *p_arg, int int_arg)
1989{
1990 struct param_t
1991 {
1992 struct ospf_apiserver *apiserv;
1993 u_char lsa_type;
1994 u_char opaque_type;
1995 }
1996 *param;
1997
1998 /* Sanity check */
1999 assert (lsa->data);
2000 assert (p_arg);
2001 param = (struct param_t *) p_arg;
2002
2003 /* If LSA matches type and opaque type then delete it */
2004 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2005 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2006 {
2007 ospf_opaque_lsa_flush_schedule (lsa);
2008 }
2009 return 0;
2010}
2011
2012/* Delete self-originated opaque LSAs of a given opaque type. This
2013 function is called when an application unregisters a given opaque
2014 type or a connection to an application closes and all those opaque
2015 LSAs need to be flushed the LSDB. */
2016void
2017ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2018 u_char lsa_type, u_char opaque_type)
2019{
2020 struct param_t
2021 {
2022 struct ospf_apiserver *apiserv;
2023 u_char lsa_type;
2024 u_char opaque_type;
2025 }
2026 param;
2027 listnode node;
2028
2029 /* Set parameter struct. */
2030 param.apiserv = apiserv;
2031 param.lsa_type = lsa_type;
2032 param.opaque_type = opaque_type;
2033
2034#ifdef ORIGINAL_CODING
2035 /* Iterate over all areas */
2036 for (node = listhead (ospf_top->areas); node; nextnode (node))
2037 {
2038 struct ospf_area *area = node->data;
2039
2040 foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) &param, 0,
2041 apiserver_flush_opaque_type_callback);
2042 foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) &param, 0,
2043 apiserver_flush_opaque_type_callback);
2044 }
2045
2046 /* For AS-external opaque LSAs */
2047 if (ospf_top->lsdb)
2048 {
2049 foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) &param, 0,
2050 apiserver_flush_opaque_type_callback);
2051 }
2052#else /* ORIGINAL_CODING */
2053 switch (lsa_type)
2054 {
2055 case OSPF_OPAQUE_LINK_LSA:
2056 for (node = listhead (ospf_top->areas); node; nextnode (node))
2057 {
2058 struct ospf_area *area = node->data;
2059 foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) &param, 0,
2060 apiserver_flush_opaque_type_callback);
2061 }
2062 break;
2063 case OSPF_OPAQUE_AREA_LSA:
2064 for (node = listhead (ospf_top->areas); node; nextnode (node))
2065 {
2066 struct ospf_area *area = node->data;
2067 foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) &param, 0,
2068 apiserver_flush_opaque_type_callback);
2069 }
2070 break;
2071 case OSPF_OPAQUE_AS_LSA:
2072 foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) &param, 0,
2073 apiserver_flush_opaque_type_callback);
2074 break;
2075 default:
2076 break;
2077 }
2078 return;
2079#endif /* ORIGINAL_CODING */
2080}
2081
2082
2083/* -----------------------------------------------------------
2084 * Followings are callback functions to handle opaque types
2085 * -----------------------------------------------------------
2086 */
2087
2088int
2089ospf_apiserver_new_if (struct interface *ifp)
2090{
2091 struct ospf_interface *oi;
2092
2093 /* For some strange reason it seems possible that we are invoked
2094 with an interface that has no name. This seems to happen during
2095 initialization. Return if this happens */
2096
2097 if (ifp->name[0] == '\0') {
2098 /* interface has empty name */
2099 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2100 return 0;
2101 }
2102
2103 /* zlog_warn for debugging */
2104 zlog_warn ("ospf_apiserver_new_if");
2105 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2106 ifp->ifindex);
2107
2108 if (ifp->name[0] == '\0') {
2109 /* interface has empty name */
2110 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2111 return 0;
2112 }
2113
2114 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2115
2116 if (!oi) {
2117 /* This interface is known to Zebra but not to OSPF daemon yet. */
2118 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2119 ifp->name);
2120 return 0;
2121 }
2122
2123 assert (oi);
2124
2125 /* New interface added to OSPF, tell clients about it */
2126 if (listcount (apiserver_list) > 0) {
2127 ospf_apiserver_clients_notify_new_if (oi);
2128 }
2129 return 0;
2130}
2131
2132int
2133ospf_apiserver_del_if (struct interface *ifp)
2134{
2135 struct ospf_interface *oi;
2136
2137 /* zlog_warn for debugging */
2138 zlog_warn ("ospf_apiserver_del_if");
2139 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2140 ifp->ifindex);
2141
2142 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002143
2144 if (!oi) {
2145 /* This interface is known to Zebra but not to OSPF daemon
2146 anymore. No need to tell clients about it */
2147 return 0;
2148 }
paul2d33f152003-03-17 01:10:58 +00002149
2150 /* Interface deleted, tell clients about it */
2151 if (listcount (apiserver_list) > 0) {
2152 ospf_apiserver_clients_notify_del_if (oi);
2153 }
2154 return 0;
2155}
2156
2157void
2158ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2159{
2160 /* Tell clients about interface change */
2161
2162 /* zlog_warn for debugging */
2163 zlog_warn ("ospf_apiserver_ism_change");
2164 if (listcount (apiserver_list) > 0) {
2165 ospf_apiserver_clients_notify_ism_change (oi);
2166 }
2167
2168 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2169 zlog_warn ("old_state=%d", old_state);
2170 zlog_warn ("oi->state=%d", oi->state);
2171}
2172
2173void
2174ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2175{
2176 /* Neighbor status changed, tell clients about it */
2177 zlog_warn ("ospf_apiserver_nsm_change");
2178 if (listcount (apiserver_list) > 0) {
2179 ospf_apiserver_clients_notify_nsm_change (nbr);
2180 }
2181}
2182
2183void
2184ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2185{
2186 struct opaque_lsa
2187 {
2188 struct lsa_header header;
2189 u_char data[1]; /* opaque data have variable length. This is start
2190 address */
2191 };
2192 struct opaque_lsa *olsa;
2193 int opaquelen;
2194
2195 olsa = (struct opaque_lsa *) lsa->data;
2196
2197 if (VALID_OPAQUE_INFO_LEN (lsa->data))
2198 {
2199 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2200 }
2201 else
2202 {
2203 opaquelen = 0;
2204 }
2205
2206 /* Output information about opaque LSAs */
2207 if (vty != NULL)
2208 {
2209 int i;
2210 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2211 opaquelen,
2212 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2213 VTY_NEWLINE);
2214 vty_out (vty, " Opaque data: ");
2215
2216 for (i = 0; i < opaquelen; i++)
2217 {
2218 vty_out (vty, "0x%x ", olsa->data[i]);
2219 }
2220 vty_out (vty, "%s", VTY_NEWLINE);
2221 }
2222 else
2223 {
2224 int i;
2225 zlog_info (" Added using OSPF API: %u octets of opaque data %s",
2226 opaquelen,
2227 VALID_OPAQUE_INFO_LEN (lsa->
2228 data) ? "" : "(Invalid length?)");
2229 zlog_info (" Opaque data: ");
2230
2231 for (i = 0; i < opaquelen; i++)
2232 {
2233 zlog_info ("0x%x ", olsa->data[i]);
2234 }
2235 zlog_info ("\n");
2236 }
2237 return;
2238}
2239
2240/* -----------------------------------------------------------
2241 * Followings are functions to notify clients about events
2242 * -----------------------------------------------------------
2243 */
2244
2245/* Send a message to all clients. This is useful for messages
2246 that need to be notified to all clients (such as interface
2247 changes) */
2248
2249void
2250ospf_apiserver_clients_notify_all (struct msg *msg)
2251{
2252 listnode node;
2253
2254 /* Send message to all clients */
2255 for (node = listhead (apiserver_list); node; nextnode (node))
2256 {
2257 struct ospf_apiserver *apiserv =
2258 (struct ospf_apiserver *) getdata (node);
2259
2260 ospf_apiserver_send_msg (apiserv, msg);
2261 }
2262}
2263
2264/* An interface is now ready to accept opaque LSAs. Notify all
2265 clients that registered to use this opaque type */
2266void
2267ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2268{
2269 listnode node;
2270 struct msg *msg;
2271
2272 assert (oi);
2273 if (!oi->address)
2274 {
2275 zlog_warn ("Interface has no address?");
2276 return;
2277 }
2278
2279 if (!ospf_apiserver_is_ready_type9 (oi))
2280 {
2281 zlog_warn ("Interface not ready for type 9?");
2282 return;
2283 }
2284
2285 for (node = listhead (apiserver_list); node; nextnode (node))
2286 {
2287 struct ospf_apiserver *apiserv =
2288 (struct ospf_apiserver *) getdata (node);
2289 listnode n2;
2290
2291 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2292 {
2293 struct registered_opaque_type *r =
2294 (struct registered_opaque_type *) getdata (n2);
2295 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2296 {
2297 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2298 r->opaque_type,
2299 oi->address->u.prefix4);
2300 if (!msg)
2301 {
2302 zlog_warn
2303 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2304#ifdef NOTYET
2305 /* Cannot allocate new message. What should we do? */
2306 ospf_apiserver_free (apiserv);
2307#endif
2308 goto out;
2309 }
2310
2311 ospf_apiserver_send_msg (apiserv, msg);
2312 msg_free (msg);
2313 }
2314 }
2315 }
2316
2317out:
2318 return;
2319}
2320
2321void
2322ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2323{
2324 listnode node;
2325 struct msg *msg;
2326
2327 assert (area);
2328
2329 if (!ospf_apiserver_is_ready_type10 (area))
2330 {
2331 zlog_warn ("Area not ready for type 10?");
2332 return;
2333 }
2334
2335 for (node = listhead (apiserver_list); node; nextnode (node))
2336 {
2337 struct ospf_apiserver *apiserv =
2338 (struct ospf_apiserver *) getdata (node);
2339 listnode n2;
2340
2341 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2342 {
2343 struct registered_opaque_type *r =
2344 (struct registered_opaque_type *) getdata (n2);
2345 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2346 {
2347 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2348 r->opaque_type, area->area_id);
2349 if (!msg)
2350 {
2351 zlog_warn
2352 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2353#ifdef NOTYET
2354 /* Cannot allocate new message. What should we do? */
2355 ospf_apiserver_free (apiserv);
2356#endif
2357 goto out;
2358 }
2359
2360 ospf_apiserver_send_msg (apiserv, msg);
2361 msg_free (msg);
2362 }
2363 }
2364 }
2365
2366out:
2367 return;
2368}
2369
2370
2371void
2372ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2373{
2374 listnode node;
2375 struct msg *msg;
2376 struct in_addr id_null = { 0L };
2377
2378 assert (top);
2379
2380 if (!ospf_apiserver_is_ready_type11 (top))
2381 {
2382 zlog_warn ("AS not ready for type 11?");
2383 return;
2384 }
2385
2386 for (node = listhead (apiserver_list); node; nextnode (node))
2387 {
2388 struct ospf_apiserver *apiserv =
2389 (struct ospf_apiserver *) getdata (node);
2390 listnode n2;
2391
2392 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2393 {
2394 struct registered_opaque_type *r =
2395 (struct registered_opaque_type *) getdata (n2);
2396 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2397 {
2398 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2399 r->opaque_type, id_null);
2400 if (!msg)
2401 {
2402 zlog_warn
2403 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2404#ifdef NOTYET
2405 /* Cannot allocate new message. What should we do? */
2406 ospf_apiserver_free (apiserv);
2407#endif
2408 goto out;
2409 }
2410
2411 ospf_apiserver_send_msg (apiserv, msg);
2412 msg_free (msg);
2413 }
2414 }
2415 }
2416
2417out:
2418 return;
2419}
2420
2421void
2422ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2423{
2424 struct msg *msg;
2425
2426 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2427 if (msg != NULL)
2428 {
2429 ospf_apiserver_clients_notify_all (msg);
2430 msg_free (msg);
2431 }
2432}
2433
2434void
2435ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2436{
2437 struct msg *msg;
2438
2439 msg = new_msg_del_if (0, oi->address->u.prefix4);
2440 if (msg != NULL)
2441 {
2442 ospf_apiserver_clients_notify_all (msg);
2443 msg_free (msg);
2444 }
2445}
2446
2447void
2448ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2449{
2450 struct msg *msg;
2451 struct in_addr ifaddr = { 0L };
2452 struct in_addr area_id = { 0L };
2453
2454 assert (oi);
2455 assert (oi->ifp);
2456
2457 if (oi->address)
2458 {
2459 ifaddr = oi->address->u.prefix4;
2460 }
2461 if (oi->area)
2462 {
2463 area_id = oi->area->area_id;
2464 }
2465
2466 msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status);
2467 if (!msg)
2468 {
2469 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2470 return;
2471 }
2472
2473 ospf_apiserver_clients_notify_all (msg);
2474 msg_free (msg);
2475}
2476
2477void
2478ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2479{
2480 struct msg *msg;
2481 struct in_addr ifaddr = { 0L };
2482 struct in_addr nbraddr = { 0L };
2483
2484 assert (nbr);
2485
2486 if (nbr->oi)
2487 {
2488 ifaddr = nbr->oi->address->u.prefix4;
2489 }
2490
2491 nbraddr = nbr->address.u.prefix4;
2492
2493 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2494 if (!msg)
2495 {
2496 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2497 return;
2498 }
2499
2500 ospf_apiserver_clients_notify_all (msg);
2501 msg_free (msg);
2502}
2503
2504void
2505apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2506{
2507 struct msg *msg;
2508 listnode node;
2509
2510 /* Default area for AS-External and Opaque11 LSAs */
2511 struct in_addr area_id = { 0L };
2512
2513 /* Default interface for non Opaque9 LSAs */
2514 struct in_addr ifaddr = { 0L };
2515
2516 if (lsa->area)
2517 {
2518 area_id = lsa->area->area_id;
2519 }
2520 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2521 {
2522 assert (lsa->oi);
2523 ifaddr = lsa->oi->address->u.prefix4;
2524 }
2525
2526 /* Prepare message that can be sent to clients that have a matching
2527 filter */
2528 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2529 ifaddr, area_id,
2530 lsa->flags & OSPF_LSA_SELF, lsa->data);
2531 if (!msg)
2532 {
2533 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2534 return;
2535 }
2536
2537 /* Now send message to all clients with a matching filter */
2538 for (node = listhead (apiserver_list); node; nextnode (node))
2539 {
2540 struct ospf_apiserver *apiserv = (struct ospf_apiserver *) node->data;
2541 struct lsa_filter_type *filter;
2542 u_int16_t mask;
2543 u_int32_t *area;
2544 int i;
2545
2546 /* Check filter for this client. */
2547 filter = apiserv->filter;
2548
2549 /* Check area IDs in case of non AS-E LSAs.
2550 * If filter has areas (num_areas > 0),
2551 * then one of the areas must match the area ID of this LSA. */
2552
2553 i = filter->num_areas;
2554 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2555 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2556 {
2557 i = 0;
2558 }
2559
2560 if (i > 0)
2561 {
2562 area = (u_int32_t *) (filter + 1);
2563 while (i)
2564 {
2565 if (*area == area_id.s_addr)
2566 {
2567 break;
2568 }
2569 i--;
2570 area++;
2571 }
2572 }
2573 else
2574 {
2575 i = 1;
2576 }
2577
2578 if (i > 0)
2579 {
2580 /* Area match. Check LSA type. */
2581 mask = ntohs (filter->typemask);
2582
2583 if (mask & Power2[lsa->data->type])
2584 {
2585 /* Type also matches. Check origin. */
2586 if ((filter->origin == ANY_ORIGIN) ||
2587 (filter->origin == IS_LSA_SELF (lsa)))
2588 {
2589 ospf_apiserver_send_msg (apiserv, msg);
2590 }
2591 }
2592 }
2593 }
2594 /* Free message since it is not used anymore */
2595 msg_free (msg);
2596}
2597
2598
2599/* -------------------------------------------------------------
2600 * Followings are hooks invoked when LSAs are updated or deleted
2601 * -------------------------------------------------------------
2602 */
2603
2604
2605int
2606apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2607{
2608 struct msg *msg;
2609 /* default area for AS-External and Opaque11 LSAs */
2610 struct in_addr area_id = { 0L };
2611
2612 /* default interface for non Opaque9 LSAs */
2613 struct in_addr ifaddr = { 0L };
2614
2615 /* Only notify this update if the LSA's age is smaller than
2616 MAXAGE. Otherwise clients would see LSA updates with max age just
2617 before they are deleted from the LSDB. LSA delete messages have
2618 MAXAGE too but should not be filtered. */
2619 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2620 return 0;
2621 }
2622
2623 if (lsa->area)
2624 {
2625 area_id = lsa->area->area_id;
2626 }
2627 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2628 {
2629 ifaddr = lsa->oi->address->u.prefix4;
2630 }
2631 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2632 ifaddr, area_id,
2633 lsa->flags & OSPF_LSA_SELF, lsa->data);
2634 if (!msg)
2635 {
2636 zlog_warn ("notify_clients_lsa: msg_new failed");
2637 return -1;
2638 }
2639 /* Notify all clients that new LSA is added/updated */
2640 apiserver_clients_lsa_change_notify (msgtype, lsa);
2641
2642 /* Clients made their own copies of msg so we can free msg here */
2643 msg_free (msg);
2644
2645 return 0;
2646}
2647
2648int
2649ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2650{
2651 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2652}
2653
2654int
2655ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2656{
2657 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2658}
2659
2660#endif /* SUPPORT_OSPF_API */
2661