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