blob: 07b8f211ae36eb1078792b8a413e000bf2109dd7 [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{
gdt91f3e522004-12-09 14:51:03 +0000183 struct listnode *node;
paul87d6f872004-09-24 08:01:38 +0000184 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +0000185
186 /* Unregister wildcard [0/0] type */
187 ospf_delete_opaque_functab (0 /* all LSAs */,
188 0 /* all opaque types */);
189
190 /* Free all client instances */
paul1603c062004-09-24 08:23:24 +0000191 while ( (node = listhead (apiserver_list)) != NULL)
gdt91f3e522004-12-09 14:51:03 +0000192 /*
193 * XXX: this is just plain odd/wrong. Is there a missing
194 * apiserv = (struct ospf_apiserver *) node;
195 * ?
196 */
paul87d6f872004-09-24 08:01:38 +0000197 ospf_apiserver_free (apiserv);
paul2d33f152003-03-17 01:10:58 +0000198
199 /* Free client list itself */
200 list_delete (apiserver_list);
201
202 /* Free wildcard list */
203 /* XXX */
204}
205
206static struct ospf_apiserver *
207lookup_apiserver (u_char lsa_type, u_char opaque_type)
208{
paul87d6f872004-09-24 08:01:38 +0000209 struct listnode *n1, *n2;
paul2d33f152003-03-17 01:10:58 +0000210 struct registered_opaque_type *r;
211 struct ospf_apiserver *apiserv, *found = NULL;
212
paul87d6f872004-09-24 08:01:38 +0000213 /* XXX: this approaches O(n**2) */
paul2d33f152003-03-17 01:10:58 +0000214 for (n1 = listhead (apiserver_list); n1; nextnode (n1))
215 {
216 apiserv = (struct ospf_apiserver *) getdata (n1);
217
218 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
219 {
220 r = (struct registered_opaque_type *) getdata (n2);
221
222 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
223 {
224 found = apiserv;
225 goto out;
226 }
227 }
228 }
229out:
230 return found;
231}
232
233static struct ospf_apiserver *
234lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
235{
236 struct lsa_header *lsah = lsa->data;
237 struct ospf_apiserver *found = NULL;
238
239 if (IS_OPAQUE_LSA (lsah->type))
240 {
241 found = lookup_apiserver (lsah->type,
242 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
243 }
244 return found;
245}
246
247/* -----------------------------------------------------------
248 * Followings are functions to manage client connections.
249 * -----------------------------------------------------------
250 */
251static int
252ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
253{
254 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000255 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 +0000256 return 0;
257}
258
259static int
260ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
261{
262 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000263 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 +0000264 return 0;
265}
266
267/* Allocate new connection structure. */
268struct ospf_apiserver *
269ospf_apiserver_new (int fd_sync, int fd_async)
270{
271 struct ospf_apiserver *new =
272 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
273
274 new->filter =
275 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
276
277 new->fd_sync = fd_sync;
278 new->fd_async = fd_async;
279
280 /* list of registered opaque types that application uses */
281 new->opaque_types = list_new ();
282
283 /* Initialize temporary strage for LSA instances to be refreshed. */
284 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
285 ospf_lsdb_init (&new->reserve);
286
287 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
288 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
289
290 new->out_sync_fifo = msg_fifo_new ();
291 new->out_async_fifo = msg_fifo_new ();
292 new->t_sync_read = NULL;
293#ifdef USE_ASYNC_READ
294 new->t_async_read = NULL;
295#endif /* USE_ASYNC_READ */
296 new->t_sync_write = NULL;
297 new->t_async_write = NULL;
298
299 new->filter->typemask = 0; /* filter all LSAs */
300 new->filter->origin = ANY_ORIGIN;
301 new->filter->num_areas = 0;
302
303 return new;
304}
305
306void
307ospf_apiserver_event (enum event event, int fd,
308 struct ospf_apiserver *apiserv)
309{
310 struct thread *apiserver_serv_thread;
311
312 switch (event)
313 {
314 case OSPF_APISERVER_ACCEPT:
315 apiserver_serv_thread =
316 thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
317 break;
318 case OSPF_APISERVER_SYNC_READ:
319 apiserv->t_sync_read =
320 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
321 break;
322#ifdef USE_ASYNC_READ
323 case OSPF_APISERVER_ASYNC_READ:
324 apiserv->t_async_read =
325 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
326 break;
327#endif /* USE_ASYNC_READ */
328 case OSPF_APISERVER_SYNC_WRITE:
329 if (!apiserv->t_sync_write)
330 {
331 apiserv->t_sync_write =
332 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
333 }
334 break;
335 case OSPF_APISERVER_ASYNC_WRITE:
336 if (!apiserv->t_async_write)
337 {
338 apiserv->t_async_write =
339 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
340 }
341 break;
342 }
343}
344
345/* Free instance. First unregister all opaque types used by
346 application, flush opaque LSAs injected by application
347 from network and close connection. */
348void
349ospf_apiserver_free (struct ospf_apiserver *apiserv)
350{
paul87d6f872004-09-24 08:01:38 +0000351 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000352
353 /* Cancel read and write threads. */
354 if (apiserv->t_sync_read)
355 {
356 thread_cancel (apiserv->t_sync_read);
357 }
358#ifdef USE_ASYNC_READ
359 if (apiserv->t_async_read)
360 {
361 thread_cancel (apiserv->t_async_read);
362 }
363#endif /* USE_ASYNC_READ */
364 if (apiserv->t_sync_write)
365 {
366 thread_cancel (apiserv->t_sync_write);
367 }
368
369 if (apiserv->t_async_write)
370 {
371 thread_cancel (apiserv->t_async_write);
372 }
373
374 /* Unregister all opaque types that application registered
375 and flush opaque LSAs if still in LSDB. */
376
377 while ((node = listhead (apiserv->opaque_types)) != NULL)
378 {
379
380 struct registered_opaque_type *regtype = node->data;
381
382 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
383 regtype->opaque_type);
384
385 }
386
387 /* Close connections to OSPFd. */
388 if (apiserv->fd_sync > 0)
389 {
390 close (apiserv->fd_sync);
391 }
392
393 if (apiserv->fd_async > 0)
394 {
395 close (apiserv->fd_async);
396 }
397
398 /* Free fifos */
399 msg_fifo_free (apiserv->out_sync_fifo);
400 msg_fifo_free (apiserv->out_async_fifo);
401
402 /* Clear temporary strage for LSA instances to be refreshed. */
403 ospf_lsdb_delete_all (&apiserv->reserve);
404 ospf_lsdb_cleanup (&apiserv->reserve);
405
406 /* Remove from the list of active clients. */
407 listnode_delete (apiserver_list, apiserv);
408
409 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000410 zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000411
412 /* And free instance. */
413 XFREE (MTYPE_OSPF_APISERVER, apiserv);
414}
415
416int
417ospf_apiserver_read (struct thread *thread)
418{
419 struct ospf_apiserver *apiserv;
420 struct msg *msg;
421 int fd;
422 int rc = -1;
423 enum event event;
424
425 apiserv = THREAD_ARG (thread);
426 fd = THREAD_FD (thread);
427
428 if (fd == apiserv->fd_sync)
429 {
430 event = OSPF_APISERVER_SYNC_READ;
431 apiserv->t_sync_read = NULL;
432
433 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000434 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000435 inet_ntoa (apiserv->peer_sync.sin_addr),
436 ntohs (apiserv->peer_sync.sin_port));
437 }
438#ifdef USE_ASYNC_READ
439 else if (fd == apiserv->fd_async)
440 {
441 event = OSPF_APISERVER_ASYNC_READ;
442 apiserv->t_async_read = NULL;
443
444 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000445 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000446 inet_ntoa (apiserv->peer_async.sin_addr),
447 ntohs (apiserv->peer_async.sin_port));
448 }
449#endif /* USE_ASYNC_READ */
450 else
451 {
452 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
453 ospf_apiserver_free (apiserv);
454 goto out;
455 }
456
457 /* Read message from fd. */
458 msg = msg_read (fd);
459 if (msg == NULL)
460 {
461 zlog_warn
462 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
463
464 /* Perform cleanup. */
465 ospf_apiserver_free (apiserv);
466 goto out;
467 }
468
469 if (IS_DEBUG_OSPF_EVENT)
470 msg_print (msg);
471
472 /* Dispatch to corresponding message handler. */
473 rc = ospf_apiserver_handle_msg (apiserv, msg);
474
475 /* Prepare for next message, add read thread. */
476 ospf_apiserver_event (event, fd, apiserv);
477
478 msg_free (msg);
479
480out:
481 return rc;
482}
483
484int
485ospf_apiserver_sync_write (struct thread *thread)
486{
487 struct ospf_apiserver *apiserv;
488 struct msg *msg;
489 int fd;
490 int rc = -1;
491
492 apiserv = THREAD_ARG (thread);
493 assert (apiserv);
494 fd = THREAD_FD (thread);
495
496 apiserv->t_sync_write = NULL;
497
498 /* Sanity check */
499 if (fd != apiserv->fd_sync)
500 {
501 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
502 goto out;
503 }
504
505 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000506 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000507 inet_ntoa (apiserv->peer_sync.sin_addr),
508 ntohs (apiserv->peer_sync.sin_port));
509
510 /* Check whether there is really a message in the fifo. */
511 msg = msg_fifo_pop (apiserv->out_sync_fifo);
512 if (!msg)
513 {
514 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
515 return 0;
516 }
517
518 if (IS_DEBUG_OSPF_EVENT)
519 msg_print (msg);
520
521 rc = msg_write (fd, msg);
522
523 /* Once a message is dequeued, it should be freed anyway. */
524 msg_free (msg);
525
526 if (rc < 0)
527 {
528 zlog_warn
529 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
530 goto out;
531 }
532
533
534 /* If more messages are in sync message fifo, schedule write thread. */
535 if (msg_fifo_head (apiserv->out_sync_fifo))
536 {
537 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
538 apiserv);
539 }
540
541 out:
542
543 if (rc < 0)
544 {
545 /* Perform cleanup and disconnect with peer */
546 ospf_apiserver_free (apiserv);
547 }
548
549 return rc;
550}
551
552
553int
554ospf_apiserver_async_write (struct thread *thread)
555{
556 struct ospf_apiserver *apiserv;
557 struct msg *msg;
558 int fd;
559 int rc = -1;
560
561 apiserv = THREAD_ARG (thread);
562 assert (apiserv);
563 fd = THREAD_FD (thread);
564
565 apiserv->t_async_write = NULL;
566
567 /* Sanity check */
568 if (fd != apiserv->fd_async)
569 {
570 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
571 goto out;
572 }
573
574 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000575 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000576 inet_ntoa (apiserv->peer_async.sin_addr),
577 ntohs (apiserv->peer_async.sin_port));
578
579 /* Check whether there is really a message in the fifo. */
580 msg = msg_fifo_pop (apiserv->out_async_fifo);
581 if (!msg)
582 {
583 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
584 return 0;
585 }
586
587 if (IS_DEBUG_OSPF_EVENT)
588 msg_print (msg);
589
590 rc = msg_write (fd, msg);
591
592 /* Once a message is dequeued, it should be freed anyway. */
593 msg_free (msg);
594
595 if (rc < 0)
596 {
597 zlog_warn
598 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
599 goto out;
600 }
601
602
603 /* If more messages are in async message fifo, schedule write thread. */
604 if (msg_fifo_head (apiserv->out_async_fifo))
605 {
606 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
607 apiserv);
608 }
609
610 out:
611
612 if (rc < 0)
613 {
614 /* Perform cleanup and disconnect with peer */
615 ospf_apiserver_free (apiserv);
616 }
617
618 return rc;
619}
620
621
622int
623ospf_apiserver_serv_sock_family (unsigned short port, int family)
624{
625 union sockunion su;
626 int accept_sock;
627 int rc;
628
629 memset (&su, 0, sizeof (union sockunion));
630 su.sa.sa_family = family;
631
632 /* Make new socket */
633 accept_sock = sockunion_stream_socket (&su);
634 if (accept_sock < 0)
635 return accept_sock;
636
637 /* This is a server, so reuse address and port */
638 sockopt_reuseaddr (accept_sock);
639 sockopt_reuseport (accept_sock);
640
641 /* Bind socket to address and given port. */
642 rc = sockunion_bind (accept_sock, &su, port, NULL);
643 if (rc < 0)
644 {
645 close (accept_sock); /* Close socket */
646 return rc;
647 }
648
649 /* Listen socket under queue length 3. */
650 rc = listen (accept_sock, 3);
651 if (rc < 0)
652 {
653 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
ajs6099b3b2004-11-20 02:06:59 +0000654 safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000655 close (accept_sock); /* Close socket */
656 return rc;
657 }
658 return accept_sock;
659}
660
661
662/* Accept connection request from external applications. For each
663 accepted connection allocate own connection instance. */
664int
665ospf_apiserver_accept (struct thread *thread)
666{
667 int accept_sock;
668 int new_sync_sock;
669 int new_async_sock;
670 union sockunion su;
671 struct ospf_apiserver *apiserv;
672 struct sockaddr_in peer_async;
673 struct sockaddr_in peer_sync;
674 int peerlen;
675 int ret;
676
677 /* THREAD_ARG (thread) is NULL */
678 accept_sock = THREAD_FD (thread);
679
680 /* Keep hearing on socket for further connections. */
681 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
682
683 memset (&su, 0, sizeof (union sockunion));
684 /* Accept connection for synchronous messages */
685 new_sync_sock = sockunion_accept (accept_sock, &su);
686 if (new_sync_sock < 0)
687 {
ajs6099b3b2004-11-20 02:06:59 +0000688 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000689 return -1;
690 }
691
692 /* Get port address and port number of peer to make reverse connection.
693 The reverse channel uses the port number of the peer port+1. */
694
695 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
696 peerlen = sizeof (struct sockaddr_in);
697
698 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
699 if (ret < 0)
700 {
ajs6099b3b2004-11-20 02:06:59 +0000701 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000702 close (new_sync_sock);
703 return -1;
704 }
705
706 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000707 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000708 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
709
710 /* Create new socket for asynchronous messages. */
711 peer_async = peer_sync;
712 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
713
714 /* Check if remote port number to make reverse connection is valid one. */
715 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
716 {
717 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
718 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
719 close (new_sync_sock);
720 return -1;
721 }
722
723 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
724 if (new_async_sock < 0)
725 {
ajs6099b3b2004-11-20 02:06:59 +0000726 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000727 close (new_sync_sock);
728 return -1;
729 }
730
731 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
732 sizeof (struct sockaddr_in));
733
734 if (ret < 0)
735 {
ajs6099b3b2004-11-20 02:06:59 +0000736 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000737 close (new_sync_sock);
738 close (new_async_sock);
739 return -1;
740 }
741
742#ifdef USE_ASYNC_READ
743#else /* USE_ASYNC_READ */
744 /* Make the asynchronous channel write-only. */
745 ret = shutdown (new_async_sock, SHUT_RD);
746 if (ret < 0)
747 {
ajs6099b3b2004-11-20 02:06:59 +0000748 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000749 close (new_sync_sock);
750 close (new_async_sock);
751 return -1;
752 }
753#endif /* USE_ASYNC_READ */
754
755 /* Allocate new server-side connection structure */
756 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
757
758 /* Add to active connection list */
759 listnode_add (apiserver_list, apiserv);
760 apiserv->peer_sync = peer_sync;
761 apiserv->peer_async = peer_async;
762
763 /* And add read threads for new connection */
764 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
765#ifdef USE_ASYNC_READ
766 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
767#endif /* USE_ASYNC_READ */
768
769 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000770 zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000771
772 return 0;
773}
774
775
776/* -----------------------------------------------------------
777 * Send reply with return code to client application
778 * -----------------------------------------------------------
779 */
780
781int
782ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
783{
784 struct msg_fifo *fifo;
785 struct msg *msg2;
786 enum event event;
787 int fd;
788
789 switch (msg->hdr.msgtype)
790 {
791 case MSG_REPLY:
792 fifo = apiserv->out_sync_fifo;
793 fd = apiserv->fd_sync;
794 event = OSPF_APISERVER_SYNC_WRITE;
795 break;
796 case MSG_READY_NOTIFY:
797 case MSG_LSA_UPDATE_NOTIFY:
798 case MSG_LSA_DELETE_NOTIFY:
799 case MSG_NEW_IF:
800 case MSG_DEL_IF:
801 case MSG_ISM_CHANGE:
802 case MSG_NSM_CHANGE:
803 fifo = apiserv->out_async_fifo;
804 fd = apiserv->fd_async;
805 event = OSPF_APISERVER_ASYNC_WRITE;
806 break;
807 default:
808 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
809 msg->hdr.msgtype);
810 return -1;
811 }
812
813 /* Make a copy of the message and put in the fifo. Once the fifo
814 gets drained by the write thread, the message will be freed. */
815 /* NB: Given "msg" is untouched in this function. */
816 msg2 = msg_dup (msg);
817
818 /* Enqueue message into corresponding fifo queue */
819 msg_fifo_push (fifo, msg2);
820
821 /* Schedule write thread */
822 ospf_apiserver_event (event, fd, apiserv);
823 return 0;
824}
825
826int
827ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
828 u_char rc)
829{
830 struct msg *msg = new_msg_reply (seqnr, rc);
831 int ret;
832
833 if (!msg)
834 {
835 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
836#ifdef NOTYET
837 /* Cannot allocate new message. What should we do? */
838 ospf_apiserver_free (apiserv);
839#endif
840 return -1;
841 }
842
843 ret = ospf_apiserver_send_msg (apiserv, msg);
844 msg_free (msg);
845 return ret;
846}
847
848
849/* -----------------------------------------------------------
850 * Generic message dispatching handler function
851 * -----------------------------------------------------------
852 */
853
854int
855ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
856{
857 int rc;
858
859 /* Call corresponding message handler function. */
860 switch (msg->hdr.msgtype)
861 {
862 case MSG_REGISTER_OPAQUETYPE:
863 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
864 break;
865 case MSG_UNREGISTER_OPAQUETYPE:
866 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
867 break;
868 case MSG_REGISTER_EVENT:
869 rc = ospf_apiserver_handle_register_event (apiserv, msg);
870 break;
871 case MSG_SYNC_LSDB:
872 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
873 break;
874 case MSG_ORIGINATE_REQUEST:
875 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
876 break;
877 case MSG_DELETE_REQUEST:
878 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
879 break;
880 default:
881 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
882 msg->hdr.msgtype);
883 rc = -1;
884 }
885 return rc;
886}
887
888
889/* -----------------------------------------------------------
890 * Following are functions for opaque type registration
891 * -----------------------------------------------------------
892 */
893
894int
895ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
896 u_char lsa_type, u_char opaque_type)
897{
898 struct registered_opaque_type *regtype;
899 int (*originator_func) (void *arg);
900 int rc;
901
902 switch (lsa_type)
903 {
904 case OSPF_OPAQUE_LINK_LSA:
905 originator_func = ospf_apiserver_lsa9_originator;
906 break;
907 case OSPF_OPAQUE_AREA_LSA:
908 originator_func = ospf_apiserver_lsa10_originator;
909 break;
910 case OSPF_OPAQUE_AS_LSA:
911 originator_func = ospf_apiserver_lsa11_originator;
912 break;
913 default:
914 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
915 lsa_type);
916 return OSPF_API_ILLEGALLSATYPE;
917 }
918
919
920 /* Register opaque function table */
921 /* NB: Duplicated registration will be detected inside the function. */
922 rc =
923 ospf_register_opaque_functab (lsa_type, opaque_type,
924 NULL, /* ospf_apiserver_new_if */
925 NULL, /* ospf_apiserver_del_if */
926 NULL, /* ospf_apiserver_ism_change */
927 NULL, /* ospf_apiserver_nsm_change */
928 NULL,
929 NULL,
930 NULL,
931 ospf_apiserver_show_info,
932 originator_func,
933 ospf_apiserver_lsa_refresher,
934 NULL, /* ospf_apiserver_lsa_update */
935 NULL /* ospf_apiserver_lsa_delete */);
936
937 if (rc != 0)
938 {
939 zlog_warn ("Failed to register opaque type [%d/%d]",
940 lsa_type, opaque_type);
941 return OSPF_API_OPAQUETYPEINUSE;
942 }
943
944 /* Remember the opaque type that application registers so when
945 connection shuts down, we can flush all LSAs of this opaque
946 type. */
947
948 regtype =
949 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
950 memset (regtype, 0, sizeof (struct registered_opaque_type));
951 regtype->lsa_type = lsa_type;
952 regtype->opaque_type = opaque_type;
953
954 /* Add to list of registered opaque types */
955 listnode_add (apiserv->opaque_types, regtype);
956
957 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000958 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
paul87d6f872004-09-24 08:01:38 +0000959 " apiserv(%p), total#(%d)",
960 lsa_type, opaque_type, apiserv,
961 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000962
963 return 0;
964}
965
966int
967ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
968 u_char lsa_type, u_char opaque_type)
969{
gdt54ade992004-10-07 19:38:20 +0000970 struct listnode *n1, *n1_next;
971 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000972
gdt54ade992004-10-07 19:38:20 +0000973 for (n1 = listhead (apiserv->opaque_types); n1; n1 = n1_next)
paul2d33f152003-03-17 01:10:58 +0000974 {
gdt54ade992004-10-07 19:38:20 +0000975 n1_next = n1->next;
paul87d6f872004-09-24 08:01:38 +0000976
gdt54ade992004-10-07 19:38:20 +0000977 regtype = (struct registered_opaque_type *) getdata(n1);
paul2d33f152003-03-17 01:10:58 +0000978
979 /* Check if we really registered this opaque type */
980 if (regtype->lsa_type == lsa_type &&
981 regtype->opaque_type == opaque_type)
982 {
983
984 /* Yes, we registered this opaque type. Flush
985 all existing opaque LSAs of this type */
986
987 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
988 ospf_delete_opaque_functab (lsa_type, opaque_type);
989
990 /* Remove from list of registered opaque types */
991 listnode_delete (apiserv->opaque_types, regtype);
992
993 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000994 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
paul87d6f872004-09-24 08:01:38 +0000995 " from apiserv(%p), total#(%d)",
996 lsa_type, opaque_type, apiserv,
997 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000998
999 return 0;
1000 }
1001 }
1002
1003 /* Opaque type is not registered */
1004 zlog_warn ("Failed to unregister opaque type [%d/%d]",
1005 lsa_type, opaque_type);
1006 return OSPF_API_OPAQUETYPENOTREGISTERED;
1007}
1008
1009
1010int
1011apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
1012 u_char lsa_type, u_char opaque_type)
1013{
paul87d6f872004-09-24 08:01:38 +00001014 struct listnode *node;
1015 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001016
paul87d6f872004-09-24 08:01:38 +00001017 /* XXX: how many types are there? if few, why not just a bitmap? */
1018 LIST_LOOP (apiserv->opaque_types, regtype, node)
paul2d33f152003-03-17 01:10:58 +00001019 {
paul2d33f152003-03-17 01:10:58 +00001020 /* Check if we really registered this opaque type */
1021 if (regtype->lsa_type == lsa_type &&
1022 regtype->opaque_type == opaque_type)
1023 {
1024 /* Yes registered */
1025 return 1;
1026 }
1027 }
1028 /* Not registered */
1029 return 0;
1030}
1031
1032int
1033ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1034 struct msg *msg)
1035{
1036 struct msg_register_opaque_type *rmsg;
1037 u_char lsa_type;
1038 u_char opaque_type;
1039 int rc = 0;
1040
1041 /* Extract parameters from register opaque type message */
1042 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1043
1044 lsa_type = rmsg->lsatype;
1045 opaque_type = rmsg->opaquetype;
1046
1047 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1048
1049 /* Send a reply back to client including return code */
1050 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1051 if (rc < 0)
1052 goto out;
1053
1054 /* Now inform application about opaque types that are ready */
1055 switch (lsa_type)
1056 {
1057 case OSPF_OPAQUE_LINK_LSA:
1058 ospf_apiserver_notify_ready_type9 (apiserv);
1059 break;
1060 case OSPF_OPAQUE_AREA_LSA:
1061 ospf_apiserver_notify_ready_type10 (apiserv);
1062 break;
1063 case OSPF_OPAQUE_AS_LSA:
1064 ospf_apiserver_notify_ready_type11 (apiserv);
1065 break;
1066 }
1067out:
1068 return rc;
1069}
1070
1071
1072/* Notify specific client about all opaque types 9 that are ready. */
1073void
1074ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1075{
paul87d6f872004-09-24 08:01:38 +00001076 struct listnode *node;
1077 struct listnode *n2;
paul99b7c5d2003-04-06 01:19:28 +00001078 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001079 struct ospf_interface *oi;
1080 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001081
paul99b7c5d2003-04-06 01:19:28 +00001082 ospf = ospf_lookup ();
1083
paul87d6f872004-09-24 08:01:38 +00001084 LIST_LOOP (ospf->oiflist, oi, node)
paul2d33f152003-03-17 01:10:58 +00001085 {
paul2d33f152003-03-17 01:10:58 +00001086 /* Check if this interface is indeed ready for type 9 */
1087 if (!ospf_apiserver_is_ready_type9 (oi))
1088 continue;
1089
1090 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001091 /* XXX: loop-de-loop - optimise me */
1092 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00001093 {
paul2d33f152003-03-17 01:10:58 +00001094 struct msg *msg;
1095
1096 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1097 {
1098
1099 /* Yes, this opaque type is ready */
1100 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1101 r->opaque_type,
1102 oi->address->u.prefix4);
1103 if (!msg)
1104 {
1105 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1106#ifdef NOTYET
1107 /* Cannot allocate new message. What should we do? */
1108 ospf_apiserver_free (apiserv);
1109#endif
1110 goto out;
1111 }
1112 ospf_apiserver_send_msg (apiserv, msg);
1113 msg_free (msg);
1114 }
1115 }
1116 }
1117
1118out:
1119 return;
1120}
1121
1122
1123/* Notify specific client about all opaque types 10 that are ready. */
1124void
1125ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1126{
paul87d6f872004-09-24 08:01:38 +00001127 struct listnode *node;
1128 struct listnode *n2;
paul99b7c5d2003-04-06 01:19:28 +00001129 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001130 struct ospf_area *area;
1131
paul99b7c5d2003-04-06 01:19:28 +00001132 ospf = ospf_lookup ();
1133
paul87d6f872004-09-24 08:01:38 +00001134 LIST_LOOP (ospf->areas, area, node)
paul2d33f152003-03-17 01:10:58 +00001135 {
paul87d6f872004-09-24 08:01:38 +00001136 struct registered_opaque_type *r;
1137
paul2d33f152003-03-17 01:10:58 +00001138 if (!ospf_apiserver_is_ready_type10 (area))
1139 {
1140 continue;
1141 }
1142
1143 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001144 /* XXX: loop in loop - optimise me */
1145 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00001146 {
paul2d33f152003-03-17 01:10:58 +00001147 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001148
paul2d33f152003-03-17 01:10:58 +00001149 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1150 {
1151 /* Yes, this opaque type is ready */
1152 msg =
1153 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1154 r->opaque_type, area->area_id);
1155 if (!msg)
1156 {
1157 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1158#ifdef NOTYET
1159 /* Cannot allocate new message. What should we do? */
1160 ospf_apiserver_free (apiserv);
1161#endif
1162 goto out;
1163 }
1164 ospf_apiserver_send_msg (apiserv, msg);
1165 msg_free (msg);
1166 }
1167 }
1168 }
1169
1170out:
1171 return;
1172}
1173
1174/* Notify specific client about all opaque types 11 that are ready */
1175void
1176ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1177{
paul87d6f872004-09-24 08:01:38 +00001178 struct listnode *node;
paul99b7c5d2003-04-06 01:19:28 +00001179 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001180 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001181
1182 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001183
1184 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001185 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001186 goto out;
paul2d33f152003-03-17 01:10:58 +00001187
1188 /* Check for registered opaque type 11 types */
paul87d6f872004-09-24 08:01:38 +00001189 LIST_LOOP (apiserv->opaque_types, r, node)
paul2d33f152003-03-17 01:10:58 +00001190 {
paul2d33f152003-03-17 01:10:58 +00001191 struct msg *msg;
1192 struct in_addr noarea_id = { 0L };
1193
1194 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1195 {
1196 /* Yes, this opaque type is ready */
1197 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1198 r->opaque_type, noarea_id);
1199
1200 if (!msg)
1201 {
1202 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1203#ifdef NOTYET
1204 /* Cannot allocate new message. What should we do? */
1205 ospf_apiserver_free (apiserv);
1206#endif
1207 goto out;
1208 }
1209 ospf_apiserver_send_msg (apiserv, msg);
1210 msg_free (msg);
1211 }
1212 }
1213
1214out:
1215 return;
1216}
1217
1218int
1219ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1220 struct msg *msg)
1221{
1222 struct msg_unregister_opaque_type *umsg;
1223 u_char ltype;
1224 u_char otype;
1225 int rc = 0;
1226
1227 /* Extract parameters from unregister opaque type message */
1228 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1229
1230 ltype = umsg->lsatype;
1231 otype = umsg->opaquetype;
1232
1233 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1234
1235 /* Send a reply back to client including return code */
1236 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1237
1238 return rc;
1239}
1240
1241
1242/* -----------------------------------------------------------
1243 * Following are functions for event (filter) registration.
1244 * -----------------------------------------------------------
1245 */
1246int
1247ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1248 struct msg *msg)
1249{
1250 struct msg_register_event *rmsg;
1251 int rc;
1252 u_int32_t seqnum;
1253
1254 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1255
1256 /* Get request sequence number */
1257 seqnum = msg_get_seq (msg);
1258
1259 /* Free existing filter in apiserv. */
1260 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1261 /* Alloc new space for filter. */
1262
1263 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1264 ntohs (msg->hdr.msglen));
1265 if (apiserv->filter)
1266 {
1267 /* copy it over. */
1268 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1269 rc = OSPF_API_OK;
1270 }
1271 else
1272 {
1273 rc = OSPF_API_NOMEMORY;
1274 }
1275 /* Send a reply back to client with return code */
1276 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1277 return rc;
1278}
1279
1280
1281/* -----------------------------------------------------------
1282 * Followings are functions for LSDB synchronization.
1283 * -----------------------------------------------------------
1284 */
1285
1286int
1287apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1288{
1289 struct ospf_apiserver *apiserv;
1290 int seqnum;
1291 struct msg *msg;
1292 struct param_t
1293 {
1294 struct ospf_apiserver *apiserv;
1295 struct lsa_filter_type *filter;
1296 }
1297 *param;
1298 int rc = -1;
1299
1300 /* Sanity check */
1301 assert (lsa->data);
1302 assert (p_arg);
1303
1304 param = (struct param_t *) p_arg;
1305 apiserv = param->apiserv;
1306 seqnum = (u_int32_t) int_arg;
1307
1308 /* Check origin in filter. */
1309 if ((param->filter->origin == ANY_ORIGIN) ||
1310 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1311 {
1312
1313 /* Default area for AS-External and Opaque11 LSAs */
1314 struct in_addr area_id = { 0L };
1315
1316 /* Default interface for non Opaque9 LSAs */
1317 struct in_addr ifaddr = { 0L };
1318
1319 if (lsa->area)
1320 {
1321 area_id = lsa->area->area_id;
1322 }
1323 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1324 {
1325 ifaddr = lsa->oi->address->u.prefix4;
1326 }
1327
1328 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1329 seqnum,
1330 ifaddr, area_id,
1331 lsa->flags & OSPF_LSA_SELF, lsa->data);
1332 if (!msg)
1333 {
1334 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1335#ifdef NOTYET
1336 /* Cannot allocate new message. What should we do? */
1337/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1338#endif
1339 goto out;
1340 }
1341
1342 /* Send LSA */
1343 ospf_apiserver_send_msg (apiserv, msg);
1344 msg_free (msg);
1345 }
1346 rc = 0;
1347
1348out:
1349 return rc;
1350}
1351
1352int
1353ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1354 struct msg *msg)
1355{
paul87d6f872004-09-24 08:01:38 +00001356 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00001357 u_int32_t seqnum;
1358 int rc = 0;
1359 struct msg_sync_lsdb *smsg;
1360 struct param_t
1361 {
1362 struct ospf_apiserver *apiserv;
1363 struct lsa_filter_type *filter;
1364 }
1365 param;
1366 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001367 struct route_node *rn;
1368 struct ospf_lsa *lsa;
1369 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001370 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001371
1372 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001373
1374 /* Get request sequence number */
1375 seqnum = msg_get_seq (msg);
1376 /* Set sync msg. */
1377 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1378
1379 /* Set parameter struct. */
1380 param.apiserv = apiserv;
1381 param.filter = &smsg->filter;
1382
1383 /* Remember mask. */
1384 mask = ntohs (smsg->filter.typemask);
1385
1386 /* Iterate over all areas. */
paul87d6f872004-09-24 08:01:38 +00001387 LIST_LOOP (ospf->areas, area, node)
paul2d33f152003-03-17 01:10:58 +00001388 {
paul2d33f152003-03-17 01:10:58 +00001389 int i;
1390 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001391
paul2d33f152003-03-17 01:10:58 +00001392 /* Compare area_id with area_ids in sync request. */
1393 if ((i = smsg->filter.num_areas) > 0)
1394 {
1395 /* Let area_id point to the list of area IDs,
1396 * which is at the end of smsg->filter. */
1397 area_id = (u_int32_t *) (&smsg->filter + 1);
1398 while (i)
1399 {
1400 if (*area_id == area->area_id.s_addr)
1401 {
1402 break;
1403 }
1404 i--;
1405 area_id++;
1406 }
1407 }
1408 else
1409 {
1410 i = 1;
1411 }
1412
1413 /* If area was found, then i>0 here. */
1414 if (i)
1415 {
1416 /* Check msg type. */
1417 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001418 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1419 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001420 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001421 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1422 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001423 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001424 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1425 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001426 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001427 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1428 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001429 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001430 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1431 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001432 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001433 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1434 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001435 }
1436 }
1437
1438 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001439 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001440 {
1441 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001442 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1443 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001444 }
1445
1446 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001447 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001448 {
1449 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001450 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1451 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001452 }
1453
1454 /* Send a reply back to client with return code */
1455 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1456 return rc;
1457}
1458
1459
1460/* -----------------------------------------------------------
1461 * Followings are functions to originate or update LSA
1462 * from an application.
1463 * -----------------------------------------------------------
1464 */
1465
1466/* Create a new internal opaque LSA by taking prototype and filling in
1467 missing fields such as age, sequence number, advertising router,
1468 checksum and so on. The interface parameter is used for type 9
1469 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1470 nor interface. */
1471
1472struct ospf_lsa *
1473ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1474 struct ospf_interface *oi,
1475 struct lsa_header *protolsa)
1476{
1477 struct stream *s;
1478 struct lsa_header *newlsa;
1479 struct ospf_lsa *new = NULL;
1480 u_char options = 0x0;
1481 u_int16_t length;
1482
paul99b7c5d2003-04-06 01:19:28 +00001483 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001484
paul99b7c5d2003-04-06 01:19:28 +00001485 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001486 assert(ospf);
1487
paul2d33f152003-03-17 01:10:58 +00001488 /* Create a stream for internal opaque LSA */
1489 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1490 {
1491 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1492 return NULL;
1493 }
1494
1495 newlsa = (struct lsa_header *) STREAM_DATA (s);
1496
1497 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1498 have to set options? */
1499
1500 if (area)
1501 {
1502 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001503 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001504 }
1505
1506 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1507
1508 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1509 {
ajse84cc642004-12-08 17:28:56 +00001510 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
paul2d33f152003-03-17 01:10:58 +00001511 protolsa->type, inet_ntoa (protolsa->id));
1512 }
1513
1514 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001515 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001516 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001517
1518 /* Set opaque-LSA body fields. */
1519 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1520 ntohs (protolsa->length) - sizeof (struct lsa_header));
1521
1522 /* Determine length of LSA. */
1523 length = stream_get_endp (s);
1524 newlsa->length = htons (length);
1525
1526 /* Create OSPF LSA. */
1527 if ((new = ospf_lsa_new ()) == NULL)
1528 {
1529 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1530 stream_free (s);
1531 return NULL;
1532 }
1533
1534 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1535 {
1536 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
paul788dab12004-11-15 11:48:37 +00001537 ospf_lsa_unlock (new);
paul2d33f152003-03-17 01:10:58 +00001538 stream_free (s);
1539 return NULL;
1540 }
1541
1542 new->area = area;
1543 new->oi = oi;
1544
1545 SET_FLAG (new->flags, OSPF_LSA_SELF);
1546 memcpy (new->data, newlsa, length);
1547 stream_free (s);
1548
1549 return new;
1550}
1551
1552
1553int
1554ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1555{
1556 /* Type 9 opaque LSA can be originated if there is at least one
1557 active opaque-capable neighbor attached to the outgoing
1558 interface. */
1559
paula15f45d2003-03-28 01:50:03 +00001560 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001561}
1562
1563int
1564ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1565{
1566 /* Type 10 opaque LSA can be originated if there is at least one
1567 interface belonging to the area that has an active opaque-capable
1568 neighbor. */
paul87d6f872004-09-24 08:01:38 +00001569 struct listnode *node;
1570 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001571
paul87d6f872004-09-24 08:01:38 +00001572 LIST_LOOP (area->oiflist, oi, node)
1573 /* Is there an active neighbor attached to this interface? */
1574 if (ospf_apiserver_is_ready_type9 (oi))
1575 return 1;
paul2d33f152003-03-17 01:10:58 +00001576
paul2d33f152003-03-17 01:10:58 +00001577 /* No active neighbor in area */
1578 return 0;
1579}
1580
1581int
1582ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1583{
1584 /* Type 11 opaque LSA can be originated if there is at least one interface
1585 that has an active opaque-capable neighbor. */
paul87d6f872004-09-24 08:01:38 +00001586 struct listnode *node;
1587 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001588
paul87d6f872004-09-24 08:01:38 +00001589 LIST_LOOP (ospf->oiflist, oi, node)
1590 /* Is there an active neighbor attached to this interface? */
1591 if (ospf_apiserver_is_ready_type9 (oi))
1592 return 1;
paul2d33f152003-03-17 01:10:58 +00001593
paul2d33f152003-03-17 01:10:58 +00001594 /* No active neighbor at all */
1595 return 0;
1596}
1597
1598
1599int
1600ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1601 struct msg *msg)
1602{
1603 struct msg_originate_request *omsg;
1604 struct lsa_header *data;
1605 struct ospf_lsa *new;
1606 struct ospf_lsa *old;
1607 struct ospf_area *area = NULL;
1608 struct ospf_interface *oi = NULL;
1609 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001610 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001611 int lsa_type, opaque_type;
1612 int ready = 0;
1613 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001614
paul99b7c5d2003-04-06 01:19:28 +00001615 ospf = ospf_lookup();
1616
paul2d33f152003-03-17 01:10:58 +00001617 /* Extract opaque LSA data from message */
1618 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1619 data = &omsg->data;
1620
1621 /* Determine interface for type9 or area for type10 LSAs. */
1622 switch (data->type)
1623 {
1624 case OSPF_OPAQUE_LINK_LSA:
1625 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1626 if (!oi)
1627 {
1628 zlog_warn ("apiserver_originate: unknown interface %s",
1629 inet_ntoa (omsg->ifaddr));
1630 rc = OSPF_API_NOSUCHINTERFACE;
1631 goto out;
1632 }
1633 area = oi->area;
1634 lsdb = area->lsdb;
1635 break;
1636 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001637 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001638 if (!area)
1639 {
1640 zlog_warn ("apiserver_originate: unknown area %s",
1641 inet_ntoa (omsg->area_id));
1642 rc = OSPF_API_NOSUCHAREA;
1643 goto out;
1644 }
1645 lsdb = area->lsdb;
1646 break;
1647 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001648 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001649 break;
1650 default:
1651 /* We can only handle opaque types here */
1652 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1653 data->type);
1654 rc = OSPF_API_ILLEGALLSATYPE;
1655 goto out;
1656 }
1657
1658 /* Check if we registered this opaque type */
1659 lsa_type = data->type;
1660 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1661
1662 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1663 {
1664 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1665 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1666 goto out;
1667 }
1668
1669 /* Make sure that the neighbors are ready before we can originate */
1670 switch (data->type)
1671 {
1672 case OSPF_OPAQUE_LINK_LSA:
1673 ready = ospf_apiserver_is_ready_type9 (oi);
1674 break;
1675 case OSPF_OPAQUE_AREA_LSA:
1676 ready = ospf_apiserver_is_ready_type10 (area);
1677 break;
1678 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001679 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001680 break;
1681 default:
1682 break;
1683 }
1684
1685 if (!ready)
1686 {
1687 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1688 rc = OSPF_API_NOTREADY;
1689 goto out;
1690 }
1691
1692 /* Create OSPF's internal opaque LSA representation */
1693 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1694 if (!new)
1695 {
1696 rc = OSPF_API_NOMEMORY; /* XXX */
1697 goto out;
1698 }
1699
1700 /* Determine if LSA is new or an update for an existing one. */
1701 old = ospf_lsdb_lookup (lsdb, new);
1702
1703 if (!old)
1704 {
1705 /* New LSA install in LSDB. */
1706 rc = ospf_apiserver_originate1 (new);
1707 }
1708 else
1709 {
1710 /*
1711 * Keep the new LSA instance in the "waiting place" until the next
1712 * refresh timing. If several LSA update requests for the same LSID
1713 * have issued by peer, the last one takes effect.
1714 */
1715 new->lsdb = &apiserv->reserve;
1716 ospf_lsdb_add (&apiserv->reserve, new);
1717
1718 /* Kick the scheduler function. */
1719 ospf_opaque_lsa_refresh_schedule (old);
1720 }
1721
1722out:
1723
1724 /* Send a reply back to client with return code */
1725 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1726 return rc;
1727}
1728
1729
1730/* -----------------------------------------------------------
1731 * Flood an LSA within its flooding scope.
1732 * -----------------------------------------------------------
1733 */
1734
1735/* XXX We can probably use ospf_flood_through instead of this function
1736 but then we need the neighbor parameter. If we set nbr to
1737 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1738
1739void
1740ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1741{
1742 assert (lsa);
1743
1744 switch (lsa->data->type)
1745 {
1746 case OSPF_OPAQUE_LINK_LSA:
1747 /* Increment counters? XXX */
1748
1749 /* Flood LSA through local network. */
1750 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1751 break;
1752 case OSPF_OPAQUE_AREA_LSA:
1753 /* Update LSA origination count. */
1754 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001755 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001756
1757 /* Flood LSA through area. */
1758 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1759 break;
1760 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001761 {
paul99b7c5d2003-04-06 01:19:28 +00001762 struct ospf *ospf;
1763
1764 ospf = ospf_lookup();
1765 assert(ospf);
1766
paul7d5e2682003-04-05 19:41:07 +00001767 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001768
paul7d5e2682003-04-05 19:41:07 +00001769 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001770 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001771 break;
1772 }
paul2d33f152003-03-17 01:10:58 +00001773 }
1774}
1775
1776int
1777ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1778{
paul99b7c5d2003-04-06 01:19:28 +00001779 struct ospf *ospf;
1780
1781 ospf = ospf_lookup();
1782 assert(ospf);
1783
paul2d33f152003-03-17 01:10:58 +00001784 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001785 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001786 {
1787 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1788 return -1;
1789 }
1790
1791 /* Flood LSA within scope */
1792
1793#ifdef NOTYET
1794 /*
1795 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1796 * parameter, and thus it does not cause SIGSEGV error.
1797 */
1798 ospf_flood_through (NULL /*nbr */ , lsa);
1799#else /* NOTYET */
1800
1801 ospf_apiserver_flood_opaque_lsa (lsa);
1802#endif /* NOTYET */
1803
1804 return 0;
1805}
1806
1807
1808/* Opaque LSAs of type 9 on a specific interface can now be
1809 originated. Tell clients that registered type 9. */
1810int
1811ospf_apiserver_lsa9_originator (void *arg)
1812{
1813 struct ospf_interface *oi;
1814
1815 oi = (struct ospf_interface *) arg;
1816 if (listcount (apiserver_list) > 0) {
1817 ospf_apiserver_clients_notify_ready_type9 (oi);
1818 }
1819 return 0;
1820}
1821
1822int
1823ospf_apiserver_lsa10_originator (void *arg)
1824{
1825 struct ospf_area *area;
1826
1827 area = (struct ospf_area *) arg;
1828 if (listcount (apiserver_list) > 0) {
1829 ospf_apiserver_clients_notify_ready_type10 (area);
1830 }
1831 return 0;
1832}
1833
1834int
1835ospf_apiserver_lsa11_originator (void *arg)
1836{
1837 struct ospf *ospf;
1838
1839 ospf = (struct ospf *) arg;
1840 if (listcount (apiserver_list) > 0) {
1841 ospf_apiserver_clients_notify_ready_type11 (ospf);
1842 }
1843 return 0;
1844}
1845
1846
1847/* Periodically refresh opaque LSAs so that they do not expire in
1848 other routers. */
1849void
1850ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1851{
1852 struct ospf_apiserver *apiserv;
1853 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001854 struct ospf * ospf;
1855
1856 ospf = ospf_lookup();
1857 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001858
1859 apiserv = lookup_apiserver_by_lsa (lsa);
1860 if (!apiserv)
1861 {
1862 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1863 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1864 }
1865
1866 if (IS_LSA_MAXAGE (lsa))
1867 {
1868 ospf_opaque_lsa_flush_schedule (lsa);
1869 goto out;
1870 }
1871
1872 /* Check if updated version of LSA instance has already prepared. */
1873 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1874 if (!new)
1875 {
1876 /* This is a periodic refresh, driven by core OSPF mechanism. */
1877 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1878 if (!new)
1879 {
1880 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1881 goto out;
1882 }
1883 }
1884 else
1885 {
1886 /* This is a forcible refresh, requested by OSPF-API client. */
1887 ospf_lsdb_delete (&apiserv->reserve, new);
1888 new->lsdb = NULL;
1889 }
1890
1891 /* Increment sequence number */
1892 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1893
1894 /* New LSA is in same area. */
1895 new->area = lsa->area;
1896 SET_FLAG (new->flags, OSPF_LSA_SELF);
1897
1898 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001899 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001900 {
1901 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
paul788dab12004-11-15 11:48:37 +00001902 ospf_lsa_unlock (new);
paul2d33f152003-03-17 01:10:58 +00001903 goto out;
1904 }
1905
1906 /* Flood updated LSA through interface, area or AS */
1907
1908#ifdef NOTYET
1909 ospf_flood_through (NULL /*nbr */ , new);
1910#endif /* NOTYET */
1911 ospf_apiserver_flood_opaque_lsa (new);
1912
1913 /* Debug logging. */
1914 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1915 {
ajse84cc642004-12-08 17:28:56 +00001916 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
paul2d33f152003-03-17 01:10:58 +00001917 new->data->type, inet_ntoa (new->data->id));
1918 ospf_lsa_header_dump (new->data);
1919 }
1920
1921out:
1922 return;
1923}
1924
1925
1926/* -----------------------------------------------------------
1927 * Followings are functions to delete LSAs
1928 * -----------------------------------------------------------
1929 */
1930
1931int
1932ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1933 struct msg *msg)
1934{
1935 struct msg_delete_request *dmsg;
1936 struct ospf_lsa *old;
1937 struct ospf_area *area = NULL;
1938 struct in_addr id;
1939 int lsa_type, opaque_type;
1940 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001941 struct ospf * ospf;
1942
1943 ospf = ospf_lookup();
1944 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001945
1946 /* Extract opaque LSA from message */
1947 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1948
1949 /* Lookup area for link-local and area-local opaque LSAs */
1950 switch (dmsg->lsa_type)
1951 {
1952 case OSPF_OPAQUE_LINK_LSA:
1953 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001954 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001955 if (!area)
1956 {
1957 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1958 inet_ntoa (dmsg->area_id));
1959 rc = OSPF_API_NOSUCHAREA;
1960 goto out;
1961 }
1962 break;
1963 case OSPF_OPAQUE_AS_LSA:
1964 /* AS-external opaque LSAs have no designated area */
1965 area = NULL;
1966 break;
1967 default:
1968 zlog_warn
1969 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1970 dmsg->lsa_type);
1971 rc = OSPF_API_ILLEGALLSATYPE;
1972 goto out;
1973 }
1974
1975 /* Check if we registered this opaque type */
1976 lsa_type = dmsg->lsa_type;
1977 opaque_type = dmsg->opaque_type;
1978
1979 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1980 {
1981 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1982 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1983 goto out;
1984 }
1985
1986 /* opaque_id is in network byte order */
1987 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1988 ntohl (dmsg->opaque_id)));
1989
1990 /*
1991 * Even if the target LSA has once scheduled to flush, it remains in
1992 * the LSDB until it is finally handled by the maxage remover thread.
1993 * Therefore, the lookup function below may return non-NULL result.
1994 */
paul99b7c5d2003-04-06 01:19:28 +00001995 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001996 if (!old)
1997 {
1998 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1999 dmsg->lsa_type, inet_ntoa (id));
2000 rc = OSPF_API_NOSUCHLSA;
2001 goto out;
2002 }
2003
2004 /* Schedule flushing of LSA from LSDB */
2005 /* NB: Multiple scheduling will produce a warning message, but harmless. */
2006 ospf_opaque_lsa_flush_schedule (old);
2007
2008out:
2009
2010 /* Send reply back to client including return code */
2011 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
2012 return rc;
2013}
2014
2015/* Flush self-originated opaque LSA */
2016int
2017apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2018 void *p_arg, int int_arg)
2019{
2020 struct param_t
2021 {
2022 struct ospf_apiserver *apiserv;
2023 u_char lsa_type;
2024 u_char opaque_type;
2025 }
2026 *param;
2027
2028 /* Sanity check */
2029 assert (lsa->data);
2030 assert (p_arg);
2031 param = (struct param_t *) p_arg;
2032
2033 /* If LSA matches type and opaque type then delete it */
2034 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2035 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2036 {
2037 ospf_opaque_lsa_flush_schedule (lsa);
2038 }
2039 return 0;
2040}
2041
2042/* Delete self-originated opaque LSAs of a given opaque type. This
2043 function is called when an application unregisters a given opaque
2044 type or a connection to an application closes and all those opaque
2045 LSAs need to be flushed the LSDB. */
2046void
2047ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2048 u_char lsa_type, u_char opaque_type)
2049{
2050 struct param_t
2051 {
2052 struct ospf_apiserver *apiserv;
2053 u_char lsa_type;
2054 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002055 } param;
2056 struct listnode *node;
paul99b7c5d2003-04-06 01:19:28 +00002057 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002058 struct ospf_area *area;
2059
paul99b7c5d2003-04-06 01:19:28 +00002060 ospf = ospf_lookup();
2061 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002062
2063 /* Set parameter struct. */
2064 param.apiserv = apiserv;
2065 param.lsa_type = lsa_type;
2066 param.opaque_type = opaque_type;
2067
paul2d33f152003-03-17 01:10:58 +00002068 switch (lsa_type)
2069 {
paul99b7c5d2003-04-06 01:19:28 +00002070 struct route_node *rn;
2071 struct ospf_lsa *lsa;
2072
paul2d33f152003-03-17 01:10:58 +00002073 case OSPF_OPAQUE_LINK_LSA:
paul87d6f872004-09-24 08:01:38 +00002074 LIST_LOOP (ospf->areas, area, node)
2075 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2076 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002077 break;
2078 case OSPF_OPAQUE_AREA_LSA:
paul87d6f872004-09-24 08:01:38 +00002079 LIST_LOOP (ospf->areas, area, node)
2080 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2081 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002082 break;
2083 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002084 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2085 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002086 break;
2087 default:
2088 break;
2089 }
2090 return;
paul2d33f152003-03-17 01:10:58 +00002091}
2092
2093
2094/* -----------------------------------------------------------
2095 * Followings are callback functions to handle opaque types
2096 * -----------------------------------------------------------
2097 */
2098
2099int
2100ospf_apiserver_new_if (struct interface *ifp)
2101{
2102 struct ospf_interface *oi;
2103
2104 /* For some strange reason it seems possible that we are invoked
2105 with an interface that has no name. This seems to happen during
2106 initialization. Return if this happens */
2107
2108 if (ifp->name[0] == '\0') {
2109 /* interface has empty name */
2110 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2111 return 0;
2112 }
2113
2114 /* zlog_warn for debugging */
2115 zlog_warn ("ospf_apiserver_new_if");
2116 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2117 ifp->ifindex);
2118
2119 if (ifp->name[0] == '\0') {
2120 /* interface has empty name */
2121 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2122 return 0;
2123 }
2124
2125 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2126
2127 if (!oi) {
2128 /* This interface is known to Zebra but not to OSPF daemon yet. */
2129 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2130 ifp->name);
2131 return 0;
2132 }
2133
2134 assert (oi);
2135
2136 /* New interface added to OSPF, tell clients about it */
2137 if (listcount (apiserver_list) > 0) {
2138 ospf_apiserver_clients_notify_new_if (oi);
2139 }
2140 return 0;
2141}
2142
2143int
2144ospf_apiserver_del_if (struct interface *ifp)
2145{
2146 struct ospf_interface *oi;
2147
2148 /* zlog_warn for debugging */
2149 zlog_warn ("ospf_apiserver_del_if");
2150 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2151 ifp->ifindex);
2152
2153 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002154
2155 if (!oi) {
2156 /* This interface is known to Zebra but not to OSPF daemon
2157 anymore. No need to tell clients about it */
2158 return 0;
2159 }
paul2d33f152003-03-17 01:10:58 +00002160
2161 /* Interface deleted, tell clients about it */
2162 if (listcount (apiserver_list) > 0) {
2163 ospf_apiserver_clients_notify_del_if (oi);
2164 }
2165 return 0;
2166}
2167
2168void
2169ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2170{
2171 /* Tell clients about interface change */
2172
2173 /* zlog_warn for debugging */
2174 zlog_warn ("ospf_apiserver_ism_change");
2175 if (listcount (apiserver_list) > 0) {
2176 ospf_apiserver_clients_notify_ism_change (oi);
2177 }
2178
2179 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2180 zlog_warn ("old_state=%d", old_state);
2181 zlog_warn ("oi->state=%d", oi->state);
2182}
2183
2184void
2185ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2186{
2187 /* Neighbor status changed, tell clients about it */
2188 zlog_warn ("ospf_apiserver_nsm_change");
2189 if (listcount (apiserver_list) > 0) {
2190 ospf_apiserver_clients_notify_nsm_change (nbr);
2191 }
2192}
2193
2194void
2195ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2196{
2197 struct opaque_lsa
2198 {
2199 struct lsa_header header;
2200 u_char data[1]; /* opaque data have variable length. This is start
2201 address */
2202 };
2203 struct opaque_lsa *olsa;
2204 int opaquelen;
2205
2206 olsa = (struct opaque_lsa *) lsa->data;
2207
2208 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002209 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002210 else
paul87d6f872004-09-24 08:01:38 +00002211 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002212
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;
ajse84cc642004-12-08 17:28:56 +00002232 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
paul2d33f152003-03-17 01:10:58 +00002233 opaquelen,
2234 VALID_OPAQUE_INFO_LEN (lsa->
2235 data) ? "" : "(Invalid length?)");
ajse84cc642004-12-08 17:28:56 +00002236 zlog_debug (" Opaque data: ");
paul2d33f152003-03-17 01:10:58 +00002237
2238 for (i = 0; i < opaquelen; i++)
2239 {
ajse84cc642004-12-08 17:28:56 +00002240 zlog_debug ("0x%x ", olsa->data[i]);
paul2d33f152003-03-17 01:10:58 +00002241 }
ajse84cc642004-12-08 17:28:56 +00002242 zlog_debug ("\n");
paul2d33f152003-03-17 01:10:58 +00002243 }
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{
paul87d6f872004-09-24 08:01:38 +00002259 struct listnode *node;
2260 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002261
2262 /* Send message to all clients */
paul87d6f872004-09-24 08:01:38 +00002263 LIST_LOOP (apiserver_list, apiserv, node)
2264 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002265}
2266
2267/* An interface is now ready to accept opaque LSAs. Notify all
2268 clients that registered to use this opaque type */
2269void
2270ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2271{
paul87d6f872004-09-24 08:01:38 +00002272 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002273 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002274 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002275
2276 assert (oi);
2277 if (!oi->address)
2278 {
2279 zlog_warn ("Interface has no address?");
2280 return;
2281 }
2282
2283 if (!ospf_apiserver_is_ready_type9 (oi))
2284 {
2285 zlog_warn ("Interface not ready for type 9?");
2286 return;
2287 }
2288
paul87d6f872004-09-24 08:01:38 +00002289 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002290 {
paul87d6f872004-09-24 08:01:38 +00002291 struct listnode *n2;
2292 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002293
paul87d6f872004-09-24 08:01:38 +00002294 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002295 {
paul2d33f152003-03-17 01:10:58 +00002296 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2297 {
2298 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2299 r->opaque_type,
2300 oi->address->u.prefix4);
2301 if (!msg)
2302 {
2303 zlog_warn
2304 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2305#ifdef NOTYET
2306 /* Cannot allocate new message. What should we do? */
2307 ospf_apiserver_free (apiserv);
2308#endif
2309 goto out;
2310 }
2311
2312 ospf_apiserver_send_msg (apiserv, msg);
2313 msg_free (msg);
2314 }
2315 }
2316 }
2317
2318out:
2319 return;
2320}
2321
2322void
2323ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2324{
paul87d6f872004-09-24 08:01:38 +00002325 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002326 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002327 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002328
2329 assert (area);
2330
2331 if (!ospf_apiserver_is_ready_type10 (area))
2332 {
2333 zlog_warn ("Area not ready for type 10?");
2334 return;
2335 }
2336
paul87d6f872004-09-24 08:01:38 +00002337 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002338 {
paul87d6f872004-09-24 08:01:38 +00002339 struct listnode *n2;
2340 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002341
paul87d6f872004-09-24 08:01:38 +00002342 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002343 {
paul2d33f152003-03-17 01:10:58 +00002344 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2345 {
2346 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2347 r->opaque_type, area->area_id);
2348 if (!msg)
2349 {
2350 zlog_warn
2351 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2352#ifdef NOTYET
2353 /* Cannot allocate new message. What should we do? */
2354 ospf_apiserver_free (apiserv);
2355#endif
paul87d6f872004-09-24 08:01:38 +00002356 goto out;
paul2d33f152003-03-17 01:10:58 +00002357 }
2358
2359 ospf_apiserver_send_msg (apiserv, msg);
2360 msg_free (msg);
2361 }
2362 }
2363 }
2364
2365out:
2366 return;
2367}
2368
2369
2370void
2371ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2372{
paul87d6f872004-09-24 08:01:38 +00002373 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002374 struct msg *msg;
2375 struct in_addr id_null = { 0L };
paul87d6f872004-09-24 08:01:38 +00002376 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002377
2378 assert (top);
2379
2380 if (!ospf_apiserver_is_ready_type11 (top))
2381 {
2382 zlog_warn ("AS not ready for type 11?");
2383 return;
2384 }
2385
paul87d6f872004-09-24 08:01:38 +00002386 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002387 {
paul87d6f872004-09-24 08:01:38 +00002388 struct listnode *n2;
2389 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002390
paul87d6f872004-09-24 08:01:38 +00002391 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002392 {
paul2d33f152003-03-17 01:10:58 +00002393 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2394 {
2395 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2396 r->opaque_type, id_null);
2397 if (!msg)
2398 {
2399 zlog_warn
2400 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2401#ifdef NOTYET
2402 /* Cannot allocate new message. What should we do? */
2403 ospf_apiserver_free (apiserv);
2404#endif
2405 goto out;
2406 }
2407
2408 ospf_apiserver_send_msg (apiserv, msg);
2409 msg_free (msg);
2410 }
2411 }
2412 }
2413
2414out:
2415 return;
2416}
2417
2418void
2419ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2420{
2421 struct msg *msg;
2422
2423 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2424 if (msg != NULL)
2425 {
2426 ospf_apiserver_clients_notify_all (msg);
2427 msg_free (msg);
2428 }
2429}
2430
2431void
2432ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2433{
2434 struct msg *msg;
2435
2436 msg = new_msg_del_if (0, oi->address->u.prefix4);
2437 if (msg != NULL)
2438 {
2439 ospf_apiserver_clients_notify_all (msg);
2440 msg_free (msg);
2441 }
2442}
2443
2444void
2445ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2446{
2447 struct msg *msg;
2448 struct in_addr ifaddr = { 0L };
2449 struct in_addr area_id = { 0L };
2450
2451 assert (oi);
2452 assert (oi->ifp);
2453
2454 if (oi->address)
2455 {
2456 ifaddr = oi->address->u.prefix4;
2457 }
2458 if (oi->area)
2459 {
2460 area_id = oi->area->area_id;
2461 }
2462
2463 msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status);
2464 if (!msg)
2465 {
2466 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2467 return;
2468 }
2469
2470 ospf_apiserver_clients_notify_all (msg);
2471 msg_free (msg);
2472}
2473
2474void
2475ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2476{
2477 struct msg *msg;
2478 struct in_addr ifaddr = { 0L };
2479 struct in_addr nbraddr = { 0L };
2480
2481 assert (nbr);
2482
2483 if (nbr->oi)
2484 {
2485 ifaddr = nbr->oi->address->u.prefix4;
2486 }
2487
2488 nbraddr = nbr->address.u.prefix4;
2489
2490 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2491 if (!msg)
2492 {
2493 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2494 return;
2495 }
2496
2497 ospf_apiserver_clients_notify_all (msg);
2498 msg_free (msg);
2499}
2500
2501void
2502apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2503{
2504 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002505 struct listnode *node;
2506 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002507
2508 /* Default area for AS-External and Opaque11 LSAs */
2509 struct in_addr area_id = { 0L };
2510
2511 /* Default interface for non Opaque9 LSAs */
2512 struct in_addr ifaddr = { 0L };
2513
2514 if (lsa->area)
2515 {
2516 area_id = lsa->area->area_id;
2517 }
2518 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2519 {
2520 assert (lsa->oi);
2521 ifaddr = lsa->oi->address->u.prefix4;
2522 }
2523
2524 /* Prepare message that can be sent to clients that have a matching
2525 filter */
2526 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2527 ifaddr, area_id,
2528 lsa->flags & OSPF_LSA_SELF, lsa->data);
2529 if (!msg)
2530 {
2531 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2532 return;
2533 }
2534
2535 /* Now send message to all clients with a matching filter */
paul87d6f872004-09-24 08:01:38 +00002536 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002537 {
paul2d33f152003-03-17 01:10:58 +00002538 struct lsa_filter_type *filter;
2539 u_int16_t mask;
2540 u_int32_t *area;
2541 int i;
2542
2543 /* Check filter for this client. */
2544 filter = apiserv->filter;
2545
2546 /* Check area IDs in case of non AS-E LSAs.
2547 * If filter has areas (num_areas > 0),
2548 * then one of the areas must match the area ID of this LSA. */
2549
2550 i = filter->num_areas;
2551 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2552 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2553 {
2554 i = 0;
2555 }
2556
2557 if (i > 0)
2558 {
2559 area = (u_int32_t *) (filter + 1);
2560 while (i)
2561 {
2562 if (*area == area_id.s_addr)
2563 {
2564 break;
2565 }
2566 i--;
2567 area++;
2568 }
2569 }
2570 else
2571 {
2572 i = 1;
2573 }
2574
2575 if (i > 0)
2576 {
2577 /* Area match. Check LSA type. */
2578 mask = ntohs (filter->typemask);
2579
2580 if (mask & Power2[lsa->data->type])
2581 {
2582 /* Type also matches. Check origin. */
2583 if ((filter->origin == ANY_ORIGIN) ||
2584 (filter->origin == IS_LSA_SELF (lsa)))
2585 {
2586 ospf_apiserver_send_msg (apiserv, msg);
2587 }
2588 }
2589 }
2590 }
2591 /* Free message since it is not used anymore */
2592 msg_free (msg);
2593}
2594
2595
2596/* -------------------------------------------------------------
2597 * Followings are hooks invoked when LSAs are updated or deleted
2598 * -------------------------------------------------------------
2599 */
2600
2601
2602int
2603apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2604{
2605 struct msg *msg;
2606 /* default area for AS-External and Opaque11 LSAs */
2607 struct in_addr area_id = { 0L };
2608
2609 /* default interface for non Opaque9 LSAs */
2610 struct in_addr ifaddr = { 0L };
2611
2612 /* Only notify this update if the LSA's age is smaller than
2613 MAXAGE. Otherwise clients would see LSA updates with max age just
2614 before they are deleted from the LSDB. LSA delete messages have
2615 MAXAGE too but should not be filtered. */
2616 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2617 return 0;
2618 }
2619
2620 if (lsa->area)
2621 {
2622 area_id = lsa->area->area_id;
2623 }
2624 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2625 {
2626 ifaddr = lsa->oi->address->u.prefix4;
2627 }
2628 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2629 ifaddr, area_id,
2630 lsa->flags & OSPF_LSA_SELF, lsa->data);
2631 if (!msg)
2632 {
2633 zlog_warn ("notify_clients_lsa: msg_new failed");
2634 return -1;
2635 }
2636 /* Notify all clients that new LSA is added/updated */
2637 apiserver_clients_lsa_change_notify (msgtype, lsa);
2638
2639 /* Clients made their own copies of msg so we can free msg here */
2640 msg_free (msg);
2641
2642 return 0;
2643}
2644
2645int
2646ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2647{
2648 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2649}
2650
2651int
2652ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2653{
2654 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2655}
2656
2657#endif /* SUPPORT_OSPF_API */
2658