blob: 20bf6a50aeec04facbe9a302a61d545b13a6fb65 [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;
paul2d33f152003-03-17 01:10:58 +000088
paul7d5e2682003-04-05 19:41:07 +000089 for (node = listhead (ospf_top->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +000090 {
91 if ((oi = getdata (node)) != NULL
92 && oi->type != OSPF_IFTYPE_VIRTUALLINK)
93 {
94 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
95 return oi;
96 }
97 }
98 return NULL;
99}
100
101struct ospf_interface *
102ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
103{
104 listnode node;
105 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +0000106
paul7d5e2682003-04-05 19:41:07 +0000107 for (node = listhead (ospf_top->oiflist); node; nextnode (node))
paul2d33f152003-03-17 01:10:58 +0000108 {
109 if ((oi = getdata (node)) && oi->ifp == ifp)
110 {
111 return oi;
112 }
113 }
114 return NULL;
115}
116
117/* -----------------------------------------------------------
118 * Initialization
119 * -----------------------------------------------------------
120 */
121
122unsigned short
123ospf_apiserver_getport (void)
124{
125 struct servent *sp = getservbyname ("ospfapi", "tcp");
126
127 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
128}
129
130/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
131int
132ospf_apiserver_init (void)
133{
134 int fd;
135 int rc = -1;
136
137 /* Create new socket for synchronous messages. */
138 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
139
140 if (fd < 0)
141 goto out;
142
143 /* Schedule new thread that handles accepted connections. */
144 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
145
146 /* Initialize list that keeps track of all connections. */
147 apiserver_list = list_new ();
148
149 /* Register opaque-independent call back functions. These functions
150 are invoked on ISM, NSM changes and LSA update and LSA deletes */
151 rc =
152 ospf_register_opaque_functab (0 /* all LSAs */,
153 0 /* all opaque types */,
154 ospf_apiserver_new_if,
155 ospf_apiserver_del_if,
156 ospf_apiserver_ism_change,
157 ospf_apiserver_nsm_change,
158 NULL,
159 NULL,
160 NULL,
161 NULL, /* ospf_apiserver_show_info */
162 NULL, /* originator_func */
163 NULL, /* ospf_apiserver_lsa_refresher */
164 ospf_apiserver_lsa_update,
165 ospf_apiserver_lsa_delete);
166 if (rc != 0)
167 {
168 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
169 }
170
171 rc = 0;
172
173out:
174 return rc;
175}
176
177/* Terminate OSPF API module. */
178void
179ospf_apiserver_term (void)
180{
181 listnode node;
182
183 /* Unregister wildcard [0/0] type */
184 ospf_delete_opaque_functab (0 /* all LSAs */,
185 0 /* all opaque types */);
186
187 /* Free all client instances */
188 for (node = listhead (apiserver_list); node; nextnode (node))
189 {
190 struct ospf_apiserver *apiserv =
191 (struct ospf_apiserver *) getdata (node);
192 ospf_apiserver_free (apiserv);
193 }
194
195 /* Free client list itself */
196 list_delete (apiserver_list);
197
198 /* Free wildcard list */
199 /* XXX */
200}
201
202static struct ospf_apiserver *
203lookup_apiserver (u_char lsa_type, u_char opaque_type)
204{
205 listnode n1, n2;
206 struct registered_opaque_type *r;
207 struct ospf_apiserver *apiserv, *found = NULL;
208
209 for (n1 = listhead (apiserver_list); n1; nextnode (n1))
210 {
211 apiserv = (struct ospf_apiserver *) getdata (n1);
212
213 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
214 {
215 r = (struct registered_opaque_type *) getdata (n2);
216
217 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
218 {
219 found = apiserv;
220 goto out;
221 }
222 }
223 }
224out:
225 return found;
226}
227
228static struct ospf_apiserver *
229lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
230{
231 struct lsa_header *lsah = lsa->data;
232 struct ospf_apiserver *found = NULL;
233
234 if (IS_OPAQUE_LSA (lsah->type))
235 {
236 found = lookup_apiserver (lsah->type,
237 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
238 }
239 return found;
240}
241
242/* -----------------------------------------------------------
243 * Followings are functions to manage client connections.
244 * -----------------------------------------------------------
245 */
246static int
247ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
248{
249 if (IS_DEBUG_OSPF_EVENT)
250 zlog_info ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
251 return 0;
252}
253
254static int
255ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
256{
257 if (IS_DEBUG_OSPF_EVENT)
258 zlog_info ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
259 return 0;
260}
261
262/* Allocate new connection structure. */
263struct ospf_apiserver *
264ospf_apiserver_new (int fd_sync, int fd_async)
265{
266 struct ospf_apiserver *new =
267 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
268
269 new->filter =
270 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
271
272 new->fd_sync = fd_sync;
273 new->fd_async = fd_async;
274
275 /* list of registered opaque types that application uses */
276 new->opaque_types = list_new ();
277
278 /* Initialize temporary strage for LSA instances to be refreshed. */
279 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
280 ospf_lsdb_init (&new->reserve);
281
282 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
283 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
284
285 new->out_sync_fifo = msg_fifo_new ();
286 new->out_async_fifo = msg_fifo_new ();
287 new->t_sync_read = NULL;
288#ifdef USE_ASYNC_READ
289 new->t_async_read = NULL;
290#endif /* USE_ASYNC_READ */
291 new->t_sync_write = NULL;
292 new->t_async_write = NULL;
293
294 new->filter->typemask = 0; /* filter all LSAs */
295 new->filter->origin = ANY_ORIGIN;
296 new->filter->num_areas = 0;
297
298 return new;
299}
300
301void
302ospf_apiserver_event (enum event event, int fd,
303 struct ospf_apiserver *apiserv)
304{
305 struct thread *apiserver_serv_thread;
306
307 switch (event)
308 {
309 case OSPF_APISERVER_ACCEPT:
310 apiserver_serv_thread =
311 thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
312 break;
313 case OSPF_APISERVER_SYNC_READ:
314 apiserv->t_sync_read =
315 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
316 break;
317#ifdef USE_ASYNC_READ
318 case OSPF_APISERVER_ASYNC_READ:
319 apiserv->t_async_read =
320 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
321 break;
322#endif /* USE_ASYNC_READ */
323 case OSPF_APISERVER_SYNC_WRITE:
324 if (!apiserv->t_sync_write)
325 {
326 apiserv->t_sync_write =
327 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
328 }
329 break;
330 case OSPF_APISERVER_ASYNC_WRITE:
331 if (!apiserv->t_async_write)
332 {
333 apiserv->t_async_write =
334 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
335 }
336 break;
337 }
338}
339
340/* Free instance. First unregister all opaque types used by
341 application, flush opaque LSAs injected by application
342 from network and close connection. */
343void
344ospf_apiserver_free (struct ospf_apiserver *apiserv)
345{
346 listnode node;
347
348 /* Cancel read and write threads. */
349 if (apiserv->t_sync_read)
350 {
351 thread_cancel (apiserv->t_sync_read);
352 }
353#ifdef USE_ASYNC_READ
354 if (apiserv->t_async_read)
355 {
356 thread_cancel (apiserv->t_async_read);
357 }
358#endif /* USE_ASYNC_READ */
359 if (apiserv->t_sync_write)
360 {
361 thread_cancel (apiserv->t_sync_write);
362 }
363
364 if (apiserv->t_async_write)
365 {
366 thread_cancel (apiserv->t_async_write);
367 }
368
369 /* Unregister all opaque types that application registered
370 and flush opaque LSAs if still in LSDB. */
371
372 while ((node = listhead (apiserv->opaque_types)) != NULL)
373 {
374
375 struct registered_opaque_type *regtype = node->data;
376
377 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
378 regtype->opaque_type);
379
380 }
381
382 /* Close connections to OSPFd. */
383 if (apiserv->fd_sync > 0)
384 {
385 close (apiserv->fd_sync);
386 }
387
388 if (apiserv->fd_async > 0)
389 {
390 close (apiserv->fd_async);
391 }
392
393 /* Free fifos */
394 msg_fifo_free (apiserv->out_sync_fifo);
395 msg_fifo_free (apiserv->out_async_fifo);
396
397 /* Clear temporary strage for LSA instances to be refreshed. */
398 ospf_lsdb_delete_all (&apiserv->reserve);
399 ospf_lsdb_cleanup (&apiserv->reserve);
400
401 /* Remove from the list of active clients. */
402 listnode_delete (apiserver_list, apiserv);
403
404 if (IS_DEBUG_OSPF_EVENT)
405 zlog_info ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
406
407 /* And free instance. */
408 XFREE (MTYPE_OSPF_APISERVER, apiserv);
409}
410
411int
412ospf_apiserver_read (struct thread *thread)
413{
414 struct ospf_apiserver *apiserv;
415 struct msg *msg;
416 int fd;
417 int rc = -1;
418 enum event event;
419
420 apiserv = THREAD_ARG (thread);
421 fd = THREAD_FD (thread);
422
423 if (fd == apiserv->fd_sync)
424 {
425 event = OSPF_APISERVER_SYNC_READ;
426 apiserv->t_sync_read = NULL;
427
428 if (IS_DEBUG_OSPF_EVENT)
429 zlog_info ("API: ospf_apiserver_read: Peer: %s/%u",
430 inet_ntoa (apiserv->peer_sync.sin_addr),
431 ntohs (apiserv->peer_sync.sin_port));
432 }
433#ifdef USE_ASYNC_READ
434 else if (fd == apiserv->fd_async)
435 {
436 event = OSPF_APISERVER_ASYNC_READ;
437 apiserv->t_async_read = NULL;
438
439 if (IS_DEBUG_OSPF_EVENT)
440 zlog_info ("API: ospf_apiserver_read: Peer: %s/%u",
441 inet_ntoa (apiserv->peer_async.sin_addr),
442 ntohs (apiserv->peer_async.sin_port));
443 }
444#endif /* USE_ASYNC_READ */
445 else
446 {
447 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
448 ospf_apiserver_free (apiserv);
449 goto out;
450 }
451
452 /* Read message from fd. */
453 msg = msg_read (fd);
454 if (msg == NULL)
455 {
456 zlog_warn
457 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
458
459 /* Perform cleanup. */
460 ospf_apiserver_free (apiserv);
461 goto out;
462 }
463
464 if (IS_DEBUG_OSPF_EVENT)
465 msg_print (msg);
466
467 /* Dispatch to corresponding message handler. */
468 rc = ospf_apiserver_handle_msg (apiserv, msg);
469
470 /* Prepare for next message, add read thread. */
471 ospf_apiserver_event (event, fd, apiserv);
472
473 msg_free (msg);
474
475out:
476 return rc;
477}
478
479int
480ospf_apiserver_sync_write (struct thread *thread)
481{
482 struct ospf_apiserver *apiserv;
483 struct msg *msg;
484 int fd;
485 int rc = -1;
486
487 apiserv = THREAD_ARG (thread);
488 assert (apiserv);
489 fd = THREAD_FD (thread);
490
491 apiserv->t_sync_write = NULL;
492
493 /* Sanity check */
494 if (fd != apiserv->fd_sync)
495 {
496 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
497 goto out;
498 }
499
500 if (IS_DEBUG_OSPF_EVENT)
501 zlog_info ("API: ospf_apiserver_sync_write: Peer: %s/%u",
502 inet_ntoa (apiserv->peer_sync.sin_addr),
503 ntohs (apiserv->peer_sync.sin_port));
504
505 /* Check whether there is really a message in the fifo. */
506 msg = msg_fifo_pop (apiserv->out_sync_fifo);
507 if (!msg)
508 {
509 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
510 return 0;
511 }
512
513 if (IS_DEBUG_OSPF_EVENT)
514 msg_print (msg);
515
516 rc = msg_write (fd, msg);
517
518 /* Once a message is dequeued, it should be freed anyway. */
519 msg_free (msg);
520
521 if (rc < 0)
522 {
523 zlog_warn
524 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
525 goto out;
526 }
527
528
529 /* If more messages are in sync message fifo, schedule write thread. */
530 if (msg_fifo_head (apiserv->out_sync_fifo))
531 {
532 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
533 apiserv);
534 }
535
536 out:
537
538 if (rc < 0)
539 {
540 /* Perform cleanup and disconnect with peer */
541 ospf_apiserver_free (apiserv);
542 }
543
544 return rc;
545}
546
547
548int
549ospf_apiserver_async_write (struct thread *thread)
550{
551 struct ospf_apiserver *apiserv;
552 struct msg *msg;
553 int fd;
554 int rc = -1;
555
556 apiserv = THREAD_ARG (thread);
557 assert (apiserv);
558 fd = THREAD_FD (thread);
559
560 apiserv->t_async_write = NULL;
561
562 /* Sanity check */
563 if (fd != apiserv->fd_async)
564 {
565 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
566 goto out;
567 }
568
569 if (IS_DEBUG_OSPF_EVENT)
570 zlog_info ("API: ospf_apiserver_async_write: Peer: %s/%u",
571 inet_ntoa (apiserv->peer_async.sin_addr),
572 ntohs (apiserv->peer_async.sin_port));
573
574 /* Check whether there is really a message in the fifo. */
575 msg = msg_fifo_pop (apiserv->out_async_fifo);
576 if (!msg)
577 {
578 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
579 return 0;
580 }
581
582 if (IS_DEBUG_OSPF_EVENT)
583 msg_print (msg);
584
585 rc = msg_write (fd, msg);
586
587 /* Once a message is dequeued, it should be freed anyway. */
588 msg_free (msg);
589
590 if (rc < 0)
591 {
592 zlog_warn
593 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
594 goto out;
595 }
596
597
598 /* If more messages are in async message fifo, schedule write thread. */
599 if (msg_fifo_head (apiserv->out_async_fifo))
600 {
601 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
602 apiserv);
603 }
604
605 out:
606
607 if (rc < 0)
608 {
609 /* Perform cleanup and disconnect with peer */
610 ospf_apiserver_free (apiserv);
611 }
612
613 return rc;
614}
615
616
617int
618ospf_apiserver_serv_sock_family (unsigned short port, int family)
619{
620 union sockunion su;
621 int accept_sock;
622 int rc;
623
624 memset (&su, 0, sizeof (union sockunion));
625 su.sa.sa_family = family;
626
627 /* Make new socket */
628 accept_sock = sockunion_stream_socket (&su);
629 if (accept_sock < 0)
630 return accept_sock;
631
632 /* This is a server, so reuse address and port */
633 sockopt_reuseaddr (accept_sock);
634 sockopt_reuseport (accept_sock);
635
636 /* Bind socket to address and given port. */
637 rc = sockunion_bind (accept_sock, &su, port, NULL);
638 if (rc < 0)
639 {
640 close (accept_sock); /* Close socket */
641 return rc;
642 }
643
644 /* Listen socket under queue length 3. */
645 rc = listen (accept_sock, 3);
646 if (rc < 0)
647 {
648 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
649 strerror (errno));
650 close (accept_sock); /* Close socket */
651 return rc;
652 }
653 return accept_sock;
654}
655
656
657/* Accept connection request from external applications. For each
658 accepted connection allocate own connection instance. */
659int
660ospf_apiserver_accept (struct thread *thread)
661{
662 int accept_sock;
663 int new_sync_sock;
664 int new_async_sock;
665 union sockunion su;
666 struct ospf_apiserver *apiserv;
667 struct sockaddr_in peer_async;
668 struct sockaddr_in peer_sync;
669 int peerlen;
670 int ret;
671
672 /* THREAD_ARG (thread) is NULL */
673 accept_sock = THREAD_FD (thread);
674
675 /* Keep hearing on socket for further connections. */
676 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
677
678 memset (&su, 0, sizeof (union sockunion));
679 /* Accept connection for synchronous messages */
680 new_sync_sock = sockunion_accept (accept_sock, &su);
681 if (new_sync_sock < 0)
682 {
683 zlog_warn ("ospf_apiserver_accept: accept: %s", strerror (errno));
684 return -1;
685 }
686
687 /* Get port address and port number of peer to make reverse connection.
688 The reverse channel uses the port number of the peer port+1. */
689
690 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
691 peerlen = sizeof (struct sockaddr_in);
692
693 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
694 if (ret < 0)
695 {
696 zlog_warn ("ospf_apiserver_accept: getpeername: %s", strerror (errno));
697 close (new_sync_sock);
698 return -1;
699 }
700
701 if (IS_DEBUG_OSPF_EVENT)
702 zlog_info ("API: ospf_apiserver_accept: New peer: %s/%u",
703 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
704
705 /* Create new socket for asynchronous messages. */
706 peer_async = peer_sync;
707 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
708
709 /* Check if remote port number to make reverse connection is valid one. */
710 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
711 {
712 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
713 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
714 close (new_sync_sock);
715 return -1;
716 }
717
718 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
719 if (new_async_sock < 0)
720 {
721 zlog_warn ("ospf_apiserver_accept: socket: %s", strerror (errno));
722 close (new_sync_sock);
723 return -1;
724 }
725
726 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
727 sizeof (struct sockaddr_in));
728
729 if (ret < 0)
730 {
731 zlog_warn ("ospf_apiserver_accept: connect: %s", strerror (errno));
732 close (new_sync_sock);
733 close (new_async_sock);
734 return -1;
735 }
736
737#ifdef USE_ASYNC_READ
738#else /* USE_ASYNC_READ */
739 /* Make the asynchronous channel write-only. */
740 ret = shutdown (new_async_sock, SHUT_RD);
741 if (ret < 0)
742 {
743 zlog_warn ("ospf_apiserver_accept: shutdown: %s", strerror (errno));
744 close (new_sync_sock);
745 close (new_async_sock);
746 return -1;
747 }
748#endif /* USE_ASYNC_READ */
749
750 /* Allocate new server-side connection structure */
751 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
752
753 /* Add to active connection list */
754 listnode_add (apiserver_list, apiserv);
755 apiserv->peer_sync = peer_sync;
756 apiserv->peer_async = peer_async;
757
758 /* And add read threads for new connection */
759 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
760#ifdef USE_ASYNC_READ
761 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
762#endif /* USE_ASYNC_READ */
763
764 if (IS_DEBUG_OSPF_EVENT)
765 zlog_warn ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
766
767 return 0;
768}
769
770
771/* -----------------------------------------------------------
772 * Send reply with return code to client application
773 * -----------------------------------------------------------
774 */
775
776int
777ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
778{
779 struct msg_fifo *fifo;
780 struct msg *msg2;
781 enum event event;
782 int fd;
783
784 switch (msg->hdr.msgtype)
785 {
786 case MSG_REPLY:
787 fifo = apiserv->out_sync_fifo;
788 fd = apiserv->fd_sync;
789 event = OSPF_APISERVER_SYNC_WRITE;
790 break;
791 case MSG_READY_NOTIFY:
792 case MSG_LSA_UPDATE_NOTIFY:
793 case MSG_LSA_DELETE_NOTIFY:
794 case MSG_NEW_IF:
795 case MSG_DEL_IF:
796 case MSG_ISM_CHANGE:
797 case MSG_NSM_CHANGE:
798 fifo = apiserv->out_async_fifo;
799 fd = apiserv->fd_async;
800 event = OSPF_APISERVER_ASYNC_WRITE;
801 break;
802 default:
803 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
804 msg->hdr.msgtype);
805 return -1;
806 }
807
808 /* Make a copy of the message and put in the fifo. Once the fifo
809 gets drained by the write thread, the message will be freed. */
810 /* NB: Given "msg" is untouched in this function. */
811 msg2 = msg_dup (msg);
812
813 /* Enqueue message into corresponding fifo queue */
814 msg_fifo_push (fifo, msg2);
815
816 /* Schedule write thread */
817 ospf_apiserver_event (event, fd, apiserv);
818 return 0;
819}
820
821int
822ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
823 u_char rc)
824{
825 struct msg *msg = new_msg_reply (seqnr, rc);
826 int ret;
827
828 if (!msg)
829 {
830 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
831#ifdef NOTYET
832 /* Cannot allocate new message. What should we do? */
833 ospf_apiserver_free (apiserv);
834#endif
835 return -1;
836 }
837
838 ret = ospf_apiserver_send_msg (apiserv, msg);
839 msg_free (msg);
840 return ret;
841}
842
843
844/* -----------------------------------------------------------
845 * Generic message dispatching handler function
846 * -----------------------------------------------------------
847 */
848
849int
850ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
851{
852 int rc;
853
854 /* Call corresponding message handler function. */
855 switch (msg->hdr.msgtype)
856 {
857 case MSG_REGISTER_OPAQUETYPE:
858 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
859 break;
860 case MSG_UNREGISTER_OPAQUETYPE:
861 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
862 break;
863 case MSG_REGISTER_EVENT:
864 rc = ospf_apiserver_handle_register_event (apiserv, msg);
865 break;
866 case MSG_SYNC_LSDB:
867 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
868 break;
869 case MSG_ORIGINATE_REQUEST:
870 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
871 break;
872 case MSG_DELETE_REQUEST:
873 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
874 break;
875 default:
876 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
877 msg->hdr.msgtype);
878 rc = -1;
879 }
880 return rc;
881}
882
883
884/* -----------------------------------------------------------
885 * Following are functions for opaque type registration
886 * -----------------------------------------------------------
887 */
888
889int
890ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
891 u_char lsa_type, u_char opaque_type)
892{
893 struct registered_opaque_type *regtype;
894 int (*originator_func) (void *arg);
895 int rc;
896
897 switch (lsa_type)
898 {
899 case OSPF_OPAQUE_LINK_LSA:
900 originator_func = ospf_apiserver_lsa9_originator;
901 break;
902 case OSPF_OPAQUE_AREA_LSA:
903 originator_func = ospf_apiserver_lsa10_originator;
904 break;
905 case OSPF_OPAQUE_AS_LSA:
906 originator_func = ospf_apiserver_lsa11_originator;
907 break;
908 default:
909 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
910 lsa_type);
911 return OSPF_API_ILLEGALLSATYPE;
912 }
913
914
915 /* Register opaque function table */
916 /* NB: Duplicated registration will be detected inside the function. */
917 rc =
918 ospf_register_opaque_functab (lsa_type, opaque_type,
919 NULL, /* ospf_apiserver_new_if */
920 NULL, /* ospf_apiserver_del_if */
921 NULL, /* ospf_apiserver_ism_change */
922 NULL, /* ospf_apiserver_nsm_change */
923 NULL,
924 NULL,
925 NULL,
926 ospf_apiserver_show_info,
927 originator_func,
928 ospf_apiserver_lsa_refresher,
929 NULL, /* ospf_apiserver_lsa_update */
930 NULL /* ospf_apiserver_lsa_delete */);
931
932 if (rc != 0)
933 {
934 zlog_warn ("Failed to register opaque type [%d/%d]",
935 lsa_type, opaque_type);
936 return OSPF_API_OPAQUETYPEINUSE;
937 }
938
939 /* Remember the opaque type that application registers so when
940 connection shuts down, we can flush all LSAs of this opaque
941 type. */
942
943 regtype =
944 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
945 memset (regtype, 0, sizeof (struct registered_opaque_type));
946 regtype->lsa_type = lsa_type;
947 regtype->opaque_type = opaque_type;
948
949 /* Add to list of registered opaque types */
950 listnode_add (apiserv->opaque_types, regtype);
951
952 if (IS_DEBUG_OSPF_EVENT)
953 zlog_info ("API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)", lsa_type, opaque_type, apiserv, listcount (apiserv->opaque_types));
954
955 return 0;
956}
957
958int
959ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
960 u_char lsa_type, u_char opaque_type)
961{
962 listnode node;
963
964 for (node = listhead (apiserv->opaque_types); node; nextnode (node))
965 {
966 struct registered_opaque_type *regtype = node->data;
967
968 /* Check if we really registered this opaque type */
969 if (regtype->lsa_type == lsa_type &&
970 regtype->opaque_type == opaque_type)
971 {
972
973 /* Yes, we registered this opaque type. Flush
974 all existing opaque LSAs of this type */
975
976 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
977 ospf_delete_opaque_functab (lsa_type, opaque_type);
978
979 /* Remove from list of registered opaque types */
980 listnode_delete (apiserv->opaque_types, regtype);
981
982 if (IS_DEBUG_OSPF_EVENT)
983 zlog_info ("API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)", lsa_type, opaque_type, apiserv, listcount (apiserv->opaque_types));
984
985 return 0;
986 }
987 }
988
989 /* Opaque type is not registered */
990 zlog_warn ("Failed to unregister opaque type [%d/%d]",
991 lsa_type, opaque_type);
992 return OSPF_API_OPAQUETYPENOTREGISTERED;
993}
994
995
996int
997apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
998 u_char lsa_type, u_char opaque_type)
999{
1000 listnode node;
1001
1002 for (node = listhead (apiserv->opaque_types); node; nextnode (node))
1003 {
1004 struct registered_opaque_type *regtype = node->data;
1005
1006 /* Check if we really registered this opaque type */
1007 if (regtype->lsa_type == lsa_type &&
1008 regtype->opaque_type == opaque_type)
1009 {
1010 /* Yes registered */
1011 return 1;
1012 }
1013 }
1014 /* Not registered */
1015 return 0;
1016}
1017
1018int
1019ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1020 struct msg *msg)
1021{
1022 struct msg_register_opaque_type *rmsg;
1023 u_char lsa_type;
1024 u_char opaque_type;
1025 int rc = 0;
1026
1027 /* Extract parameters from register opaque type message */
1028 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1029
1030 lsa_type = rmsg->lsatype;
1031 opaque_type = rmsg->opaquetype;
1032
1033 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1034
1035 /* Send a reply back to client including return code */
1036 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1037 if (rc < 0)
1038 goto out;
1039
1040 /* Now inform application about opaque types that are ready */
1041 switch (lsa_type)
1042 {
1043 case OSPF_OPAQUE_LINK_LSA:
1044 ospf_apiserver_notify_ready_type9 (apiserv);
1045 break;
1046 case OSPF_OPAQUE_AREA_LSA:
1047 ospf_apiserver_notify_ready_type10 (apiserv);
1048 break;
1049 case OSPF_OPAQUE_AS_LSA:
1050 ospf_apiserver_notify_ready_type11 (apiserv);
1051 break;
1052 }
1053out:
1054 return rc;
1055}
1056
1057
1058/* Notify specific client about all opaque types 9 that are ready. */
1059void
1060ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1061{
1062 listnode node;
1063 listnode n2;
1064
1065 for (node = listhead (ospf_top->oiflist); node; nextnode (node))
1066 {
1067 struct ospf_interface *oi = (struct ospf_interface *) getdata (node);
1068
1069 /* Check if this interface is indeed ready for type 9 */
1070 if (!ospf_apiserver_is_ready_type9 (oi))
1071 continue;
1072
1073 /* Check for registered opaque type 9 types */
1074 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1075 {
1076 struct registered_opaque_type *r =
1077 (struct registered_opaque_type *) getdata (n2);
1078 struct msg *msg;
1079
1080 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1081 {
1082
1083 /* Yes, this opaque type is ready */
1084 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1085 r->opaque_type,
1086 oi->address->u.prefix4);
1087 if (!msg)
1088 {
1089 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1090#ifdef NOTYET
1091 /* Cannot allocate new message. What should we do? */
1092 ospf_apiserver_free (apiserv);
1093#endif
1094 goto out;
1095 }
1096 ospf_apiserver_send_msg (apiserv, msg);
1097 msg_free (msg);
1098 }
1099 }
1100 }
1101
1102out:
1103 return;
1104}
1105
1106
1107/* Notify specific client about all opaque types 10 that are ready. */
1108void
1109ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1110{
1111 listnode node;
1112 listnode n2;
1113
1114 for (node = listhead (ospf_top->areas); node; nextnode (node))
1115 {
1116 struct ospf_area *area = getdata (node);
1117
1118 if (!ospf_apiserver_is_ready_type10 (area))
1119 {
1120 continue;
1121 }
1122
1123 /* Check for registered opaque type 10 types */
1124 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1125 {
1126 struct registered_opaque_type *r =
1127 (struct registered_opaque_type *) getdata (n2);
1128 struct msg *msg;
1129
1130 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1131 {
1132 /* Yes, this opaque type is ready */
1133 msg =
1134 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1135 r->opaque_type, area->area_id);
1136 if (!msg)
1137 {
1138 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1139#ifdef NOTYET
1140 /* Cannot allocate new message. What should we do? */
1141 ospf_apiserver_free (apiserv);
1142#endif
1143 goto out;
1144 }
1145 ospf_apiserver_send_msg (apiserv, msg);
1146 msg_free (msg);
1147 }
1148 }
1149 }
1150
1151out:
1152 return;
1153}
1154
1155/* Notify specific client about all opaque types 11 that are ready */
1156void
1157ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1158{
1159 listnode n2;
1160
1161 /* Can type 11 be originated? */
1162 if (!ospf_apiserver_is_ready_type11 (ospf_top))
1163 goto out;;
1164
1165 /* Check for registered opaque type 11 types */
1166 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
1167 {
1168 struct registered_opaque_type *r =
1169 (struct registered_opaque_type *) getdata (n2);
1170 struct msg *msg;
1171 struct in_addr noarea_id = { 0L };
1172
1173 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1174 {
1175 /* Yes, this opaque type is ready */
1176 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1177 r->opaque_type, noarea_id);
1178
1179 if (!msg)
1180 {
1181 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1182#ifdef NOTYET
1183 /* Cannot allocate new message. What should we do? */
1184 ospf_apiserver_free (apiserv);
1185#endif
1186 goto out;
1187 }
1188 ospf_apiserver_send_msg (apiserv, msg);
1189 msg_free (msg);
1190 }
1191 }
1192
1193out:
1194 return;
1195}
1196
1197int
1198ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1199 struct msg *msg)
1200{
1201 struct msg_unregister_opaque_type *umsg;
1202 u_char ltype;
1203 u_char otype;
1204 int rc = 0;
1205
1206 /* Extract parameters from unregister opaque type message */
1207 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1208
1209 ltype = umsg->lsatype;
1210 otype = umsg->opaquetype;
1211
1212 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1213
1214 /* Send a reply back to client including return code */
1215 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1216
1217 return rc;
1218}
1219
1220
1221/* -----------------------------------------------------------
1222 * Following are functions for event (filter) registration.
1223 * -----------------------------------------------------------
1224 */
1225int
1226ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1227 struct msg *msg)
1228{
1229 struct msg_register_event *rmsg;
1230 int rc;
1231 u_int32_t seqnum;
1232
1233 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1234
1235 /* Get request sequence number */
1236 seqnum = msg_get_seq (msg);
1237
1238 /* Free existing filter in apiserv. */
1239 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1240 /* Alloc new space for filter. */
1241
1242 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1243 ntohs (msg->hdr.msglen));
1244 if (apiserv->filter)
1245 {
1246 /* copy it over. */
1247 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1248 rc = OSPF_API_OK;
1249 }
1250 else
1251 {
1252 rc = OSPF_API_NOMEMORY;
1253 }
1254 /* Send a reply back to client with return code */
1255 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1256 return rc;
1257}
1258
1259
1260/* -----------------------------------------------------------
1261 * Followings are functions for LSDB synchronization.
1262 * -----------------------------------------------------------
1263 */
1264
1265int
1266apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1267{
1268 struct ospf_apiserver *apiserv;
1269 int seqnum;
1270 struct msg *msg;
1271 struct param_t
1272 {
1273 struct ospf_apiserver *apiserv;
1274 struct lsa_filter_type *filter;
1275 }
1276 *param;
1277 int rc = -1;
1278
1279 /* Sanity check */
1280 assert (lsa->data);
1281 assert (p_arg);
1282
1283 param = (struct param_t *) p_arg;
1284 apiserv = param->apiserv;
1285 seqnum = (u_int32_t) int_arg;
1286
1287 /* Check origin in filter. */
1288 if ((param->filter->origin == ANY_ORIGIN) ||
1289 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1290 {
1291
1292 /* Default area for AS-External and Opaque11 LSAs */
1293 struct in_addr area_id = { 0L };
1294
1295 /* Default interface for non Opaque9 LSAs */
1296 struct in_addr ifaddr = { 0L };
1297
1298 if (lsa->area)
1299 {
1300 area_id = lsa->area->area_id;
1301 }
1302 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1303 {
1304 ifaddr = lsa->oi->address->u.prefix4;
1305 }
1306
1307 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1308 seqnum,
1309 ifaddr, area_id,
1310 lsa->flags & OSPF_LSA_SELF, lsa->data);
1311 if (!msg)
1312 {
1313 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1314#ifdef NOTYET
1315 /* Cannot allocate new message. What should we do? */
1316/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1317#endif
1318 goto out;
1319 }
1320
1321 /* Send LSA */
1322 ospf_apiserver_send_msg (apiserv, msg);
1323 msg_free (msg);
1324 }
1325 rc = 0;
1326
1327out:
1328 return rc;
1329}
1330
1331int
1332ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1333 struct msg *msg)
1334{
1335 listnode node;
1336 u_int32_t seqnum;
1337 int rc = 0;
1338 struct msg_sync_lsdb *smsg;
1339 struct param_t
1340 {
1341 struct ospf_apiserver *apiserv;
1342 struct lsa_filter_type *filter;
1343 }
1344 param;
1345 u_int16_t mask;
1346
1347 /* Get request sequence number */
1348 seqnum = msg_get_seq (msg);
1349 /* Set sync msg. */
1350 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1351
1352 /* Set parameter struct. */
1353 param.apiserv = apiserv;
1354 param.filter = &smsg->filter;
1355
1356 /* Remember mask. */
1357 mask = ntohs (smsg->filter.typemask);
1358
1359 /* Iterate over all areas. */
1360 for (node = listhead (ospf_top->areas); node; nextnode (node))
1361 {
1362 struct ospf_area *area = node->data;
1363 int i;
1364 u_int32_t *area_id = NULL;
1365 /* Compare area_id with area_ids in sync request. */
1366 if ((i = smsg->filter.num_areas) > 0)
1367 {
1368 /* Let area_id point to the list of area IDs,
1369 * which is at the end of smsg->filter. */
1370 area_id = (u_int32_t *) (&smsg->filter + 1);
1371 while (i)
1372 {
1373 if (*area_id == area->area_id.s_addr)
1374 {
1375 break;
1376 }
1377 i--;
1378 area_id++;
1379 }
1380 }
1381 else
1382 {
1383 i = 1;
1384 }
1385
1386 /* If area was found, then i>0 here. */
1387 if (i)
1388 {
1389 /* Check msg type. */
1390 if (mask & Power2[OSPF_ROUTER_LSA])
1391 foreach_lsa (ROUTER_LSDB (area), (void *) &param, seqnum,
1392 apiserver_sync_callback);
1393 if (mask & Power2[OSPF_NETWORK_LSA])
1394 foreach_lsa (NETWORK_LSDB (area), (void *) &param, seqnum,
1395 apiserver_sync_callback);
1396 if (mask & Power2[OSPF_SUMMARY_LSA])
1397 foreach_lsa (SUMMARY_LSDB (area), (void *) &param, seqnum,
1398 apiserver_sync_callback);
1399 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
1400 foreach_lsa (ASBR_SUMMARY_LSDB (area), (void *) &param, seqnum,
1401 apiserver_sync_callback);
1402 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
1403 foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) &param,
1404 seqnum, apiserver_sync_callback);
1405 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
1406 foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) &param,
1407 seqnum, apiserver_sync_callback);
1408 }
1409 }
1410
1411 /* For AS-external LSAs */
1412 if (ospf_top->lsdb)
1413 {
1414 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
1415 foreach_lsa (EXTERNAL_LSDB (ospf_top), (void *) &param, seqnum,
1416 apiserver_sync_callback);
1417 }
1418
1419 /* For AS-external opaque LSAs */
1420 if (ospf_top->lsdb)
1421 {
1422 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
1423 foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) &param,
1424 seqnum, apiserver_sync_callback);
1425 }
1426
1427 /* Send a reply back to client with return code */
1428 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1429 return rc;
1430}
1431
1432
1433/* -----------------------------------------------------------
1434 * Followings are functions to originate or update LSA
1435 * from an application.
1436 * -----------------------------------------------------------
1437 */
1438
1439/* Create a new internal opaque LSA by taking prototype and filling in
1440 missing fields such as age, sequence number, advertising router,
1441 checksum and so on. The interface parameter is used for type 9
1442 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1443 nor interface. */
1444
1445struct ospf_lsa *
1446ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1447 struct ospf_interface *oi,
1448 struct lsa_header *protolsa)
1449{
1450 struct stream *s;
1451 struct lsa_header *newlsa;
1452 struct ospf_lsa *new = NULL;
1453 u_char options = 0x0;
1454 u_int16_t length;
1455
paul7d5e2682003-04-05 19:41:07 +00001456 struct ospf *ospf = ospf_top;
1457
1458#if 0
1459 struct ospf *ospf = NULL;
1460
1461 switch(protolsa->type)
1462 {
1463 case OSPF_OPAQUE_LINK_LSA:
1464 ospf = oi_to_top (oi); /* ospf_opaque.c */
1465 break;
1466 case OSPF_OPAQUE_AREA_LSA:
1467 ospf = area->ospf;
1468 break;
1469 case OSPF_OPAQUE_AS_LSA:
1470 ospf = ospf_top; /* XXX */
1471 break;
1472 }
1473#endif
1474
1475 assert(ospf);
1476
paul2d33f152003-03-17 01:10:58 +00001477 /* Create a stream for internal opaque LSA */
1478 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1479 {
1480 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1481 return NULL;
1482 }
1483
1484 newlsa = (struct lsa_header *) STREAM_DATA (s);
1485
1486 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1487 have to set options? */
1488
1489 if (area)
1490 {
1491 options = LSA_OPTIONS_GET (area);
1492#ifdef HAVE_NSSA
1493 options |= LSA_NSSA_GET (area);
1494#endif /* HAVE_NSSA */
1495 }
1496
1497 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1498
1499 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1500 {
1501 zlog_info ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1502 protolsa->type, inet_ntoa (protolsa->id));
1503 }
1504
1505 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001506 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001507 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001508
1509 /* Set opaque-LSA body fields. */
1510 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1511 ntohs (protolsa->length) - sizeof (struct lsa_header));
1512
1513 /* Determine length of LSA. */
1514 length = stream_get_endp (s);
1515 newlsa->length = htons (length);
1516
1517 /* Create OSPF LSA. */
1518 if ((new = ospf_lsa_new ()) == NULL)
1519 {
1520 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1521 stream_free (s);
1522 return NULL;
1523 }
1524
1525 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1526 {
1527 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1528 ospf_lsa_free (new);
1529 new = NULL;
1530 stream_free (s);
1531 return NULL;
1532 }
1533
1534 new->area = area;
1535 new->oi = oi;
1536
1537 SET_FLAG (new->flags, OSPF_LSA_SELF);
1538 memcpy (new->data, newlsa, length);
1539 stream_free (s);
1540
1541 return new;
1542}
1543
1544
1545int
1546ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1547{
1548 /* Type 9 opaque LSA can be originated if there is at least one
1549 active opaque-capable neighbor attached to the outgoing
1550 interface. */
1551
paula15f45d2003-03-28 01:50:03 +00001552 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001553}
1554
1555int
1556ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1557{
1558 /* Type 10 opaque LSA can be originated if there is at least one
1559 interface belonging to the area that has an active opaque-capable
1560 neighbor. */
1561 listnode node;
1562
1563 for (node = listhead (area->oiflist); node; nextnode (node))
1564 {
1565 struct ospf_interface *oi = getdata (node);
1566
1567 /* Is there an active neighbor attached to this interface? */
1568 if (ospf_apiserver_is_ready_type9 (oi))
1569 {
1570 return 1;
1571 }
1572 }
1573 /* No active neighbor in area */
1574 return 0;
1575}
1576
1577int
1578ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1579{
1580 /* Type 11 opaque LSA can be originated if there is at least one interface
1581 that has an active opaque-capable neighbor. */
1582 listnode node;
1583
1584 for (node = listhead (ospf->oiflist); node; nextnode (node))
1585 {
1586 struct ospf_interface *oi = getdata (node);
1587
1588 /* Is there an active neighbor attached to this interface? */
1589 if (ospf_apiserver_is_ready_type9 (oi))
1590 return 1;
1591 }
1592 /* No active neighbor at all */
1593 return 0;
1594}
1595
1596
1597int
1598ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1599 struct msg *msg)
1600{
1601 struct msg_originate_request *omsg;
1602 struct lsa_header *data;
1603 struct ospf_lsa *new;
1604 struct ospf_lsa *old;
1605 struct ospf_area *area = NULL;
1606 struct ospf_interface *oi = NULL;
1607 struct ospf_lsdb *lsdb = NULL;
1608 int lsa_type, opaque_type;
1609 int ready = 0;
1610 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001611
paul2d33f152003-03-17 01:10:58 +00001612 /* Extract opaque LSA data from message */
1613 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1614 data = &omsg->data;
1615
1616 /* Determine interface for type9 or area for type10 LSAs. */
1617 switch (data->type)
1618 {
1619 case OSPF_OPAQUE_LINK_LSA:
1620 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1621 if (!oi)
1622 {
1623 zlog_warn ("apiserver_originate: unknown interface %s",
1624 inet_ntoa (omsg->ifaddr));
1625 rc = OSPF_API_NOSUCHINTERFACE;
1626 goto out;
1627 }
1628 area = oi->area;
1629 lsdb = area->lsdb;
1630 break;
1631 case OSPF_OPAQUE_AREA_LSA:
paul7d5e2682003-04-05 19:41:07 +00001632 area = ospf_area_lookup_by_area_id (ospf_top, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001633 if (!area)
1634 {
1635 zlog_warn ("apiserver_originate: unknown area %s",
1636 inet_ntoa (omsg->area_id));
1637 rc = OSPF_API_NOSUCHAREA;
1638 goto out;
1639 }
1640 lsdb = area->lsdb;
1641 break;
1642 case OSPF_OPAQUE_AS_LSA:
1643 lsdb = ospf_top->lsdb;
1644 break;
1645 default:
1646 /* We can only handle opaque types here */
1647 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1648 data->type);
1649 rc = OSPF_API_ILLEGALLSATYPE;
1650 goto out;
1651 }
1652
1653 /* Check if we registered this opaque type */
1654 lsa_type = data->type;
1655 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1656
1657 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1658 {
1659 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1660 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1661 goto out;
1662 }
1663
1664 /* Make sure that the neighbors are ready before we can originate */
1665 switch (data->type)
1666 {
1667 case OSPF_OPAQUE_LINK_LSA:
1668 ready = ospf_apiserver_is_ready_type9 (oi);
1669 break;
1670 case OSPF_OPAQUE_AREA_LSA:
1671 ready = ospf_apiserver_is_ready_type10 (area);
1672 break;
1673 case OSPF_OPAQUE_AS_LSA:
1674 ready = ospf_apiserver_is_ready_type11 (ospf_top);
1675 break;
1676 default:
1677 break;
1678 }
1679
1680 if (!ready)
1681 {
1682 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1683 rc = OSPF_API_NOTREADY;
1684 goto out;
1685 }
1686
1687 /* Create OSPF's internal opaque LSA representation */
1688 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1689 if (!new)
1690 {
1691 rc = OSPF_API_NOMEMORY; /* XXX */
1692 goto out;
1693 }
1694
1695 /* Determine if LSA is new or an update for an existing one. */
1696 old = ospf_lsdb_lookup (lsdb, new);
1697
1698 if (!old)
1699 {
1700 /* New LSA install in LSDB. */
1701 rc = ospf_apiserver_originate1 (new);
1702 }
1703 else
1704 {
1705 /*
1706 * Keep the new LSA instance in the "waiting place" until the next
1707 * refresh timing. If several LSA update requests for the same LSID
1708 * have issued by peer, the last one takes effect.
1709 */
1710 new->lsdb = &apiserv->reserve;
1711 ospf_lsdb_add (&apiserv->reserve, new);
1712
1713 /* Kick the scheduler function. */
1714 ospf_opaque_lsa_refresh_schedule (old);
1715 }
1716
1717out:
1718
1719 /* Send a reply back to client with return code */
1720 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1721 return rc;
1722}
1723
1724
1725/* -----------------------------------------------------------
1726 * Flood an LSA within its flooding scope.
1727 * -----------------------------------------------------------
1728 */
1729
1730/* XXX We can probably use ospf_flood_through instead of this function
1731 but then we need the neighbor parameter. If we set nbr to
1732 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1733
1734void
1735ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1736{
1737 assert (lsa);
1738
1739 switch (lsa->data->type)
1740 {
1741 case OSPF_OPAQUE_LINK_LSA:
1742 /* Increment counters? XXX */
1743
1744 /* Flood LSA through local network. */
1745 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1746 break;
1747 case OSPF_OPAQUE_AREA_LSA:
1748 /* Update LSA origination count. */
1749 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001750 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001751
1752 /* Flood LSA through area. */
1753 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1754 break;
1755 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001756 {
1757 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001758
paul7d5e2682003-04-05 19:41:07 +00001759 /* Flood LSA through AS. */
1760 ospf_flood_through_as (ospf_top, NULL /*nbr */ , lsa);
1761 break;
1762 }
paul2d33f152003-03-17 01:10:58 +00001763 }
1764}
1765
1766int
1767ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1768{
1769 /* Install this LSA into LSDB. */
paul7d5e2682003-04-05 19:41:07 +00001770 if (ospf_lsa_install (ospf_top, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001771 {
1772 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1773 return -1;
1774 }
1775
1776 /* Flood LSA within scope */
1777
1778#ifdef NOTYET
1779 /*
1780 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1781 * parameter, and thus it does not cause SIGSEGV error.
1782 */
1783 ospf_flood_through (NULL /*nbr */ , lsa);
1784#else /* NOTYET */
1785
1786 ospf_apiserver_flood_opaque_lsa (lsa);
1787#endif /* NOTYET */
1788
1789 return 0;
1790}
1791
1792
1793/* Opaque LSAs of type 9 on a specific interface can now be
1794 originated. Tell clients that registered type 9. */
1795int
1796ospf_apiserver_lsa9_originator (void *arg)
1797{
1798 struct ospf_interface *oi;
1799
1800 oi = (struct ospf_interface *) arg;
1801 if (listcount (apiserver_list) > 0) {
1802 ospf_apiserver_clients_notify_ready_type9 (oi);
1803 }
1804 return 0;
1805}
1806
1807int
1808ospf_apiserver_lsa10_originator (void *arg)
1809{
1810 struct ospf_area *area;
1811
1812 area = (struct ospf_area *) arg;
1813 if (listcount (apiserver_list) > 0) {
1814 ospf_apiserver_clients_notify_ready_type10 (area);
1815 }
1816 return 0;
1817}
1818
1819int
1820ospf_apiserver_lsa11_originator (void *arg)
1821{
1822 struct ospf *ospf;
1823
1824 ospf = (struct ospf *) arg;
1825 if (listcount (apiserver_list) > 0) {
1826 ospf_apiserver_clients_notify_ready_type11 (ospf);
1827 }
1828 return 0;
1829}
1830
1831
1832/* Periodically refresh opaque LSAs so that they do not expire in
1833 other routers. */
1834void
1835ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1836{
1837 struct ospf_apiserver *apiserv;
1838 struct ospf_lsa *new = NULL;
1839
1840 apiserv = lookup_apiserver_by_lsa (lsa);
1841 if (!apiserv)
1842 {
1843 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1844 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1845 }
1846
1847 if (IS_LSA_MAXAGE (lsa))
1848 {
1849 ospf_opaque_lsa_flush_schedule (lsa);
1850 goto out;
1851 }
1852
1853 /* Check if updated version of LSA instance has already prepared. */
1854 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1855 if (!new)
1856 {
1857 /* This is a periodic refresh, driven by core OSPF mechanism. */
1858 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1859 if (!new)
1860 {
1861 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1862 goto out;
1863 }
1864 }
1865 else
1866 {
1867 /* This is a forcible refresh, requested by OSPF-API client. */
1868 ospf_lsdb_delete (&apiserv->reserve, new);
1869 new->lsdb = NULL;
1870 }
1871
1872 /* Increment sequence number */
1873 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1874
1875 /* New LSA is in same area. */
1876 new->area = lsa->area;
1877 SET_FLAG (new->flags, OSPF_LSA_SELF);
1878
1879 /* Install LSA into LSDB. */
paul7d5e2682003-04-05 19:41:07 +00001880 if (ospf_lsa_install (ospf_top, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001881 {
1882 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1883 ospf_lsa_free (new);
1884 goto out;
1885 }
1886
1887 /* Flood updated LSA through interface, area or AS */
1888
1889#ifdef NOTYET
1890 ospf_flood_through (NULL /*nbr */ , new);
1891#endif /* NOTYET */
1892 ospf_apiserver_flood_opaque_lsa (new);
1893
1894 /* Debug logging. */
1895 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1896 {
1897 zlog_info ("LSA[Type%d:%s]: Refresh Opaque LSA",
1898 new->data->type, inet_ntoa (new->data->id));
1899 ospf_lsa_header_dump (new->data);
1900 }
1901
1902out:
1903 return;
1904}
1905
1906
1907/* -----------------------------------------------------------
1908 * Followings are functions to delete LSAs
1909 * -----------------------------------------------------------
1910 */
1911
1912int
1913ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1914 struct msg *msg)
1915{
1916 struct msg_delete_request *dmsg;
1917 struct ospf_lsa *old;
1918 struct ospf_area *area = NULL;
1919 struct in_addr id;
1920 int lsa_type, opaque_type;
1921 int rc = 0;
1922
1923 /* Extract opaque LSA from message */
1924 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1925
1926 /* Lookup area for link-local and area-local opaque LSAs */
1927 switch (dmsg->lsa_type)
1928 {
1929 case OSPF_OPAQUE_LINK_LSA:
1930 case OSPF_OPAQUE_AREA_LSA:
paul7d5e2682003-04-05 19:41:07 +00001931 area = ospf_area_lookup_by_area_id (ospf_top, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001932 if (!area)
1933 {
1934 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1935 inet_ntoa (dmsg->area_id));
1936 rc = OSPF_API_NOSUCHAREA;
1937 goto out;
1938 }
1939 break;
1940 case OSPF_OPAQUE_AS_LSA:
1941 /* AS-external opaque LSAs have no designated area */
1942 area = NULL;
1943 break;
1944 default:
1945 zlog_warn
1946 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1947 dmsg->lsa_type);
1948 rc = OSPF_API_ILLEGALLSATYPE;
1949 goto out;
1950 }
1951
1952 /* Check if we registered this opaque type */
1953 lsa_type = dmsg->lsa_type;
1954 opaque_type = dmsg->opaque_type;
1955
1956 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1957 {
1958 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1959 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1960 goto out;
1961 }
1962
1963 /* opaque_id is in network byte order */
1964 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1965 ntohl (dmsg->opaque_id)));
1966
1967 /*
1968 * Even if the target LSA has once scheduled to flush, it remains in
1969 * the LSDB until it is finally handled by the maxage remover thread.
1970 * Therefore, the lookup function below may return non-NULL result.
1971 */
1972 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf_top->router_id);
1973 if (!old)
1974 {
1975 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1976 dmsg->lsa_type, inet_ntoa (id));
1977 rc = OSPF_API_NOSUCHLSA;
1978 goto out;
1979 }
1980
1981 /* Schedule flushing of LSA from LSDB */
1982 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1983 ospf_opaque_lsa_flush_schedule (old);
1984
1985out:
1986
1987 /* Send reply back to client including return code */
1988 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1989 return rc;
1990}
1991
1992/* Flush self-originated opaque LSA */
1993int
1994apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
1995 void *p_arg, int int_arg)
1996{
1997 struct param_t
1998 {
1999 struct ospf_apiserver *apiserv;
2000 u_char lsa_type;
2001 u_char opaque_type;
2002 }
2003 *param;
2004
2005 /* Sanity check */
2006 assert (lsa->data);
2007 assert (p_arg);
2008 param = (struct param_t *) p_arg;
2009
2010 /* If LSA matches type and opaque type then delete it */
2011 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2012 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2013 {
2014 ospf_opaque_lsa_flush_schedule (lsa);
2015 }
2016 return 0;
2017}
2018
2019/* Delete self-originated opaque LSAs of a given opaque type. This
2020 function is called when an application unregisters a given opaque
2021 type or a connection to an application closes and all those opaque
2022 LSAs need to be flushed the LSDB. */
2023void
2024ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2025 u_char lsa_type, u_char opaque_type)
2026{
2027 struct param_t
2028 {
2029 struct ospf_apiserver *apiserv;
2030 u_char lsa_type;
2031 u_char opaque_type;
2032 }
2033 param;
2034 listnode node;
2035
2036 /* Set parameter struct. */
2037 param.apiserv = apiserv;
2038 param.lsa_type = lsa_type;
2039 param.opaque_type = opaque_type;
2040
2041#ifdef ORIGINAL_CODING
2042 /* Iterate over all areas */
2043 for (node = listhead (ospf_top->areas); node; nextnode (node))
2044 {
2045 struct ospf_area *area = node->data;
2046
2047 foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) &param, 0,
2048 apiserver_flush_opaque_type_callback);
2049 foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) &param, 0,
2050 apiserver_flush_opaque_type_callback);
2051 }
2052
2053 /* For AS-external opaque LSAs */
2054 if (ospf_top->lsdb)
2055 {
2056 foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) &param, 0,
2057 apiserver_flush_opaque_type_callback);
2058 }
2059#else /* ORIGINAL_CODING */
2060 switch (lsa_type)
2061 {
2062 case OSPF_OPAQUE_LINK_LSA:
2063 for (node = listhead (ospf_top->areas); node; nextnode (node))
2064 {
2065 struct ospf_area *area = node->data;
2066 foreach_lsa (OPAQUE_LINK_LSDB (area), (void *) &param, 0,
2067 apiserver_flush_opaque_type_callback);
2068 }
2069 break;
2070 case OSPF_OPAQUE_AREA_LSA:
2071 for (node = listhead (ospf_top->areas); node; nextnode (node))
2072 {
2073 struct ospf_area *area = node->data;
2074 foreach_lsa (OPAQUE_AREA_LSDB (area), (void *) &param, 0,
2075 apiserver_flush_opaque_type_callback);
2076 }
2077 break;
2078 case OSPF_OPAQUE_AS_LSA:
2079 foreach_lsa (OPAQUE_AS_LSDB (ospf_top), (void *) &param, 0,
2080 apiserver_flush_opaque_type_callback);
2081 break;
2082 default:
2083 break;
2084 }
2085 return;
2086#endif /* ORIGINAL_CODING */
2087}
2088
2089
2090/* -----------------------------------------------------------
2091 * Followings are callback functions to handle opaque types
2092 * -----------------------------------------------------------
2093 */
2094
2095int
2096ospf_apiserver_new_if (struct interface *ifp)
2097{
2098 struct ospf_interface *oi;
2099
2100 /* For some strange reason it seems possible that we are invoked
2101 with an interface that has no name. This seems to happen during
2102 initialization. Return if this happens */
2103
2104 if (ifp->name[0] == '\0') {
2105 /* interface has empty name */
2106 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2107 return 0;
2108 }
2109
2110 /* zlog_warn for debugging */
2111 zlog_warn ("ospf_apiserver_new_if");
2112 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2113 ifp->ifindex);
2114
2115 if (ifp->name[0] == '\0') {
2116 /* interface has empty name */
2117 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2118 return 0;
2119 }
2120
2121 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2122
2123 if (!oi) {
2124 /* This interface is known to Zebra but not to OSPF daemon yet. */
2125 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2126 ifp->name);
2127 return 0;
2128 }
2129
2130 assert (oi);
2131
2132 /* New interface added to OSPF, tell clients about it */
2133 if (listcount (apiserver_list) > 0) {
2134 ospf_apiserver_clients_notify_new_if (oi);
2135 }
2136 return 0;
2137}
2138
2139int
2140ospf_apiserver_del_if (struct interface *ifp)
2141{
2142 struct ospf_interface *oi;
2143
2144 /* zlog_warn for debugging */
2145 zlog_warn ("ospf_apiserver_del_if");
2146 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2147 ifp->ifindex);
2148
2149 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002150
2151 if (!oi) {
2152 /* This interface is known to Zebra but not to OSPF daemon
2153 anymore. No need to tell clients about it */
2154 return 0;
2155 }
paul2d33f152003-03-17 01:10:58 +00002156
2157 /* Interface deleted, tell clients about it */
2158 if (listcount (apiserver_list) > 0) {
2159 ospf_apiserver_clients_notify_del_if (oi);
2160 }
2161 return 0;
2162}
2163
2164void
2165ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2166{
2167 /* Tell clients about interface change */
2168
2169 /* zlog_warn for debugging */
2170 zlog_warn ("ospf_apiserver_ism_change");
2171 if (listcount (apiserver_list) > 0) {
2172 ospf_apiserver_clients_notify_ism_change (oi);
2173 }
2174
2175 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2176 zlog_warn ("old_state=%d", old_state);
2177 zlog_warn ("oi->state=%d", oi->state);
2178}
2179
2180void
2181ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2182{
2183 /* Neighbor status changed, tell clients about it */
2184 zlog_warn ("ospf_apiserver_nsm_change");
2185 if (listcount (apiserver_list) > 0) {
2186 ospf_apiserver_clients_notify_nsm_change (nbr);
2187 }
2188}
2189
2190void
2191ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2192{
2193 struct opaque_lsa
2194 {
2195 struct lsa_header header;
2196 u_char data[1]; /* opaque data have variable length. This is start
2197 address */
2198 };
2199 struct opaque_lsa *olsa;
2200 int opaquelen;
2201
2202 olsa = (struct opaque_lsa *) lsa->data;
2203
2204 if (VALID_OPAQUE_INFO_LEN (lsa->data))
2205 {
2206 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2207 }
2208 else
2209 {
2210 opaquelen = 0;
2211 }
2212
2213 /* Output information about opaque LSAs */
2214 if (vty != NULL)
2215 {
2216 int i;
2217 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2218 opaquelen,
2219 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2220 VTY_NEWLINE);
2221 vty_out (vty, " Opaque data: ");
2222
2223 for (i = 0; i < opaquelen; i++)
2224 {
2225 vty_out (vty, "0x%x ", olsa->data[i]);
2226 }
2227 vty_out (vty, "%s", VTY_NEWLINE);
2228 }
2229 else
2230 {
2231 int i;
2232 zlog_info (" Added using OSPF API: %u octets of opaque data %s",
2233 opaquelen,
2234 VALID_OPAQUE_INFO_LEN (lsa->
2235 data) ? "" : "(Invalid length?)");
2236 zlog_info (" Opaque data: ");
2237
2238 for (i = 0; i < opaquelen; i++)
2239 {
2240 zlog_info ("0x%x ", olsa->data[i]);
2241 }
2242 zlog_info ("\n");
2243 }
2244 return;
2245}
2246
2247/* -----------------------------------------------------------
2248 * Followings are functions to notify clients about events
2249 * -----------------------------------------------------------
2250 */
2251
2252/* Send a message to all clients. This is useful for messages
2253 that need to be notified to all clients (such as interface
2254 changes) */
2255
2256void
2257ospf_apiserver_clients_notify_all (struct msg *msg)
2258{
2259 listnode node;
2260
2261 /* Send message to all clients */
2262 for (node = listhead (apiserver_list); node; nextnode (node))
2263 {
2264 struct ospf_apiserver *apiserv =
2265 (struct ospf_apiserver *) getdata (node);
2266
2267 ospf_apiserver_send_msg (apiserv, msg);
2268 }
2269}
2270
2271/* An interface is now ready to accept opaque LSAs. Notify all
2272 clients that registered to use this opaque type */
2273void
2274ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2275{
2276 listnode node;
2277 struct msg *msg;
2278
2279 assert (oi);
2280 if (!oi->address)
2281 {
2282 zlog_warn ("Interface has no address?");
2283 return;
2284 }
2285
2286 if (!ospf_apiserver_is_ready_type9 (oi))
2287 {
2288 zlog_warn ("Interface not ready for type 9?");
2289 return;
2290 }
2291
2292 for (node = listhead (apiserver_list); node; nextnode (node))
2293 {
2294 struct ospf_apiserver *apiserv =
2295 (struct ospf_apiserver *) getdata (node);
2296 listnode n2;
2297
2298 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2299 {
2300 struct registered_opaque_type *r =
2301 (struct registered_opaque_type *) getdata (n2);
2302 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2303 {
2304 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2305 r->opaque_type,
2306 oi->address->u.prefix4);
2307 if (!msg)
2308 {
2309 zlog_warn
2310 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2311#ifdef NOTYET
2312 /* Cannot allocate new message. What should we do? */
2313 ospf_apiserver_free (apiserv);
2314#endif
2315 goto out;
2316 }
2317
2318 ospf_apiserver_send_msg (apiserv, msg);
2319 msg_free (msg);
2320 }
2321 }
2322 }
2323
2324out:
2325 return;
2326}
2327
2328void
2329ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2330{
2331 listnode node;
2332 struct msg *msg;
2333
2334 assert (area);
2335
2336 if (!ospf_apiserver_is_ready_type10 (area))
2337 {
2338 zlog_warn ("Area not ready for type 10?");
2339 return;
2340 }
2341
2342 for (node = listhead (apiserver_list); node; nextnode (node))
2343 {
2344 struct ospf_apiserver *apiserv =
2345 (struct ospf_apiserver *) getdata (node);
2346 listnode n2;
2347
2348 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2349 {
2350 struct registered_opaque_type *r =
2351 (struct registered_opaque_type *) getdata (n2);
2352 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2353 {
2354 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2355 r->opaque_type, area->area_id);
2356 if (!msg)
2357 {
2358 zlog_warn
2359 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2360#ifdef NOTYET
2361 /* Cannot allocate new message. What should we do? */
2362 ospf_apiserver_free (apiserv);
2363#endif
2364 goto out;
2365 }
2366
2367 ospf_apiserver_send_msg (apiserv, msg);
2368 msg_free (msg);
2369 }
2370 }
2371 }
2372
2373out:
2374 return;
2375}
2376
2377
2378void
2379ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2380{
2381 listnode node;
2382 struct msg *msg;
2383 struct in_addr id_null = { 0L };
2384
2385 assert (top);
2386
2387 if (!ospf_apiserver_is_ready_type11 (top))
2388 {
2389 zlog_warn ("AS not ready for type 11?");
2390 return;
2391 }
2392
2393 for (node = listhead (apiserver_list); node; nextnode (node))
2394 {
2395 struct ospf_apiserver *apiserv =
2396 (struct ospf_apiserver *) getdata (node);
2397 listnode n2;
2398
2399 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
2400 {
2401 struct registered_opaque_type *r =
2402 (struct registered_opaque_type *) getdata (n2);
2403 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2404 {
2405 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2406 r->opaque_type, id_null);
2407 if (!msg)
2408 {
2409 zlog_warn
2410 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2411#ifdef NOTYET
2412 /* Cannot allocate new message. What should we do? */
2413 ospf_apiserver_free (apiserv);
2414#endif
2415 goto out;
2416 }
2417
2418 ospf_apiserver_send_msg (apiserv, msg);
2419 msg_free (msg);
2420 }
2421 }
2422 }
2423
2424out:
2425 return;
2426}
2427
2428void
2429ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2430{
2431 struct msg *msg;
2432
2433 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2434 if (msg != NULL)
2435 {
2436 ospf_apiserver_clients_notify_all (msg);
2437 msg_free (msg);
2438 }
2439}
2440
2441void
2442ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2443{
2444 struct msg *msg;
2445
2446 msg = new_msg_del_if (0, oi->address->u.prefix4);
2447 if (msg != NULL)
2448 {
2449 ospf_apiserver_clients_notify_all (msg);
2450 msg_free (msg);
2451 }
2452}
2453
2454void
2455ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2456{
2457 struct msg *msg;
2458 struct in_addr ifaddr = { 0L };
2459 struct in_addr area_id = { 0L };
2460
2461 assert (oi);
2462 assert (oi->ifp);
2463
2464 if (oi->address)
2465 {
2466 ifaddr = oi->address->u.prefix4;
2467 }
2468 if (oi->area)
2469 {
2470 area_id = oi->area->area_id;
2471 }
2472
2473 msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status);
2474 if (!msg)
2475 {
2476 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2477 return;
2478 }
2479
2480 ospf_apiserver_clients_notify_all (msg);
2481 msg_free (msg);
2482}
2483
2484void
2485ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2486{
2487 struct msg *msg;
2488 struct in_addr ifaddr = { 0L };
2489 struct in_addr nbraddr = { 0L };
2490
2491 assert (nbr);
2492
2493 if (nbr->oi)
2494 {
2495 ifaddr = nbr->oi->address->u.prefix4;
2496 }
2497
2498 nbraddr = nbr->address.u.prefix4;
2499
2500 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2501 if (!msg)
2502 {
2503 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2504 return;
2505 }
2506
2507 ospf_apiserver_clients_notify_all (msg);
2508 msg_free (msg);
2509}
2510
2511void
2512apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2513{
2514 struct msg *msg;
2515 listnode node;
2516
2517 /* Default area for AS-External and Opaque11 LSAs */
2518 struct in_addr area_id = { 0L };
2519
2520 /* Default interface for non Opaque9 LSAs */
2521 struct in_addr ifaddr = { 0L };
2522
2523 if (lsa->area)
2524 {
2525 area_id = lsa->area->area_id;
2526 }
2527 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2528 {
2529 assert (lsa->oi);
2530 ifaddr = lsa->oi->address->u.prefix4;
2531 }
2532
2533 /* Prepare message that can be sent to clients that have a matching
2534 filter */
2535 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2536 ifaddr, area_id,
2537 lsa->flags & OSPF_LSA_SELF, lsa->data);
2538 if (!msg)
2539 {
2540 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2541 return;
2542 }
2543
2544 /* Now send message to all clients with a matching filter */
2545 for (node = listhead (apiserver_list); node; nextnode (node))
2546 {
2547 struct ospf_apiserver *apiserv = (struct ospf_apiserver *) node->data;
2548 struct lsa_filter_type *filter;
2549 u_int16_t mask;
2550 u_int32_t *area;
2551 int i;
2552
2553 /* Check filter for this client. */
2554 filter = apiserv->filter;
2555
2556 /* Check area IDs in case of non AS-E LSAs.
2557 * If filter has areas (num_areas > 0),
2558 * then one of the areas must match the area ID of this LSA. */
2559
2560 i = filter->num_areas;
2561 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2562 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2563 {
2564 i = 0;
2565 }
2566
2567 if (i > 0)
2568 {
2569 area = (u_int32_t *) (filter + 1);
2570 while (i)
2571 {
2572 if (*area == area_id.s_addr)
2573 {
2574 break;
2575 }
2576 i--;
2577 area++;
2578 }
2579 }
2580 else
2581 {
2582 i = 1;
2583 }
2584
2585 if (i > 0)
2586 {
2587 /* Area match. Check LSA type. */
2588 mask = ntohs (filter->typemask);
2589
2590 if (mask & Power2[lsa->data->type])
2591 {
2592 /* Type also matches. Check origin. */
2593 if ((filter->origin == ANY_ORIGIN) ||
2594 (filter->origin == IS_LSA_SELF (lsa)))
2595 {
2596 ospf_apiserver_send_msg (apiserv, msg);
2597 }
2598 }
2599 }
2600 }
2601 /* Free message since it is not used anymore */
2602 msg_free (msg);
2603}
2604
2605
2606/* -------------------------------------------------------------
2607 * Followings are hooks invoked when LSAs are updated or deleted
2608 * -------------------------------------------------------------
2609 */
2610
2611
2612int
2613apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2614{
2615 struct msg *msg;
2616 /* default area for AS-External and Opaque11 LSAs */
2617 struct in_addr area_id = { 0L };
2618
2619 /* default interface for non Opaque9 LSAs */
2620 struct in_addr ifaddr = { 0L };
2621
2622 /* Only notify this update if the LSA's age is smaller than
2623 MAXAGE. Otherwise clients would see LSA updates with max age just
2624 before they are deleted from the LSDB. LSA delete messages have
2625 MAXAGE too but should not be filtered. */
2626 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2627 return 0;
2628 }
2629
2630 if (lsa->area)
2631 {
2632 area_id = lsa->area->area_id;
2633 }
2634 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2635 {
2636 ifaddr = lsa->oi->address->u.prefix4;
2637 }
2638 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2639 ifaddr, area_id,
2640 lsa->flags & OSPF_LSA_SELF, lsa->data);
2641 if (!msg)
2642 {
2643 zlog_warn ("notify_clients_lsa: msg_new failed");
2644 return -1;
2645 }
2646 /* Notify all clients that new LSA is added/updated */
2647 apiserver_clients_lsa_change_notify (msgtype, lsa);
2648
2649 /* Clients made their own copies of msg so we can free msg here */
2650 msg_free (msg);
2651
2652 return 0;
2653}
2654
2655int
2656ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2657{
2658 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2659}
2660
2661int
2662ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2663{
2664 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2665}
2666
2667#endif /* SUPPORT_OSPF_API */
2668