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