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