blob: 941678422dc900cdb8873b1db4853c975048af82 [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
paul99b7c5d2003-04-06 01:19:28 +000090 ospf = ospf_lookup ();
91
92 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +000093 {
94 if ((oi = getdata (node)) != NULL
95 && oi->type != OSPF_IFTYPE_VIRTUALLINK)
96 {
97 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
98 return oi;
99 }
100 }
101 return NULL;
102}
103
104struct ospf_interface *
105ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
106{
107 listnode node;
108 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +0000109 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000110
paul99b7c5d2003-04-06 01:19:28 +0000111 ospf = ospf_lookup ();
112
113 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +0000114 {
115 if ((oi = getdata (node)) && oi->ifp == ifp)
116 {
117 return oi;
118 }
119 }
120 return NULL;
121}
122
123/* -----------------------------------------------------------
124 * Initialization
125 * -----------------------------------------------------------
126 */
127
128unsigned short
129ospf_apiserver_getport (void)
130{
131 struct servent *sp = getservbyname ("ospfapi", "tcp");
132
133 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
134}
135
136/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
137int
138ospf_apiserver_init (void)
139{
140 int fd;
141 int rc = -1;
142
143 /* Create new socket for synchronous messages. */
144 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
145
146 if (fd < 0)
147 goto out;
148
149 /* Schedule new thread that handles accepted connections. */
150 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
151
152 /* Initialize list that keeps track of all connections. */
153 apiserver_list = list_new ();
154
155 /* Register opaque-independent call back functions. These functions
156 are invoked on ISM, NSM changes and LSA update and LSA deletes */
157 rc =
158 ospf_register_opaque_functab (0 /* all LSAs */,
159 0 /* all opaque types */,
160 ospf_apiserver_new_if,
161 ospf_apiserver_del_if,
162 ospf_apiserver_ism_change,
163 ospf_apiserver_nsm_change,
164 NULL,
165 NULL,
166 NULL,
167 NULL, /* ospf_apiserver_show_info */
168 NULL, /* originator_func */
169 NULL, /* ospf_apiserver_lsa_refresher */
170 ospf_apiserver_lsa_update,
171 ospf_apiserver_lsa_delete);
172 if (rc != 0)
173 {
174 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
175 }
176
177 rc = 0;
178
179out:
180 return rc;
181}
182
183/* Terminate OSPF API module. */
184void
185ospf_apiserver_term (void)
186{
187 listnode node;
188
189 /* Unregister wildcard [0/0] type */
190 ospf_delete_opaque_functab (0 /* all LSAs */,
191 0 /* all opaque types */);
192
193 /* Free all client instances */
194 for (node = listhead (apiserver_list); node; nextnode (node))
195 {
196 struct ospf_apiserver *apiserv =
197 (struct ospf_apiserver *) getdata (node);
198 ospf_apiserver_free (apiserv);
199 }
200
201 /* Free client list itself */
202 list_delete (apiserver_list);
203
204 /* Free wildcard list */
205 /* XXX */
206}
207
208static struct ospf_apiserver *
209lookup_apiserver (u_char lsa_type, u_char opaque_type)
210{
211 listnode n1, n2;
212 struct registered_opaque_type *r;
213 struct ospf_apiserver *apiserv, *found = NULL;
214
215 for (n1 = listhead (apiserver_list); n1; nextnode (n1))
216 {
217 apiserv = (struct ospf_apiserver *) getdata (n1);
218
219 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
220 {
221 r = (struct registered_opaque_type *) getdata (n2);
222
223 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
224 {
225 found = apiserv;
226 goto out;
227 }
228 }
229 }
230out:
231 return found;
232}
233
234static struct ospf_apiserver *
235lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
236{
237 struct lsa_header *lsah = lsa->data;
238 struct ospf_apiserver *found = NULL;
239
240 if (IS_OPAQUE_LSA (lsah->type))
241 {
242 found = lookup_apiserver (lsah->type,
243 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
244 }
245 return found;
246}
247
248/* -----------------------------------------------------------
249 * Followings are functions to manage client connections.
250 * -----------------------------------------------------------
251 */
252static int
253ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
254{
255 if (IS_DEBUG_OSPF_EVENT)
256 zlog_info ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
257 return 0;
258}
259
260static int
261ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
262{
263 if (IS_DEBUG_OSPF_EVENT)
264 zlog_info ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
265 return 0;
266}
267
268/* Allocate new connection structure. */
269struct ospf_apiserver *
270ospf_apiserver_new (int fd_sync, int fd_async)
271{
272 struct ospf_apiserver *new =
273 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
274
275 new->filter =
276 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
277
278 new->fd_sync = fd_sync;
279 new->fd_async = fd_async;
280
281 /* list of registered opaque types that application uses */
282 new->opaque_types = list_new ();
283
284 /* Initialize temporary strage for LSA instances to be refreshed. */
285 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
286 ospf_lsdb_init (&new->reserve);
287
288 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
289 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
290
291 new->out_sync_fifo = msg_fifo_new ();
292 new->out_async_fifo = msg_fifo_new ();
293 new->t_sync_read = NULL;
294#ifdef USE_ASYNC_READ
295 new->t_async_read = NULL;
296#endif /* USE_ASYNC_READ */
297 new->t_sync_write = NULL;
298 new->t_async_write = NULL;
299
300 new->filter->typemask = 0; /* filter all LSAs */
301 new->filter->origin = ANY_ORIGIN;
302 new->filter->num_areas = 0;
303
304 return new;
305}
306
307void
308ospf_apiserver_event (enum event event, int fd,
309 struct ospf_apiserver *apiserv)
310{
311 struct thread *apiserver_serv_thread;
312
313 switch (event)
314 {
315 case OSPF_APISERVER_ACCEPT:
316 apiserver_serv_thread =
317 thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
318 break;
319 case OSPF_APISERVER_SYNC_READ:
320 apiserv->t_sync_read =
321 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
322 break;
323#ifdef USE_ASYNC_READ
324 case OSPF_APISERVER_ASYNC_READ:
325 apiserv->t_async_read =
326 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
327 break;
328#endif /* USE_ASYNC_READ */
329 case OSPF_APISERVER_SYNC_WRITE:
330 if (!apiserv->t_sync_write)
331 {
332 apiserv->t_sync_write =
333 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
334 }
335 break;
336 case OSPF_APISERVER_ASYNC_WRITE:
337 if (!apiserv->t_async_write)
338 {
339 apiserv->t_async_write =
340 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
341 }
342 break;
343 }
344}
345
346/* Free instance. First unregister all opaque types used by
347 application, flush opaque LSAs injected by application
348 from network and close connection. */
349void
350ospf_apiserver_free (struct ospf_apiserver *apiserv)
351{
352 listnode node;
353
354 /* Cancel read and write threads. */
355 if (apiserv->t_sync_read)
356 {
357 thread_cancel (apiserv->t_sync_read);
358 }
359#ifdef USE_ASYNC_READ
360 if (apiserv->t_async_read)
361 {
362 thread_cancel (apiserv->t_async_read);
363 }
364#endif /* USE_ASYNC_READ */
365 if (apiserv->t_sync_write)
366 {
367 thread_cancel (apiserv->t_sync_write);
368 }
369
370 if (apiserv->t_async_write)
371 {
372 thread_cancel (apiserv->t_async_write);
373 }
374
375 /* Unregister all opaque types that application registered
376 and flush opaque LSAs if still in LSDB. */
377
378 while ((node = listhead (apiserv->opaque_types)) != NULL)
379 {
380
381 struct registered_opaque_type *regtype = node->data;
382
383 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
384 regtype->opaque_type);
385
386 }
387
388 /* Close connections to OSPFd. */
389 if (apiserv->fd_sync > 0)
390 {
391 close (apiserv->fd_sync);
392 }
393
394 if (apiserv->fd_async > 0)
395 {
396 close (apiserv->fd_async);
397 }
398
399 /* Free fifos */
400 msg_fifo_free (apiserv->out_sync_fifo);
401 msg_fifo_free (apiserv->out_async_fifo);
402
403 /* Clear temporary strage for LSA instances to be refreshed. */
404 ospf_lsdb_delete_all (&apiserv->reserve);
405 ospf_lsdb_cleanup (&apiserv->reserve);
406
407 /* Remove from the list of active clients. */
408 listnode_delete (apiserver_list, apiserv);
409
410 if (IS_DEBUG_OSPF_EVENT)
411 zlog_info ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
412
413 /* And free instance. */
414 XFREE (MTYPE_OSPF_APISERVER, apiserv);
415}
416
417int
418ospf_apiserver_read (struct thread *thread)
419{
420 struct ospf_apiserver *apiserv;
421 struct msg *msg;
422 int fd;
423 int rc = -1;
424 enum event event;
425
426 apiserv = THREAD_ARG (thread);
427 fd = THREAD_FD (thread);
428
429 if (fd == apiserv->fd_sync)
430 {
431 event = OSPF_APISERVER_SYNC_READ;
432 apiserv->t_sync_read = NULL;
433
434 if (IS_DEBUG_OSPF_EVENT)
435 zlog_info ("API: ospf_apiserver_read: Peer: %s/%u",
436 inet_ntoa (apiserv->peer_sync.sin_addr),
437 ntohs (apiserv->peer_sync.sin_port));
438 }
439#ifdef USE_ASYNC_READ
440 else if (fd == apiserv->fd_async)
441 {
442 event = OSPF_APISERVER_ASYNC_READ;
443 apiserv->t_async_read = NULL;
444
445 if (IS_DEBUG_OSPF_EVENT)
446 zlog_info ("API: ospf_apiserver_read: Peer: %s/%u",
447 inet_ntoa (apiserv->peer_async.sin_addr),
448 ntohs (apiserv->peer_async.sin_port));
449 }
450#endif /* USE_ASYNC_READ */
451 else
452 {
453 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
454 ospf_apiserver_free (apiserv);
455 goto out;
456 }
457
458 /* Read message from fd. */
459 msg = msg_read (fd);
460 if (msg == NULL)
461 {
462 zlog_warn
463 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
464
465 /* Perform cleanup. */
466 ospf_apiserver_free (apiserv);
467 goto out;
468 }
469
470 if (IS_DEBUG_OSPF_EVENT)
471 msg_print (msg);
472
473 /* Dispatch to corresponding message handler. */
474 rc = ospf_apiserver_handle_msg (apiserv, msg);
475
476 /* Prepare for next message, add read thread. */
477 ospf_apiserver_event (event, fd, apiserv);
478
479 msg_free (msg);
480
481out:
482 return rc;
483}
484
485int
486ospf_apiserver_sync_write (struct thread *thread)
487{
488 struct ospf_apiserver *apiserv;
489 struct msg *msg;
490 int fd;
491 int rc = -1;
492
493 apiserv = THREAD_ARG (thread);
494 assert (apiserv);
495 fd = THREAD_FD (thread);
496
497 apiserv->t_sync_write = NULL;
498
499 /* Sanity check */
500 if (fd != apiserv->fd_sync)
501 {
502 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
503 goto out;
504 }
505
506 if (IS_DEBUG_OSPF_EVENT)
507 zlog_info ("API: ospf_apiserver_sync_write: Peer: %s/%u",
508 inet_ntoa (apiserv->peer_sync.sin_addr),
509 ntohs (apiserv->peer_sync.sin_port));
510
511 /* Check whether there is really a message in the fifo. */
512 msg = msg_fifo_pop (apiserv->out_sync_fifo);
513 if (!msg)
514 {
515 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
516 return 0;
517 }
518
519 if (IS_DEBUG_OSPF_EVENT)
520 msg_print (msg);
521
522 rc = msg_write (fd, msg);
523
524 /* Once a message is dequeued, it should be freed anyway. */
525 msg_free (msg);
526
527 if (rc < 0)
528 {
529 zlog_warn
530 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
531 goto out;
532 }
533
534
535 /* If more messages are in sync message fifo, schedule write thread. */
536 if (msg_fifo_head (apiserv->out_sync_fifo))
537 {
538 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
539 apiserv);
540 }
541
542 out:
543
544 if (rc < 0)
545 {
546 /* Perform cleanup and disconnect with peer */
547 ospf_apiserver_free (apiserv);
548 }
549
550 return rc;
551}
552
553
554int
555ospf_apiserver_async_write (struct thread *thread)
556{
557 struct ospf_apiserver *apiserv;
558 struct msg *msg;
559 int fd;
560 int rc = -1;
561
562 apiserv = THREAD_ARG (thread);
563 assert (apiserv);
564 fd = THREAD_FD (thread);
565
566 apiserv->t_async_write = NULL;
567
568 /* Sanity check */
569 if (fd != apiserv->fd_async)
570 {
571 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
572 goto out;
573 }
574
575 if (IS_DEBUG_OSPF_EVENT)
576 zlog_info ("API: ospf_apiserver_async_write: Peer: %s/%u",
577 inet_ntoa (apiserv->peer_async.sin_addr),
578 ntohs (apiserv->peer_async.sin_port));
579
580 /* Check whether there is really a message in the fifo. */
581 msg = msg_fifo_pop (apiserv->out_async_fifo);
582 if (!msg)
583 {
584 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
585 return 0;
586 }
587
588 if (IS_DEBUG_OSPF_EVENT)
589 msg_print (msg);
590
591 rc = msg_write (fd, msg);
592
593 /* Once a message is dequeued, it should be freed anyway. */
594 msg_free (msg);
595
596 if (rc < 0)
597 {
598 zlog_warn
599 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
600 goto out;
601 }
602
603
604 /* If more messages are in async message fifo, schedule write thread. */
605 if (msg_fifo_head (apiserv->out_async_fifo))
606 {
607 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
608 apiserv);
609 }
610
611 out:
612
613 if (rc < 0)
614 {
615 /* Perform cleanup and disconnect with peer */
616 ospf_apiserver_free (apiserv);
617 }
618
619 return rc;
620}
621
622
623int
624ospf_apiserver_serv_sock_family (unsigned short port, int family)
625{
626 union sockunion su;
627 int accept_sock;
628 int rc;
629
630 memset (&su, 0, sizeof (union sockunion));
631 su.sa.sa_family = family;
632
633 /* Make new socket */
634 accept_sock = sockunion_stream_socket (&su);
635 if (accept_sock < 0)
636 return accept_sock;
637
638 /* This is a server, so reuse address and port */
639 sockopt_reuseaddr (accept_sock);
640 sockopt_reuseport (accept_sock);
641
642 /* Bind socket to address and given port. */
643 rc = sockunion_bind (accept_sock, &su, port, NULL);
644 if (rc < 0)
645 {
646 close (accept_sock); /* Close socket */
647 return rc;
648 }
649
650 /* Listen socket under queue length 3. */
651 rc = listen (accept_sock, 3);
652 if (rc < 0)
653 {
654 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
655 strerror (errno));
656 close (accept_sock); /* Close socket */
657 return rc;
658 }
659 return accept_sock;
660}
661
662
663/* Accept connection request from external applications. For each
664 accepted connection allocate own connection instance. */
665int
666ospf_apiserver_accept (struct thread *thread)
667{
668 int accept_sock;
669 int new_sync_sock;
670 int new_async_sock;
671 union sockunion su;
672 struct ospf_apiserver *apiserv;
673 struct sockaddr_in peer_async;
674 struct sockaddr_in peer_sync;
675 int peerlen;
676 int ret;
677
678 /* THREAD_ARG (thread) is NULL */
679 accept_sock = THREAD_FD (thread);
680
681 /* Keep hearing on socket for further connections. */
682 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
683
684 memset (&su, 0, sizeof (union sockunion));
685 /* Accept connection for synchronous messages */
686 new_sync_sock = sockunion_accept (accept_sock, &su);
687 if (new_sync_sock < 0)
688 {
689 zlog_warn ("ospf_apiserver_accept: accept: %s", strerror (errno));
690 return -1;
691 }
692
693 /* Get port address and port number of peer to make reverse connection.
694 The reverse channel uses the port number of the peer port+1. */
695
696 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
697 peerlen = sizeof (struct sockaddr_in);
698
699 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
700 if (ret < 0)
701 {
702 zlog_warn ("ospf_apiserver_accept: getpeername: %s", strerror (errno));
703 close (new_sync_sock);
704 return -1;
705 }
706
707 if (IS_DEBUG_OSPF_EVENT)
708 zlog_info ("API: ospf_apiserver_accept: New peer: %s/%u",
709 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
710
711 /* Create new socket for asynchronous messages. */
712 peer_async = peer_sync;
713 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
714
715 /* Check if remote port number to make reverse connection is valid one. */
716 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
717 {
718 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
719 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
720 close (new_sync_sock);
721 return -1;
722 }
723
724 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
725 if (new_async_sock < 0)
726 {
727 zlog_warn ("ospf_apiserver_accept: socket: %s", strerror (errno));
728 close (new_sync_sock);
729 return -1;
730 }
731
732 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
733 sizeof (struct sockaddr_in));
734
735 if (ret < 0)
736 {
737 zlog_warn ("ospf_apiserver_accept: connect: %s", strerror (errno));
738 close (new_sync_sock);
739 close (new_async_sock);
740 return -1;
741 }
742
743#ifdef USE_ASYNC_READ
744#else /* USE_ASYNC_READ */
745 /* Make the asynchronous channel write-only. */
746 ret = shutdown (new_async_sock, SHUT_RD);
747 if (ret < 0)
748 {
749 zlog_warn ("ospf_apiserver_accept: shutdown: %s", strerror (errno));
750 close (new_sync_sock);
751 close (new_async_sock);
752 return -1;
753 }
754#endif /* USE_ASYNC_READ */
755
756 /* Allocate new server-side connection structure */
757 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
758
759 /* Add to active connection list */
760 listnode_add (apiserver_list, apiserv);
761 apiserv->peer_sync = peer_sync;
762 apiserv->peer_async = peer_async;
763
764 /* And add read threads for new connection */
765 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
766#ifdef USE_ASYNC_READ
767 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
768#endif /* USE_ASYNC_READ */
769
770 if (IS_DEBUG_OSPF_EVENT)
771 zlog_warn ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
772
773 return 0;
774}
775
776
777/* -----------------------------------------------------------
778 * Send reply with return code to client application
779 * -----------------------------------------------------------
780 */
781
782int
783ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
784{
785 struct msg_fifo *fifo;
786 struct msg *msg2;
787 enum event event;
788 int fd;
789
790 switch (msg->hdr.msgtype)
791 {
792 case MSG_REPLY:
793 fifo = apiserv->out_sync_fifo;
794 fd = apiserv->fd_sync;
795 event = OSPF_APISERVER_SYNC_WRITE;
796 break;
797 case MSG_READY_NOTIFY:
798 case MSG_LSA_UPDATE_NOTIFY:
799 case MSG_LSA_DELETE_NOTIFY:
800 case MSG_NEW_IF:
801 case MSG_DEL_IF:
802 case MSG_ISM_CHANGE:
803 case MSG_NSM_CHANGE:
804 fifo = apiserv->out_async_fifo;
805 fd = apiserv->fd_async;
806 event = OSPF_APISERVER_ASYNC_WRITE;
807 break;
808 default:
809 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
810 msg->hdr.msgtype);
811 return -1;
812 }
813
814 /* Make a copy of the message and put in the fifo. Once the fifo
815 gets drained by the write thread, the message will be freed. */
816 /* NB: Given "msg" is untouched in this function. */
817 msg2 = msg_dup (msg);
818
819 /* Enqueue message into corresponding fifo queue */
820 msg_fifo_push (fifo, msg2);
821
822 /* Schedule write thread */
823 ospf_apiserver_event (event, fd, apiserv);
824 return 0;
825}
826
827int
828ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
829 u_char rc)
830{
831 struct msg *msg = new_msg_reply (seqnr, rc);
832 int ret;
833
834 if (!msg)
835 {
836 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
837#ifdef NOTYET
838 /* Cannot allocate new message. What should we do? */
839 ospf_apiserver_free (apiserv);
840#endif
841 return -1;
842 }
843
844 ret = ospf_apiserver_send_msg (apiserv, msg);
845 msg_free (msg);
846 return ret;
847}
848
849
850/* -----------------------------------------------------------
851 * Generic message dispatching handler function
852 * -----------------------------------------------------------
853 */
854
855int
856ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
857{
858 int rc;
859
860 /* Call corresponding message handler function. */
861 switch (msg->hdr.msgtype)
862 {
863 case MSG_REGISTER_OPAQUETYPE:
864 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
865 break;
866 case MSG_UNREGISTER_OPAQUETYPE:
867 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
868 break;
869 case MSG_REGISTER_EVENT:
870 rc = ospf_apiserver_handle_register_event (apiserv, msg);
871 break;
872 case MSG_SYNC_LSDB:
873 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
874 break;
875 case MSG_ORIGINATE_REQUEST:
876 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
877 break;
878 case MSG_DELETE_REQUEST:
879 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
880 break;
881 default:
882 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
883 msg->hdr.msgtype);
884 rc = -1;
885 }
886 return rc;
887}
888
889
890/* -----------------------------------------------------------
891 * Following are functions for opaque type registration
892 * -----------------------------------------------------------
893 */
894
895int
896ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
897 u_char lsa_type, u_char opaque_type)
898{
899 struct registered_opaque_type *regtype;
900 int (*originator_func) (void *arg);
901 int rc;
902
903 switch (lsa_type)
904 {
905 case OSPF_OPAQUE_LINK_LSA:
906 originator_func = ospf_apiserver_lsa9_originator;
907 break;
908 case OSPF_OPAQUE_AREA_LSA:
909 originator_func = ospf_apiserver_lsa10_originator;
910 break;
911 case OSPF_OPAQUE_AS_LSA:
912 originator_func = ospf_apiserver_lsa11_originator;
913 break;
914 default:
915 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
916 lsa_type);
917 return OSPF_API_ILLEGALLSATYPE;
918 }
919
920
921 /* Register opaque function table */
922 /* NB: Duplicated registration will be detected inside the function. */
923 rc =
924 ospf_register_opaque_functab (lsa_type, opaque_type,
925 NULL, /* ospf_apiserver_new_if */
926 NULL, /* ospf_apiserver_del_if */
927 NULL, /* ospf_apiserver_ism_change */
928 NULL, /* ospf_apiserver_nsm_change */
929 NULL,
930 NULL,
931 NULL,
932 ospf_apiserver_show_info,
933 originator_func,
934 ospf_apiserver_lsa_refresher,
935 NULL, /* ospf_apiserver_lsa_update */
936 NULL /* ospf_apiserver_lsa_delete */);
937
938 if (rc != 0)
939 {
940 zlog_warn ("Failed to register opaque type [%d/%d]",
941 lsa_type, opaque_type);
942 return OSPF_API_OPAQUETYPEINUSE;
943 }
944
945 /* Remember the opaque type that application registers so when
946 connection shuts down, we can flush all LSAs of this opaque
947 type. */
948
949 regtype =
950 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
951 memset (regtype, 0, sizeof (struct registered_opaque_type));
952 regtype->lsa_type = lsa_type;
953 regtype->opaque_type = opaque_type;
954
955 /* Add to list of registered opaque types */
956 listnode_add (apiserv->opaque_types, regtype);
957
958 if (IS_DEBUG_OSPF_EVENT)
959 zlog_info ("API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)", lsa_type, opaque_type, apiserv, listcount (apiserv->opaque_types));
960
961 return 0;
962}
963
964int
965ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
966 u_char lsa_type, u_char opaque_type)
967{
968 listnode node;
969
970 for (node = listhead (apiserv->opaque_types); node; nextnode (node))
971 {
972 struct registered_opaque_type *regtype = node->data;
973
974 /* Check if we really registered this opaque type */
975 if (regtype->lsa_type == lsa_type &&
976 regtype->opaque_type == opaque_type)
977 {
978
979 /* Yes, we registered this opaque type. Flush
980 all existing opaque LSAs of this type */
981
982 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
983 ospf_delete_opaque_functab (lsa_type, opaque_type);
984
985 /* Remove from list of registered opaque types */
986 listnode_delete (apiserv->opaque_types, regtype);
987
988 if (IS_DEBUG_OSPF_EVENT)
989 zlog_info ("API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)", lsa_type, opaque_type, apiserv, listcount (apiserv->opaque_types));
990
991 return 0;
992 }
993 }
994
995 /* Opaque type is not registered */
996 zlog_warn ("Failed to unregister opaque type [%d/%d]",
997 lsa_type, opaque_type);
998 return OSPF_API_OPAQUETYPENOTREGISTERED;
999}
1000
1001
1002int
1003apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
1004 u_char lsa_type, u_char opaque_type)
1005{
1006 listnode node;
1007
1008 for (node = listhead (apiserv->opaque_types); node; nextnode (node))
1009 {
1010 struct registered_opaque_type *regtype = node->data;
1011
1012 /* Check if we really registered this opaque type */
1013 if (regtype->lsa_type == lsa_type &&
1014 regtype->opaque_type == opaque_type)
1015 {
1016 /* Yes registered */
1017 return 1;
1018 }
1019 }
1020 /* Not registered */
1021 return 0;
1022}
1023
1024int
1025ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1026 struct msg *msg)
1027{
1028 struct msg_register_opaque_type *rmsg;
1029 u_char lsa_type;
1030 u_char opaque_type;
1031 int rc = 0;
1032
1033 /* Extract parameters from register opaque type message */
1034 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1035
1036 lsa_type = rmsg->lsatype;
1037 opaque_type = rmsg->opaquetype;
1038
1039 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1040
1041 /* Send a reply back to client including return code */
1042 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1043 if (rc < 0)
1044 goto out;
1045
1046 /* Now inform application about opaque types that are ready */
1047 switch (lsa_type)
1048 {
1049 case OSPF_OPAQUE_LINK_LSA:
1050 ospf_apiserver_notify_ready_type9 (apiserv);
1051 break;
1052 case OSPF_OPAQUE_AREA_LSA:
1053 ospf_apiserver_notify_ready_type10 (apiserv);
1054 break;
1055 case OSPF_OPAQUE_AS_LSA:
1056 ospf_apiserver_notify_ready_type11 (apiserv);
1057 break;
1058 }
1059out:
1060 return rc;
1061}
1062
1063
1064/* Notify specific client about all opaque types 9 that are ready. */
1065void
1066ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1067{
1068 listnode node;
1069 listnode n2;
paul99b7c5d2003-04-06 01:19:28 +00001070 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001071
paul99b7c5d2003-04-06 01:19:28 +00001072 ospf = ospf_lookup ();
1073
1074 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00001075 {
1076 struct ospf_interface *oi = (struct ospf_interface *) getdata (node);
1077
1078 /* Check if this interface is indeed ready for type 9 */
1079 if (!ospf_apiserver_is_ready_type9 (oi))
1080 continue;
1081
1082 /* Check for registered opaque type 9 types */
1083 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1084 {
1085 struct registered_opaque_type *r =
1086 (struct registered_opaque_type *) getdata (n2);
1087 struct msg *msg;
1088
1089 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1090 {
1091
1092 /* Yes, this opaque type is ready */
1093 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1094 r->opaque_type,
1095 oi->address->u.prefix4);
1096 if (!msg)
1097 {
1098 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1099#ifdef NOTYET
1100 /* Cannot allocate new message. What should we do? */
1101 ospf_apiserver_free (apiserv);
1102#endif
1103 goto out;
1104 }
1105 ospf_apiserver_send_msg (apiserv, msg);
1106 msg_free (msg);
1107 }
1108 }
1109 }
1110
1111out:
1112 return;
1113}
1114
1115
1116/* Notify specific client about all opaque types 10 that are ready. */
1117void
1118ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1119{
1120 listnode node;
1121 listnode n2;
paul99b7c5d2003-04-06 01:19:28 +00001122 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001123
paul99b7c5d2003-04-06 01:19:28 +00001124 ospf = ospf_lookup ();
1125
1126 for (node = listhead (ospf->areas); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00001127 {
1128 struct ospf_area *area = getdata (node);
1129
1130 if (!ospf_apiserver_is_ready_type10 (area))
1131 {
1132 continue;
1133 }
1134
1135 /* Check for registered opaque type 10 types */
1136 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1137 {
1138 struct registered_opaque_type *r =
1139 (struct registered_opaque_type *) getdata (n2);
1140 struct msg *msg;
1141
1142 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1143 {
1144 /* Yes, this opaque type is ready */
1145 msg =
1146 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1147 r->opaque_type, area->area_id);
1148 if (!msg)
1149 {
1150 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1151#ifdef NOTYET
1152 /* Cannot allocate new message. What should we do? */
1153 ospf_apiserver_free (apiserv);
1154#endif
1155 goto out;
1156 }
1157 ospf_apiserver_send_msg (apiserv, msg);
1158 msg_free (msg);
1159 }
1160 }
1161 }
1162
1163out:
1164 return;
1165}
1166
1167/* Notify specific client about all opaque types 11 that are ready */
1168void
1169ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1170{
1171 listnode n2;
paul99b7c5d2003-04-06 01:19:28 +00001172 struct ospf *ospf;
1173
1174 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001175
1176 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001177 if (!ospf_apiserver_is_ready_type11 (ospf))
paul2d33f152003-03-17 01:10:58 +00001178 goto out;;
1179
1180 /* Check for registered opaque type 11 types */
1181 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1182 {
1183 struct registered_opaque_type *r =
1184 (struct registered_opaque_type *) getdata (n2);
1185 struct msg *msg;
1186 struct in_addr noarea_id = { 0L };
1187
1188 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1189 {
1190 /* Yes, this opaque type is ready */
1191 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1192 r->opaque_type, noarea_id);
1193
1194 if (!msg)
1195 {
1196 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1197#ifdef NOTYET
1198 /* Cannot allocate new message. What should we do? */
1199 ospf_apiserver_free (apiserv);
1200#endif
1201 goto out;
1202 }
1203 ospf_apiserver_send_msg (apiserv, msg);
1204 msg_free (msg);
1205 }
1206 }
1207
1208out:
1209 return;
1210}
1211
1212int
1213ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1214 struct msg *msg)
1215{
1216 struct msg_unregister_opaque_type *umsg;
1217 u_char ltype;
1218 u_char otype;
1219 int rc = 0;
1220
1221 /* Extract parameters from unregister opaque type message */
1222 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1223
1224 ltype = umsg->lsatype;
1225 otype = umsg->opaquetype;
1226
1227 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1228
1229 /* Send a reply back to client including return code */
1230 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1231
1232 return rc;
1233}
1234
1235
1236/* -----------------------------------------------------------
1237 * Following are functions for event (filter) registration.
1238 * -----------------------------------------------------------
1239 */
1240int
1241ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1242 struct msg *msg)
1243{
1244 struct msg_register_event *rmsg;
1245 int rc;
1246 u_int32_t seqnum;
1247
1248 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1249
1250 /* Get request sequence number */
1251 seqnum = msg_get_seq (msg);
1252
1253 /* Free existing filter in apiserv. */
1254 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1255 /* Alloc new space for filter. */
1256
1257 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1258 ntohs (msg->hdr.msglen));
1259 if (apiserv->filter)
1260 {
1261 /* copy it over. */
1262 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1263 rc = OSPF_API_OK;
1264 }
1265 else
1266 {
1267 rc = OSPF_API_NOMEMORY;
1268 }
1269 /* Send a reply back to client with return code */
1270 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1271 return rc;
1272}
1273
1274
1275/* -----------------------------------------------------------
1276 * Followings are functions for LSDB synchronization.
1277 * -----------------------------------------------------------
1278 */
1279
1280int
1281apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1282{
1283 struct ospf_apiserver *apiserv;
1284 int seqnum;
1285 struct msg *msg;
1286 struct param_t
1287 {
1288 struct ospf_apiserver *apiserv;
1289 struct lsa_filter_type *filter;
1290 }
1291 *param;
1292 int rc = -1;
1293
1294 /* Sanity check */
1295 assert (lsa->data);
1296 assert (p_arg);
1297
1298 param = (struct param_t *) p_arg;
1299 apiserv = param->apiserv;
1300 seqnum = (u_int32_t) int_arg;
1301
1302 /* Check origin in filter. */
1303 if ((param->filter->origin == ANY_ORIGIN) ||
1304 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1305 {
1306
1307 /* Default area for AS-External and Opaque11 LSAs */
1308 struct in_addr area_id = { 0L };
1309
1310 /* Default interface for non Opaque9 LSAs */
1311 struct in_addr ifaddr = { 0L };
1312
1313 if (lsa->area)
1314 {
1315 area_id = lsa->area->area_id;
1316 }
1317 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1318 {
1319 ifaddr = lsa->oi->address->u.prefix4;
1320 }
1321
1322 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1323 seqnum,
1324 ifaddr, area_id,
1325 lsa->flags & OSPF_LSA_SELF, lsa->data);
1326 if (!msg)
1327 {
1328 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1329#ifdef NOTYET
1330 /* Cannot allocate new message. What should we do? */
1331/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1332#endif
1333 goto out;
1334 }
1335
1336 /* Send LSA */
1337 ospf_apiserver_send_msg (apiserv, msg);
1338 msg_free (msg);
1339 }
1340 rc = 0;
1341
1342out:
1343 return rc;
1344}
1345
1346int
1347ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1348 struct msg *msg)
1349{
1350 listnode node;
1351 u_int32_t seqnum;
1352 int rc = 0;
1353 struct msg_sync_lsdb *smsg;
1354 struct param_t
1355 {
1356 struct ospf_apiserver *apiserv;
1357 struct lsa_filter_type *filter;
1358 }
1359 param;
1360 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001361 struct route_node *rn;
1362 struct ospf_lsa *lsa;
1363 struct ospf *ospf;
1364
1365 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001366
1367 /* Get request sequence number */
1368 seqnum = msg_get_seq (msg);
1369 /* Set sync msg. */
1370 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1371
1372 /* Set parameter struct. */
1373 param.apiserv = apiserv;
1374 param.filter = &smsg->filter;
1375
1376 /* Remember mask. */
1377 mask = ntohs (smsg->filter.typemask);
1378
1379 /* Iterate over all areas. */
paul99b7c5d2003-04-06 01:19:28 +00001380 for (node = listhead (ospf->areas); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +00001381 {
1382 struct ospf_area *area = node->data;
1383 int i;
1384 u_int32_t *area_id = NULL;
1385 /* Compare area_id with area_ids in sync request. */
1386 if ((i = smsg->filter.num_areas) > 0)
1387 {
1388 /* Let area_id point to the list of area IDs,
1389 * which is at the end of smsg->filter. */
1390 area_id = (u_int32_t *) (&smsg->filter + 1);
1391 while (i)
1392 {
1393 if (*area_id == area->area_id.s_addr)
1394 {
1395 break;
1396 }
1397 i--;
1398 area_id++;
1399 }
1400 }
1401 else
1402 {
1403 i = 1;
1404 }
1405
1406 /* If area was found, then i>0 here. */
1407 if (i)
1408 {
1409 /* Check msg type. */
1410 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001411 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1412 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001413 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001414 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1415 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001416 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001417 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1418 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001419 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001420 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1421 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001422 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001423 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1424 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001425 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001426 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1427 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001428 }
1429 }
1430
1431 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001432 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001433 {
1434 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001435 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1436 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001437 }
1438
1439 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001440 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001441 {
1442 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001443 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1444 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001445 }
1446
1447 /* Send a reply back to client with return code */
1448 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1449 return rc;
1450}
1451
1452
1453/* -----------------------------------------------------------
1454 * Followings are functions to originate or update LSA
1455 * from an application.
1456 * -----------------------------------------------------------
1457 */
1458
1459/* Create a new internal opaque LSA by taking prototype and filling in
1460 missing fields such as age, sequence number, advertising router,
1461 checksum and so on. The interface parameter is used for type 9
1462 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1463 nor interface. */
1464
1465struct ospf_lsa *
1466ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1467 struct ospf_interface *oi,
1468 struct lsa_header *protolsa)
1469{
1470 struct stream *s;
1471 struct lsa_header *newlsa;
1472 struct ospf_lsa *new = NULL;
1473 u_char options = 0x0;
1474 u_int16_t length;
1475
paul99b7c5d2003-04-06 01:19:28 +00001476 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001477
paul99b7c5d2003-04-06 01:19:28 +00001478 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001479 assert(ospf);
1480
paul2d33f152003-03-17 01:10:58 +00001481 /* Create a stream for internal opaque LSA */
1482 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1483 {
1484 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1485 return NULL;
1486 }
1487
1488 newlsa = (struct lsa_header *) STREAM_DATA (s);
1489
1490 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1491 have to set options? */
1492
1493 if (area)
1494 {
1495 options = LSA_OPTIONS_GET (area);
1496#ifdef HAVE_NSSA
1497 options |= LSA_NSSA_GET (area);
1498#endif /* HAVE_NSSA */
1499 }
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