blob: 545060c9cc2e1817f3f91c908790047d1f6eb4ba [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;
paul99b7c5d2003-04-06 01:19:28 +000088 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +000089
paulafbacce2003-07-09 16:09:20 +000090 if (!(ospf = ospf_lookup ()))
paul5549c6b2003-07-09 15:46:33 +000091 return NULL;
paul99b7c5d2003-04-06 01:19:28 +000092
93 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +000094 {
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;
paul99b7c5d2003-04-06 01:19:28 +0000110 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000111
paulafbacce2003-07-09 16:09:20 +0000112 if (!(ospf = ospf_lookup ()));
paul5549c6b2003-07-09 15:46:33 +0000113 return NULL;
paul99b7c5d2003-04-06 01:19:28 +0000114
115 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +0000116 {
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;
paul99b7c5d2003-04-06 01:19:28 +00001072 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001073
paul99b7c5d2003-04-06 01:19:28 +00001074 ospf = ospf_lookup ();
1075
1076 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00001077 {
1078 struct ospf_interface *oi = (struct ospf_interface *) getdata (node);
1079
1080 /* Check if this interface is indeed ready for type 9 */
1081 if (!ospf_apiserver_is_ready_type9 (oi))
1082 continue;
1083
1084 /* Check for registered opaque type 9 types */
1085 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1086 {
1087 struct registered_opaque_type *r =
1088 (struct registered_opaque_type *) getdata (n2);
1089 struct msg *msg;
1090
1091 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1092 {
1093
1094 /* Yes, this opaque type is ready */
1095 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1096 r->opaque_type,
1097 oi->address->u.prefix4);
1098 if (!msg)
1099 {
1100 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1101#ifdef NOTYET
1102 /* Cannot allocate new message. What should we do? */
1103 ospf_apiserver_free (apiserv);
1104#endif
1105 goto out;
1106 }
1107 ospf_apiserver_send_msg (apiserv, msg);
1108 msg_free (msg);
1109 }
1110 }
1111 }
1112
1113out:
1114 return;
1115}
1116
1117
1118/* Notify specific client about all opaque types 10 that are ready. */
1119void
1120ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1121{
1122 listnode node;
1123 listnode n2;
paul99b7c5d2003-04-06 01:19:28 +00001124 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001125
paul99b7c5d2003-04-06 01:19:28 +00001126 ospf = ospf_lookup ();
1127
1128 for (node = listhead (ospf->areas); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00001129 {
1130 struct ospf_area *area = getdata (node);
1131
1132 if (!ospf_apiserver_is_ready_type10 (area))
1133 {
1134 continue;
1135 }
1136
1137 /* Check for registered opaque type 10 types */
1138 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1139 {
1140 struct registered_opaque_type *r =
1141 (struct registered_opaque_type *) getdata (n2);
1142 struct msg *msg;
1143
1144 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1145 {
1146 /* Yes, this opaque type is ready */
1147 msg =
1148 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1149 r->opaque_type, area->area_id);
1150 if (!msg)
1151 {
1152 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1153#ifdef NOTYET
1154 /* Cannot allocate new message. What should we do? */
1155 ospf_apiserver_free (apiserv);
1156#endif
1157 goto out;
1158 }
1159 ospf_apiserver_send_msg (apiserv, msg);
1160 msg_free (msg);
1161 }
1162 }
1163 }
1164
1165out:
1166 return;
1167}
1168
1169/* Notify specific client about all opaque types 11 that are ready */
1170void
1171ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1172{
1173 listnode n2;
paul99b7c5d2003-04-06 01:19:28 +00001174 struct ospf *ospf;
1175
1176 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001177
1178 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001179 if (!ospf_apiserver_is_ready_type11 (ospf))
paul2d33f152003-03-17 01:10:58 +00001180 goto out;;
1181
1182 /* Check for registered opaque type 11 types */
1183 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1184 {
1185 struct registered_opaque_type *r =
1186 (struct registered_opaque_type *) getdata (n2);
1187 struct msg *msg;
1188 struct in_addr noarea_id = { 0L };
1189
1190 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1191 {
1192 /* Yes, this opaque type is ready */
1193 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1194 r->opaque_type, noarea_id);
1195
1196 if (!msg)
1197 {
1198 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1199#ifdef NOTYET
1200 /* Cannot allocate new message. What should we do? */
1201 ospf_apiserver_free (apiserv);
1202#endif
1203 goto out;
1204 }
1205 ospf_apiserver_send_msg (apiserv, msg);
1206 msg_free (msg);
1207 }
1208 }
1209
1210out:
1211 return;
1212}
1213
1214int
1215ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1216 struct msg *msg)
1217{
1218 struct msg_unregister_opaque_type *umsg;
1219 u_char ltype;
1220 u_char otype;
1221 int rc = 0;
1222
1223 /* Extract parameters from unregister opaque type message */
1224 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1225
1226 ltype = umsg->lsatype;
1227 otype = umsg->opaquetype;
1228
1229 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1230
1231 /* Send a reply back to client including return code */
1232 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1233
1234 return rc;
1235}
1236
1237
1238/* -----------------------------------------------------------
1239 * Following are functions for event (filter) registration.
1240 * -----------------------------------------------------------
1241 */
1242int
1243ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1244 struct msg *msg)
1245{
1246 struct msg_register_event *rmsg;
1247 int rc;
1248 u_int32_t seqnum;
1249
1250 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1251
1252 /* Get request sequence number */
1253 seqnum = msg_get_seq (msg);
1254
1255 /* Free existing filter in apiserv. */
1256 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1257 /* Alloc new space for filter. */
1258
1259 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1260 ntohs (msg->hdr.msglen));
1261 if (apiserv->filter)
1262 {
1263 /* copy it over. */
1264 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1265 rc = OSPF_API_OK;
1266 }
1267 else
1268 {
1269 rc = OSPF_API_NOMEMORY;
1270 }
1271 /* Send a reply back to client with return code */
1272 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1273 return rc;
1274}
1275
1276
1277/* -----------------------------------------------------------
1278 * Followings are functions for LSDB synchronization.
1279 * -----------------------------------------------------------
1280 */
1281
1282int
1283apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1284{
1285 struct ospf_apiserver *apiserv;
1286 int seqnum;
1287 struct msg *msg;
1288 struct param_t
1289 {
1290 struct ospf_apiserver *apiserv;
1291 struct lsa_filter_type *filter;
1292 }
1293 *param;
1294 int rc = -1;
1295
1296 /* Sanity check */
1297 assert (lsa->data);
1298 assert (p_arg);
1299
1300 param = (struct param_t *) p_arg;
1301 apiserv = param->apiserv;
1302 seqnum = (u_int32_t) int_arg;
1303
1304 /* Check origin in filter. */
1305 if ((param->filter->origin == ANY_ORIGIN) ||
1306 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1307 {
1308
1309 /* Default area for AS-External and Opaque11 LSAs */
1310 struct in_addr area_id = { 0L };
1311
1312 /* Default interface for non Opaque9 LSAs */
1313 struct in_addr ifaddr = { 0L };
1314
1315 if (lsa->area)
1316 {
1317 area_id = lsa->area->area_id;
1318 }
1319 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1320 {
1321 ifaddr = lsa->oi->address->u.prefix4;
1322 }
1323
1324 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1325 seqnum,
1326 ifaddr, area_id,
1327 lsa->flags & OSPF_LSA_SELF, lsa->data);
1328 if (!msg)
1329 {
1330 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1331#ifdef NOTYET
1332 /* Cannot allocate new message. What should we do? */
1333/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1334#endif
1335 goto out;
1336 }
1337
1338 /* Send LSA */
1339 ospf_apiserver_send_msg (apiserv, msg);
1340 msg_free (msg);
1341 }
1342 rc = 0;
1343
1344out:
1345 return rc;
1346}
1347
1348int
1349ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1350 struct msg *msg)
1351{
1352 listnode node;
1353 u_int32_t seqnum;
1354 int rc = 0;
1355 struct msg_sync_lsdb *smsg;
1356 struct param_t
1357 {
1358 struct ospf_apiserver *apiserv;
1359 struct lsa_filter_type *filter;
1360 }
1361 param;
1362 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001363 struct route_node *rn;
1364 struct ospf_lsa *lsa;
1365 struct ospf *ospf;
1366
1367 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001368
1369 /* Get request sequence number */
1370 seqnum = msg_get_seq (msg);
1371 /* Set sync msg. */
1372 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1373
1374 /* Set parameter struct. */
1375 param.apiserv = apiserv;
1376 param.filter = &smsg->filter;
1377
1378 /* Remember mask. */
1379 mask = ntohs (smsg->filter.typemask);
1380
1381 /* Iterate over all areas. */
paul99b7c5d2003-04-06 01:19:28 +00001382 for (node = listhead (ospf->areas); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00001383 {
1384 struct ospf_area *area = node->data;
1385 int i;
1386 u_int32_t *area_id = NULL;
1387 /* Compare area_id with area_ids in sync request. */
1388 if ((i = smsg->filter.num_areas) > 0)
1389 {
1390 /* Let area_id point to the list of area IDs,
1391 * which is at the end of smsg->filter. */
1392 area_id = (u_int32_t *) (&smsg->filter + 1);
1393 while (i)
1394 {
1395 if (*area_id == area->area_id.s_addr)
1396 {
1397 break;
1398 }
1399 i--;
1400 area_id++;
1401 }
1402 }
1403 else
1404 {
1405 i = 1;
1406 }
1407
1408 /* If area was found, then i>0 here. */
1409 if (i)
1410 {
1411 /* Check msg type. */
1412 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001413 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1414 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001415 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001416 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1417 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001418 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001419 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1420 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001421 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001422 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1423 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001424 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001425 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1426 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001427 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001428 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1429 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001430 }
1431 }
1432
1433 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001434 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001435 {
1436 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001437 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1438 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001439 }
1440
1441 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001442 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001443 {
1444 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001445 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1446 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001447 }
1448
1449 /* Send a reply back to client with return code */
1450 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1451 return rc;
1452}
1453
1454
1455/* -----------------------------------------------------------
1456 * Followings are functions to originate or update LSA
1457 * from an application.
1458 * -----------------------------------------------------------
1459 */
1460
1461/* Create a new internal opaque LSA by taking prototype and filling in
1462 missing fields such as age, sequence number, advertising router,
1463 checksum and so on. The interface parameter is used for type 9
1464 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1465 nor interface. */
1466
1467struct ospf_lsa *
1468ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1469 struct ospf_interface *oi,
1470 struct lsa_header *protolsa)
1471{
1472 struct stream *s;
1473 struct lsa_header *newlsa;
1474 struct ospf_lsa *new = NULL;
1475 u_char options = 0x0;
1476 u_int16_t length;
1477
paul99b7c5d2003-04-06 01:19:28 +00001478 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001479
paul99b7c5d2003-04-06 01:19:28 +00001480 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001481 assert(ospf);
1482
paul2d33f152003-03-17 01:10:58 +00001483 /* Create a stream for internal opaque LSA */
1484 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1485 {
1486 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1487 return NULL;
1488 }
1489
1490 newlsa = (struct lsa_header *) STREAM_DATA (s);
1491
1492 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1493 have to set options? */
1494
1495 if (area)
1496 {
1497 options = LSA_OPTIONS_GET (area);
1498#ifdef HAVE_NSSA
paul5549c6b2003-07-09 15:46:33 +00001499 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001500#endif /* HAVE_NSSA */
1501 }
1502
1503 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1504
1505 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1506 {
1507 zlog_info ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1508 protolsa->type, inet_ntoa (protolsa->id));
1509 }
1510
1511 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001512 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001513 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001514
1515 /* Set opaque-LSA body fields. */
1516 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1517 ntohs (protolsa->length) - sizeof (struct lsa_header));
1518
1519 /* Determine length of LSA. */
1520 length = stream_get_endp (s);
1521 newlsa->length = htons (length);
1522
1523 /* Create OSPF LSA. */
1524 if ((new = ospf_lsa_new ()) == NULL)
1525 {
1526 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1527 stream_free (s);
1528 return NULL;
1529 }
1530
1531 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1532 {
1533 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1534 ospf_lsa_free (new);
1535 new = NULL;
1536 stream_free (s);
1537 return NULL;
1538 }
1539
1540 new->area = area;
1541 new->oi = oi;
1542
1543 SET_FLAG (new->flags, OSPF_LSA_SELF);
1544 memcpy (new->data, newlsa, length);
1545 stream_free (s);
1546
1547 return new;
1548}
1549
1550
1551int
1552ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1553{
1554 /* Type 9 opaque LSA can be originated if there is at least one
1555 active opaque-capable neighbor attached to the outgoing
1556 interface. */
1557
paula15f45d2003-03-28 01:50:03 +00001558 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001559}
1560
1561int
1562ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1563{
1564 /* Type 10 opaque LSA can be originated if there is at least one
1565 interface belonging to the area that has an active opaque-capable
1566 neighbor. */
1567 listnode node;
1568
1569 for (node = listhead (area->oiflist); node; nextnode (node))
1570 {
1571 struct ospf_interface *oi = getdata (node);
1572
1573 /* Is there an active neighbor attached to this interface? */
1574 if (ospf_apiserver_is_ready_type9 (oi))
1575 {
1576 return 1;
1577 }
1578 }
1579 /* No active neighbor in area */
1580 return 0;
1581}
1582
1583int
1584ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1585{
1586 /* Type 11 opaque LSA can be originated if there is at least one interface
1587 that has an active opaque-capable neighbor. */
1588 listnode node;
1589
1590 for (node = listhead (ospf->oiflist); node; nextnode (node))
1591 {
1592 struct ospf_interface *oi = getdata (node);
1593
1594 /* Is there an active neighbor attached to this interface? */
1595 if (ospf_apiserver_is_ready_type9 (oi))
1596 return 1;
1597 }
1598 /* No active neighbor at all */
1599 return 0;
1600}
1601
1602
1603int
1604ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1605 struct msg *msg)
1606{
1607 struct msg_originate_request *omsg;
1608 struct lsa_header *data;
1609 struct ospf_lsa *new;
1610 struct ospf_lsa *old;
1611 struct ospf_area *area = NULL;
1612 struct ospf_interface *oi = NULL;
1613 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001614 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001615 int lsa_type, opaque_type;
1616 int ready = 0;
1617 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001618
paul99b7c5d2003-04-06 01:19:28 +00001619 ospf = ospf_lookup();
1620
paul2d33f152003-03-17 01:10:58 +00001621 /* Extract opaque LSA data from message */
1622 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1623 data = &omsg->data;
1624
1625 /* Determine interface for type9 or area for type10 LSAs. */
1626 switch (data->type)
1627 {
1628 case OSPF_OPAQUE_LINK_LSA:
1629 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1630 if (!oi)
1631 {
1632 zlog_warn ("apiserver_originate: unknown interface %s",
1633 inet_ntoa (omsg->ifaddr));
1634 rc = OSPF_API_NOSUCHINTERFACE;
1635 goto out;
1636 }
1637 area = oi->area;
1638 lsdb = area->lsdb;
1639 break;
1640 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001641 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001642 if (!area)
1643 {
1644 zlog_warn ("apiserver_originate: unknown area %s",
1645 inet_ntoa (omsg->area_id));
1646 rc = OSPF_API_NOSUCHAREA;
1647 goto out;
1648 }
1649 lsdb = area->lsdb;
1650 break;
1651 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001652 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001653 break;
1654 default:
1655 /* We can only handle opaque types here */
1656 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1657 data->type);
1658 rc = OSPF_API_ILLEGALLSATYPE;
1659 goto out;
1660 }
1661
1662 /* Check if we registered this opaque type */
1663 lsa_type = data->type;
1664 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1665
1666 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1667 {
1668 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1669 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1670 goto out;
1671 }
1672
1673 /* Make sure that the neighbors are ready before we can originate */
1674 switch (data->type)
1675 {
1676 case OSPF_OPAQUE_LINK_LSA:
1677 ready = ospf_apiserver_is_ready_type9 (oi);
1678 break;
1679 case OSPF_OPAQUE_AREA_LSA:
1680 ready = ospf_apiserver_is_ready_type10 (area);
1681 break;
1682 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001683 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001684 break;
1685 default:
1686 break;
1687 }
1688
1689 if (!ready)
1690 {
1691 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1692 rc = OSPF_API_NOTREADY;
1693 goto out;
1694 }
1695
1696 /* Create OSPF's internal opaque LSA representation */
1697 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1698 if (!new)
1699 {
1700 rc = OSPF_API_NOMEMORY; /* XXX */
1701 goto out;
1702 }
1703
1704 /* Determine if LSA is new or an update for an existing one. */
1705 old = ospf_lsdb_lookup (lsdb, new);
1706
1707 if (!old)
1708 {
1709 /* New LSA install in LSDB. */
1710 rc = ospf_apiserver_originate1 (new);
1711 }
1712 else
1713 {
1714 /*
1715 * Keep the new LSA instance in the "waiting place" until the next
1716 * refresh timing. If several LSA update requests for the same LSID
1717 * have issued by peer, the last one takes effect.
1718 */
1719 new->lsdb = &apiserv->reserve;
1720 ospf_lsdb_add (&apiserv->reserve, new);
1721
1722 /* Kick the scheduler function. */
1723 ospf_opaque_lsa_refresh_schedule (old);
1724 }
1725
1726out:
1727
1728 /* Send a reply back to client with return code */
1729 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1730 return rc;
1731}
1732
1733
1734/* -----------------------------------------------------------
1735 * Flood an LSA within its flooding scope.
1736 * -----------------------------------------------------------
1737 */
1738
1739/* XXX We can probably use ospf_flood_through instead of this function
1740 but then we need the neighbor parameter. If we set nbr to
1741 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1742
1743void
1744ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1745{
1746 assert (lsa);
1747
1748 switch (lsa->data->type)
1749 {
1750 case OSPF_OPAQUE_LINK_LSA:
1751 /* Increment counters? XXX */
1752
1753 /* Flood LSA through local network. */
1754 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1755 break;
1756 case OSPF_OPAQUE_AREA_LSA:
1757 /* Update LSA origination count. */
1758 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001759 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001760
1761 /* Flood LSA through area. */
1762 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1763 break;
1764 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001765 {
paul99b7c5d2003-04-06 01:19:28 +00001766 struct ospf *ospf;
1767
1768 ospf = ospf_lookup();
1769 assert(ospf);
1770
paul7d5e2682003-04-05 19:41:07 +00001771 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001772
paul7d5e2682003-04-05 19:41:07 +00001773 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001774 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001775 break;
1776 }
paul2d33f152003-03-17 01:10:58 +00001777 }
1778}
1779
1780int
1781ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1782{
paul99b7c5d2003-04-06 01:19:28 +00001783 struct ospf *ospf;
1784
1785 ospf = ospf_lookup();
1786 assert(ospf);
1787
paul2d33f152003-03-17 01:10:58 +00001788 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001789 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001790 {
1791 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1792 return -1;
1793 }
1794
1795 /* Flood LSA within scope */
1796
1797#ifdef NOTYET
1798 /*
1799 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1800 * parameter, and thus it does not cause SIGSEGV error.
1801 */
1802 ospf_flood_through (NULL /*nbr */ , lsa);
1803#else /* NOTYET */
1804
1805 ospf_apiserver_flood_opaque_lsa (lsa);
1806#endif /* NOTYET */
1807
1808 return 0;
1809}
1810
1811
1812/* Opaque LSAs of type 9 on a specific interface can now be
1813 originated. Tell clients that registered type 9. */
1814int
1815ospf_apiserver_lsa9_originator (void *arg)
1816{
1817 struct ospf_interface *oi;
1818
1819 oi = (struct ospf_interface *) arg;
1820 if (listcount (apiserver_list) > 0) {
1821 ospf_apiserver_clients_notify_ready_type9 (oi);
1822 }
1823 return 0;
1824}
1825
1826int
1827ospf_apiserver_lsa10_originator (void *arg)
1828{
1829 struct ospf_area *area;
1830
1831 area = (struct ospf_area *) arg;
1832 if (listcount (apiserver_list) > 0) {
1833 ospf_apiserver_clients_notify_ready_type10 (area);
1834 }
1835 return 0;
1836}
1837
1838int
1839ospf_apiserver_lsa11_originator (void *arg)
1840{
1841 struct ospf *ospf;
1842
1843 ospf = (struct ospf *) arg;
1844 if (listcount (apiserver_list) > 0) {
1845 ospf_apiserver_clients_notify_ready_type11 (ospf);
1846 }
1847 return 0;
1848}
1849
1850
1851/* Periodically refresh opaque LSAs so that they do not expire in
1852 other routers. */
1853void
1854ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1855{
1856 struct ospf_apiserver *apiserv;
1857 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001858 struct ospf * ospf;
1859
1860 ospf = ospf_lookup();
1861 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001862
1863 apiserv = lookup_apiserver_by_lsa (lsa);
1864 if (!apiserv)
1865 {
1866 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1867 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1868 }
1869
1870 if (IS_LSA_MAXAGE (lsa))
1871 {
1872 ospf_opaque_lsa_flush_schedule (lsa);
1873 goto out;
1874 }
1875
1876 /* Check if updated version of LSA instance has already prepared. */
1877 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1878 if (!new)
1879 {
1880 /* This is a periodic refresh, driven by core OSPF mechanism. */
1881 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1882 if (!new)
1883 {
1884 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1885 goto out;
1886 }
1887 }
1888 else
1889 {
1890 /* This is a forcible refresh, requested by OSPF-API client. */
1891 ospf_lsdb_delete (&apiserv->reserve, new);
1892 new->lsdb = NULL;
1893 }
1894
1895 /* Increment sequence number */
1896 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1897
1898 /* New LSA is in same area. */
1899 new->area = lsa->area;
1900 SET_FLAG (new->flags, OSPF_LSA_SELF);
1901
1902 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001903 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001904 {
1905 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1906 ospf_lsa_free (new);
1907 goto out;
1908 }
1909
1910 /* Flood updated LSA through interface, area or AS */
1911
1912#ifdef NOTYET
1913 ospf_flood_through (NULL /*nbr */ , new);
1914#endif /* NOTYET */
1915 ospf_apiserver_flood_opaque_lsa (new);
1916
1917 /* Debug logging. */
1918 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1919 {
1920 zlog_info ("LSA[Type%d:%s]: Refresh Opaque LSA",
1921 new->data->type, inet_ntoa (new->data->id));
1922 ospf_lsa_header_dump (new->data);
1923 }
1924
1925out:
1926 return;
1927}
1928
1929
1930/* -----------------------------------------------------------
1931 * Followings are functions to delete LSAs
1932 * -----------------------------------------------------------
1933 */
1934
1935int
1936ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1937 struct msg *msg)
1938{
1939 struct msg_delete_request *dmsg;
1940 struct ospf_lsa *old;
1941 struct ospf_area *area = NULL;
1942 struct in_addr id;
1943 int lsa_type, opaque_type;
1944 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001945 struct ospf * ospf;
1946
1947 ospf = ospf_lookup();
1948 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001949
1950 /* Extract opaque LSA from message */
1951 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1952
1953 /* Lookup area for link-local and area-local opaque LSAs */
1954 switch (dmsg->lsa_type)
1955 {
1956 case OSPF_OPAQUE_LINK_LSA:
1957 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001958 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001959 if (!area)
1960 {
1961 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1962 inet_ntoa (dmsg->area_id));
1963 rc = OSPF_API_NOSUCHAREA;
1964 goto out;
1965 }
1966 break;
1967 case OSPF_OPAQUE_AS_LSA:
1968 /* AS-external opaque LSAs have no designated area */
1969 area = NULL;
1970 break;
1971 default:
1972 zlog_warn
1973 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1974 dmsg->lsa_type);
1975 rc = OSPF_API_ILLEGALLSATYPE;
1976 goto out;
1977 }
1978
1979 /* Check if we registered this opaque type */
1980 lsa_type = dmsg->lsa_type;
1981 opaque_type = dmsg->opaque_type;
1982
1983 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1984 {
1985 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1986 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1987 goto out;
1988 }
1989
1990 /* opaque_id is in network byte order */
1991 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1992 ntohl (dmsg->opaque_id)));
1993
1994 /*
1995 * Even if the target LSA has once scheduled to flush, it remains in
1996 * the LSDB until it is finally handled by the maxage remover thread.
1997 * Therefore, the lookup function below may return non-NULL result.
1998 */
paul99b7c5d2003-04-06 01:19:28 +00001999 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00002000 if (!old)
2001 {
2002 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
2003 dmsg->lsa_type, inet_ntoa (id));
2004 rc = OSPF_API_NOSUCHLSA;
2005 goto out;
2006 }
2007
2008 /* Schedule flushing of LSA from LSDB */
2009 /* NB: Multiple scheduling will produce a warning message, but harmless. */
2010 ospf_opaque_lsa_flush_schedule (old);
2011
2012out:
2013
2014 /* Send reply back to client including return code */
2015 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
2016 return rc;
2017}
2018
2019/* Flush self-originated opaque LSA */
2020int
2021apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2022 void *p_arg, int int_arg)
2023{
2024 struct param_t
2025 {
2026 struct ospf_apiserver *apiserv;
2027 u_char lsa_type;
2028 u_char opaque_type;
2029 }
2030 *param;
2031
2032 /* Sanity check */
2033 assert (lsa->data);
2034 assert (p_arg);
2035 param = (struct param_t *) p_arg;
2036
2037 /* If LSA matches type and opaque type then delete it */
2038 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2039 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2040 {
2041 ospf_opaque_lsa_flush_schedule (lsa);
2042 }
2043 return 0;
2044}
2045
2046/* Delete self-originated opaque LSAs of a given opaque type. This
2047 function is called when an application unregisters a given opaque
2048 type or a connection to an application closes and all those opaque
2049 LSAs need to be flushed the LSDB. */
2050void
2051ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2052 u_char lsa_type, u_char opaque_type)
2053{
2054 struct param_t
2055 {
2056 struct ospf_apiserver *apiserv;
2057 u_char lsa_type;
2058 u_char opaque_type;
2059 }
2060 param;
2061 listnode node;
paul99b7c5d2003-04-06 01:19:28 +00002062 struct ospf * ospf;
2063
2064 ospf = ospf_lookup();
2065 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002066
2067 /* Set parameter struct. */
2068 param.apiserv = apiserv;
2069 param.lsa_type = lsa_type;
2070 param.opaque_type = opaque_type;
2071
2072#ifdef ORIGINAL_CODING
2073 /* Iterate over all areas */
2074 for (node = listhead (ospf_top->areas); node; nextnode (node))
2075 {
2076 struct ospf_area *area = node->data;
2077
2078 foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) &param, 0,
2079 apiserver_flush_opaque_type_callback);
2080 foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) &param, 0,
2081 apiserver_flush_opaque_type_callback);
2082 }
2083
2084 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00002085 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00002086 {
2087 foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) &param, 0,
2088 apiserver_flush_opaque_type_callback);
2089 }
2090#else /* ORIGINAL_CODING */
2091 switch (lsa_type)
2092 {
paul99b7c5d2003-04-06 01:19:28 +00002093 struct route_node *rn;
2094 struct ospf_lsa *lsa;
2095
paul2d33f152003-03-17 01:10:58 +00002096 case OSPF_OPAQUE_LINK_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002097 for (node = listhead (ospf->areas); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00002098 {
2099 struct ospf_area *area = node->data;
paul99b7c5d2003-04-06 01:19:28 +00002100 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2101 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002102 }
2103 break;
2104 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002105 for (node = listhead (ospf->areas); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00002106 {
2107 struct ospf_area *area = node->data;
paul99b7c5d2003-04-06 01:19:28 +00002108 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2109 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002110 }
2111 break;
2112 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002113 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2114 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002115 break;
2116 default:
2117 break;
2118 }
2119 return;
2120#endif /* ORIGINAL_CODING */
2121}
2122
2123
2124/* -----------------------------------------------------------
2125 * Followings are callback functions to handle opaque types
2126 * -----------------------------------------------------------
2127 */
2128
2129int
2130ospf_apiserver_new_if (struct interface *ifp)
2131{
2132 struct ospf_interface *oi;
2133
2134 /* For some strange reason it seems possible that we are invoked
2135 with an interface that has no name. This seems to happen during
2136 initialization. Return if this happens */
2137
2138 if (ifp->name[0] == '\0') {
2139 /* interface has empty name */
2140 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2141 return 0;
2142 }
2143
2144 /* zlog_warn for debugging */
2145 zlog_warn ("ospf_apiserver_new_if");
2146 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2147 ifp->ifindex);
2148
2149 if (ifp->name[0] == '\0') {
2150 /* interface has empty name */
2151 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2152 return 0;
2153 }
2154
2155 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2156
2157 if (!oi) {
2158 /* This interface is known to Zebra but not to OSPF daemon yet. */
2159 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2160 ifp->name);
2161 return 0;
2162 }
2163
2164 assert (oi);
2165
2166 /* New interface added to OSPF, tell clients about it */
2167 if (listcount (apiserver_list) > 0) {
2168 ospf_apiserver_clients_notify_new_if (oi);
2169 }
2170 return 0;
2171}
2172
2173int
2174ospf_apiserver_del_if (struct interface *ifp)
2175{
2176 struct ospf_interface *oi;
2177
2178 /* zlog_warn for debugging */
2179 zlog_warn ("ospf_apiserver_del_if");
2180 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2181 ifp->ifindex);
2182
2183 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002184
2185 if (!oi) {
2186 /* This interface is known to Zebra but not to OSPF daemon
2187 anymore. No need to tell clients about it */
2188 return 0;
2189 }
paul2d33f152003-03-17 01:10:58 +00002190
2191 /* Interface deleted, tell clients about it */
2192 if (listcount (apiserver_list) > 0) {
2193 ospf_apiserver_clients_notify_del_if (oi);
2194 }
2195 return 0;
2196}
2197
2198void
2199ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2200{
2201 /* Tell clients about interface change */
2202
2203 /* zlog_warn for debugging */
2204 zlog_warn ("ospf_apiserver_ism_change");
2205 if (listcount (apiserver_list) > 0) {
2206 ospf_apiserver_clients_notify_ism_change (oi);
2207 }
2208
2209 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2210 zlog_warn ("old_state=%d", old_state);
2211 zlog_warn ("oi->state=%d", oi->state);
2212}
2213
2214void
2215ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2216{
2217 /* Neighbor status changed, tell clients about it */
2218 zlog_warn ("ospf_apiserver_nsm_change");
2219 if (listcount (apiserver_list) > 0) {
2220 ospf_apiserver_clients_notify_nsm_change (nbr);
2221 }
2222}
2223
2224void
2225ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2226{
2227 struct opaque_lsa
2228 {
2229 struct lsa_header header;
2230 u_char data[1]; /* opaque data have variable length. This is start
2231 address */
2232 };
2233 struct opaque_lsa *olsa;
2234 int opaquelen;
2235
2236 olsa = (struct opaque_lsa *) lsa->data;
2237
2238 if (VALID_OPAQUE_INFO_LEN (lsa->data))
2239 {
2240 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2241 }
2242 else
2243 {
2244 opaquelen = 0;
2245 }
2246
2247 /* Output information about opaque LSAs */
2248 if (vty != NULL)
2249 {
2250 int i;
2251 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2252 opaquelen,
2253 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2254 VTY_NEWLINE);
2255 vty_out (vty, " Opaque data: ");
2256
2257 for (i = 0; i < opaquelen; i++)
2258 {
2259 vty_out (vty, "0x%x ", olsa->data[i]);
2260 }
2261 vty_out (vty, "%s", VTY_NEWLINE);
2262 }
2263 else
2264 {
2265 int i;
2266 zlog_info (" Added using OSPF API: %u octets of opaque data %s",
2267 opaquelen,
2268 VALID_OPAQUE_INFO_LEN (lsa->
2269 data) ? "" : "(Invalid length?)");
2270 zlog_info (" Opaque data: ");
2271
2272 for (i = 0; i < opaquelen; i++)
2273 {
2274 zlog_info ("0x%x ", olsa->data[i]);
2275 }
2276 zlog_info ("\n");
2277 }
2278 return;
2279}
2280
2281/* -----------------------------------------------------------
2282 * Followings are functions to notify clients about events
2283 * -----------------------------------------------------------
2284 */
2285
2286/* Send a message to all clients. This is useful for messages
2287 that need to be notified to all clients (such as interface
2288 changes) */
2289
2290void
2291ospf_apiserver_clients_notify_all (struct msg *msg)
2292{
2293 listnode node;
2294
2295 /* Send message to all clients */
2296 for (node = listhead (apiserver_list); node; nextnode (node))
2297 {
2298 struct ospf_apiserver *apiserv =
2299 (struct ospf_apiserver *) getdata (node);
2300
2301 ospf_apiserver_send_msg (apiserv, msg);
2302 }
2303}
2304
2305/* An interface is now ready to accept opaque LSAs. Notify all
2306 clients that registered to use this opaque type */
2307void
2308ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2309{
2310 listnode node;
2311 struct msg *msg;
2312
2313 assert (oi);
2314 if (!oi->address)
2315 {
2316 zlog_warn ("Interface has no address?");
2317 return;
2318 }
2319
2320 if (!ospf_apiserver_is_ready_type9 (oi))
2321 {
2322 zlog_warn ("Interface not ready for type 9?");
2323 return;
2324 }
2325
2326 for (node = listhead (apiserver_list); node; nextnode (node))
2327 {
2328 struct ospf_apiserver *apiserv =
2329 (struct ospf_apiserver *) getdata (node);
2330 listnode n2;
2331
2332 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2333 {
2334 struct registered_opaque_type *r =
2335 (struct registered_opaque_type *) getdata (n2);
2336 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2337 {
2338 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2339 r->opaque_type,
2340 oi->address->u.prefix4);
2341 if (!msg)
2342 {
2343 zlog_warn
2344 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify 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
2362void
2363ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2364{
2365 listnode node;
2366 struct msg *msg;
2367
2368 assert (area);
2369
2370 if (!ospf_apiserver_is_ready_type10 (area))
2371 {
2372 zlog_warn ("Area not ready for type 10?");
2373 return;
2374 }
2375
2376 for (node = listhead (apiserver_list); node; nextnode (node))
2377 {
2378 struct ospf_apiserver *apiserv =
2379 (struct ospf_apiserver *) getdata (node);
2380 listnode n2;
2381
2382 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2383 {
2384 struct registered_opaque_type *r =
2385 (struct registered_opaque_type *) getdata (n2);
2386 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2387 {
2388 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2389 r->opaque_type, area->area_id);
2390 if (!msg)
2391 {
2392 zlog_warn
2393 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2394#ifdef NOTYET
2395 /* Cannot allocate new message. What should we do? */
2396 ospf_apiserver_free (apiserv);
2397#endif
2398 goto out;
2399 }
2400
2401 ospf_apiserver_send_msg (apiserv, msg);
2402 msg_free (msg);
2403 }
2404 }
2405 }
2406
2407out:
2408 return;
2409}
2410
2411
2412void
2413ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2414{
2415 listnode node;
2416 struct msg *msg;
2417 struct in_addr id_null = { 0L };
2418
2419 assert (top);
2420
2421 if (!ospf_apiserver_is_ready_type11 (top))
2422 {
2423 zlog_warn ("AS not ready for type 11?");
2424 return;
2425 }
2426
2427 for (node = listhead (apiserver_list); node; nextnode (node))
2428 {
2429 struct ospf_apiserver *apiserv =
2430 (struct ospf_apiserver *) getdata (node);
2431 listnode n2;
2432
2433 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2434 {
2435 struct registered_opaque_type *r =
2436 (struct registered_opaque_type *) getdata (n2);
2437 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2438 {
2439 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2440 r->opaque_type, id_null);
2441 if (!msg)
2442 {
2443 zlog_warn
2444 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2445#ifdef NOTYET
2446 /* Cannot allocate new message. What should we do? */
2447 ospf_apiserver_free (apiserv);
2448#endif
2449 goto out;
2450 }
2451
2452 ospf_apiserver_send_msg (apiserv, msg);
2453 msg_free (msg);
2454 }
2455 }
2456 }
2457
2458out:
2459 return;
2460}
2461
2462void
2463ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2464{
2465 struct msg *msg;
2466
2467 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2468 if (msg != NULL)
2469 {
2470 ospf_apiserver_clients_notify_all (msg);
2471 msg_free (msg);
2472 }
2473}
2474
2475void
2476ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2477{
2478 struct msg *msg;
2479
2480 msg = new_msg_del_if (0, oi->address->u.prefix4);
2481 if (msg != NULL)
2482 {
2483 ospf_apiserver_clients_notify_all (msg);
2484 msg_free (msg);
2485 }
2486}
2487
2488void
2489ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2490{
2491 struct msg *msg;
2492 struct in_addr ifaddr = { 0L };
2493 struct in_addr area_id = { 0L };
2494
2495 assert (oi);
2496 assert (oi->ifp);
2497
2498 if (oi->address)
2499 {
2500 ifaddr = oi->address->u.prefix4;
2501 }
2502 if (oi->area)
2503 {
2504 area_id = oi->area->area_id;
2505 }
2506
2507 msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status);
2508 if (!msg)
2509 {
2510 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2511 return;
2512 }
2513
2514 ospf_apiserver_clients_notify_all (msg);
2515 msg_free (msg);
2516}
2517
2518void
2519ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2520{
2521 struct msg *msg;
2522 struct in_addr ifaddr = { 0L };
2523 struct in_addr nbraddr = { 0L };
2524
2525 assert (nbr);
2526
2527 if (nbr->oi)
2528 {
2529 ifaddr = nbr->oi->address->u.prefix4;
2530 }
2531
2532 nbraddr = nbr->address.u.prefix4;
2533
2534 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2535 if (!msg)
2536 {
2537 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2538 return;
2539 }
2540
2541 ospf_apiserver_clients_notify_all (msg);
2542 msg_free (msg);
2543}
2544
2545void
2546apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2547{
2548 struct msg *msg;
2549 listnode node;
2550
2551 /* Default area for AS-External and Opaque11 LSAs */
2552 struct in_addr area_id = { 0L };
2553
2554 /* Default interface for non Opaque9 LSAs */
2555 struct in_addr ifaddr = { 0L };
2556
2557 if (lsa->area)
2558 {
2559 area_id = lsa->area->area_id;
2560 }
2561 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2562 {
2563 assert (lsa->oi);
2564 ifaddr = lsa->oi->address->u.prefix4;
2565 }
2566
2567 /* Prepare message that can be sent to clients that have a matching
2568 filter */
2569 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2570 ifaddr, area_id,
2571 lsa->flags & OSPF_LSA_SELF, lsa->data);
2572 if (!msg)
2573 {
2574 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2575 return;
2576 }
2577
2578 /* Now send message to all clients with a matching filter */
2579 for (node = listhead (apiserver_list); node; nextnode (node))
2580 {
2581 struct ospf_apiserver *apiserv = (struct ospf_apiserver *) node->data;
2582 struct lsa_filter_type *filter;
2583 u_int16_t mask;
2584 u_int32_t *area;
2585 int i;
2586
2587 /* Check filter for this client. */
2588 filter = apiserv->filter;
2589
2590 /* Check area IDs in case of non AS-E LSAs.
2591 * If filter has areas (num_areas > 0),
2592 * then one of the areas must match the area ID of this LSA. */
2593
2594 i = filter->num_areas;
2595 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2596 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2597 {
2598 i = 0;
2599 }
2600
2601 if (i > 0)
2602 {
2603 area = (u_int32_t *) (filter + 1);
2604 while (i)
2605 {
2606 if (*area == area_id.s_addr)
2607 {
2608 break;
2609 }
2610 i--;
2611 area++;
2612 }
2613 }
2614 else
2615 {
2616 i = 1;
2617 }
2618
2619 if (i > 0)
2620 {
2621 /* Area match. Check LSA type. */
2622 mask = ntohs (filter->typemask);
2623
2624 if (mask & Power2[lsa->data->type])
2625 {
2626 /* Type also matches. Check origin. */
2627 if ((filter->origin == ANY_ORIGIN) ||
2628 (filter->origin == IS_LSA_SELF (lsa)))
2629 {
2630 ospf_apiserver_send_msg (apiserv, msg);
2631 }
2632 }
2633 }
2634 }
2635 /* Free message since it is not used anymore */
2636 msg_free (msg);
2637}
2638
2639
2640/* -------------------------------------------------------------
2641 * Followings are hooks invoked when LSAs are updated or deleted
2642 * -------------------------------------------------------------
2643 */
2644
2645
2646int
2647apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2648{
2649 struct msg *msg;
2650 /* default area for AS-External and Opaque11 LSAs */
2651 struct in_addr area_id = { 0L };
2652
2653 /* default interface for non Opaque9 LSAs */
2654 struct in_addr ifaddr = { 0L };
2655
2656 /* Only notify this update if the LSA's age is smaller than
2657 MAXAGE. Otherwise clients would see LSA updates with max age just
2658 before they are deleted from the LSDB. LSA delete messages have
2659 MAXAGE too but should not be filtered. */
2660 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2661 return 0;
2662 }
2663
2664 if (lsa->area)
2665 {
2666 area_id = lsa->area->area_id;
2667 }
2668 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2669 {
2670 ifaddr = lsa->oi->address->u.prefix4;
2671 }
2672 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2673 ifaddr, area_id,
2674 lsa->flags & OSPF_LSA_SELF, lsa->data);
2675 if (!msg)
2676 {
2677 zlog_warn ("notify_clients_lsa: msg_new failed");
2678 return -1;
2679 }
2680 /* Notify all clients that new LSA is added/updated */
2681 apiserver_clients_lsa_change_notify (msgtype, lsa);
2682
2683 /* Clients made their own copies of msg so we can free msg here */
2684 msg_free (msg);
2685
2686 return 0;
2687}
2688
2689int
2690ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2691{
2692 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2693}
2694
2695int
2696ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2697{
2698 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2699}
2700
2701#endif /* SUPPORT_OSPF_API */
2702