blob: 784716b552c580db7ada0e1be4242f677e2455ca [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{
paul1eb8ef22005-04-07 07:30:20 +000086 struct listnode *node, *nnode;
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
paul1eb8ef22005-04-07 07:30:20 +000093 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +000094 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
95 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
96 return oi;
97
paul2d33f152003-03-17 01:10:58 +000098 return NULL;
99}
100
101struct ospf_interface *
102ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
103{
paul1eb8ef22005-04-07 07:30:20 +0000104 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +0000105 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +0000106 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000107
paulafbacce2003-07-09 16:09:20 +0000108 if (!(ospf = ospf_lookup ()));
paul5549c6b2003-07-09 15:46:33 +0000109 return NULL;
paul99b7c5d2003-04-06 01:19:28 +0000110
paul1eb8ef22005-04-07 07:30:20 +0000111 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +0000112 if (oi->ifp == ifp)
113 return oi;
114
paul2d33f152003-03-17 01:10:58 +0000115 return NULL;
116}
117
118/* -----------------------------------------------------------
119 * Initialization
120 * -----------------------------------------------------------
121 */
122
123unsigned short
124ospf_apiserver_getport (void)
125{
126 struct servent *sp = getservbyname ("ospfapi", "tcp");
127
128 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
129}
130
131/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
132int
133ospf_apiserver_init (void)
134{
135 int fd;
136 int rc = -1;
137
138 /* Create new socket for synchronous messages. */
139 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
140
141 if (fd < 0)
142 goto out;
143
144 /* Schedule new thread that handles accepted connections. */
145 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
146
147 /* Initialize list that keeps track of all connections. */
148 apiserver_list = list_new ();
149
150 /* Register opaque-independent call back functions. These functions
151 are invoked on ISM, NSM changes and LSA update and LSA deletes */
152 rc =
153 ospf_register_opaque_functab (0 /* all LSAs */,
154 0 /* all opaque types */,
155 ospf_apiserver_new_if,
156 ospf_apiserver_del_if,
157 ospf_apiserver_ism_change,
158 ospf_apiserver_nsm_change,
159 NULL,
160 NULL,
161 NULL,
162 NULL, /* ospf_apiserver_show_info */
163 NULL, /* originator_func */
164 NULL, /* ospf_apiserver_lsa_refresher */
165 ospf_apiserver_lsa_update,
166 ospf_apiserver_lsa_delete);
167 if (rc != 0)
168 {
169 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
170 }
171
172 rc = 0;
173
174out:
175 return rc;
176}
177
178/* Terminate OSPF API module. */
179void
180ospf_apiserver_term (void)
181{
paul87d6f872004-09-24 08:01:38 +0000182 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +0000183
184 /* Unregister wildcard [0/0] type */
185 ospf_delete_opaque_functab (0 /* all LSAs */,
186 0 /* all opaque types */);
187
gdt3fb9de72004-12-09 16:30:04 +0000188 /*
189 * Free all client instances. ospf_apiserver_free removes the node
190 * from the list, so we examine the head of the list anew each time.
191 */
paul1eb8ef22005-04-07 07:30:20 +0000192 while ( (apiserv = listgetdata (listhead (apiserver_list))) != NULL)
paul87d6f872004-09-24 08:01:38 +0000193 ospf_apiserver_free (apiserv);
paul2d33f152003-03-17 01:10:58 +0000194
195 /* Free client list itself */
196 list_delete (apiserver_list);
197
198 /* Free wildcard list */
199 /* XXX */
200}
201
202static struct ospf_apiserver *
203lookup_apiserver (u_char lsa_type, u_char opaque_type)
204{
paul87d6f872004-09-24 08:01:38 +0000205 struct listnode *n1, *n2;
paul2d33f152003-03-17 01:10:58 +0000206 struct registered_opaque_type *r;
207 struct ospf_apiserver *apiserv, *found = NULL;
208
paul87d6f872004-09-24 08:01:38 +0000209 /* XXX: this approaches O(n**2) */
paul1eb8ef22005-04-07 07:30:20 +0000210 for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv))
paul2d33f152003-03-17 01:10:58 +0000211 {
paul1eb8ef22005-04-07 07:30:20 +0000212 for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r))
213 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
214 {
215 found = apiserv;
216 goto out;
217 }
paul2d33f152003-03-17 01:10:58 +0000218 }
219out:
220 return found;
221}
222
223static struct ospf_apiserver *
224lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
225{
226 struct lsa_header *lsah = lsa->data;
227 struct ospf_apiserver *found = NULL;
228
229 if (IS_OPAQUE_LSA (lsah->type))
230 {
231 found = lookup_apiserver (lsah->type,
232 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
233 }
234 return found;
235}
236
237/* -----------------------------------------------------------
238 * Followings are functions to manage client connections.
239 * -----------------------------------------------------------
240 */
241static int
242ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
243{
244 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000245 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 +0000246 return 0;
247}
248
249static int
250ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
251{
252 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000253 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 +0000254 return 0;
255}
256
257/* Allocate new connection structure. */
258struct ospf_apiserver *
259ospf_apiserver_new (int fd_sync, int fd_async)
260{
261 struct ospf_apiserver *new =
262 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
263
264 new->filter =
265 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
266
267 new->fd_sync = fd_sync;
268 new->fd_async = fd_async;
269
270 /* list of registered opaque types that application uses */
271 new->opaque_types = list_new ();
272
273 /* Initialize temporary strage for LSA instances to be refreshed. */
274 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
275 ospf_lsdb_init (&new->reserve);
276
277 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
278 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
279
280 new->out_sync_fifo = msg_fifo_new ();
281 new->out_async_fifo = msg_fifo_new ();
282 new->t_sync_read = NULL;
283#ifdef USE_ASYNC_READ
284 new->t_async_read = NULL;
285#endif /* USE_ASYNC_READ */
286 new->t_sync_write = NULL;
287 new->t_async_write = NULL;
288
289 new->filter->typemask = 0; /* filter all LSAs */
290 new->filter->origin = ANY_ORIGIN;
291 new->filter->num_areas = 0;
292
293 return new;
294}
295
296void
297ospf_apiserver_event (enum event event, int fd,
298 struct ospf_apiserver *apiserv)
299{
300 struct thread *apiserver_serv_thread;
301
302 switch (event)
303 {
304 case OSPF_APISERVER_ACCEPT:
305 apiserver_serv_thread =
306 thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
307 break;
308 case OSPF_APISERVER_SYNC_READ:
309 apiserv->t_sync_read =
310 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
311 break;
312#ifdef USE_ASYNC_READ
313 case OSPF_APISERVER_ASYNC_READ:
314 apiserv->t_async_read =
315 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
316 break;
317#endif /* USE_ASYNC_READ */
318 case OSPF_APISERVER_SYNC_WRITE:
319 if (!apiserv->t_sync_write)
320 {
321 apiserv->t_sync_write =
322 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
323 }
324 break;
325 case OSPF_APISERVER_ASYNC_WRITE:
326 if (!apiserv->t_async_write)
327 {
328 apiserv->t_async_write =
329 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
330 }
331 break;
332 }
333}
334
335/* Free instance. First unregister all opaque types used by
336 application, flush opaque LSAs injected by application
337 from network and close connection. */
338void
339ospf_apiserver_free (struct ospf_apiserver *apiserv)
340{
paul87d6f872004-09-24 08:01:38 +0000341 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000342
343 /* Cancel read and write threads. */
344 if (apiserv->t_sync_read)
345 {
346 thread_cancel (apiserv->t_sync_read);
347 }
348#ifdef USE_ASYNC_READ
349 if (apiserv->t_async_read)
350 {
351 thread_cancel (apiserv->t_async_read);
352 }
353#endif /* USE_ASYNC_READ */
354 if (apiserv->t_sync_write)
355 {
356 thread_cancel (apiserv->t_sync_write);
357 }
358
359 if (apiserv->t_async_write)
360 {
361 thread_cancel (apiserv->t_async_write);
362 }
363
364 /* Unregister all opaque types that application registered
365 and flush opaque LSAs if still in LSDB. */
366
367 while ((node = listhead (apiserv->opaque_types)) != NULL)
368 {
paul1eb8ef22005-04-07 07:30:20 +0000369 struct registered_opaque_type *regtype = listgetdata(node);
paul2d33f152003-03-17 01:10:58 +0000370
371 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
372 regtype->opaque_type);
373
374 }
375
376 /* Close connections to OSPFd. */
377 if (apiserv->fd_sync > 0)
378 {
379 close (apiserv->fd_sync);
380 }
381
382 if (apiserv->fd_async > 0)
383 {
384 close (apiserv->fd_async);
385 }
386
387 /* Free fifos */
388 msg_fifo_free (apiserv->out_sync_fifo);
389 msg_fifo_free (apiserv->out_async_fifo);
390
391 /* Clear temporary strage for LSA instances to be refreshed. */
392 ospf_lsdb_delete_all (&apiserv->reserve);
393 ospf_lsdb_cleanup (&apiserv->reserve);
394
395 /* Remove from the list of active clients. */
396 listnode_delete (apiserver_list, apiserv);
397
398 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000399 zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000400
401 /* And free instance. */
402 XFREE (MTYPE_OSPF_APISERVER, apiserv);
403}
404
405int
406ospf_apiserver_read (struct thread *thread)
407{
408 struct ospf_apiserver *apiserv;
409 struct msg *msg;
410 int fd;
411 int rc = -1;
412 enum event event;
413
414 apiserv = THREAD_ARG (thread);
415 fd = THREAD_FD (thread);
416
417 if (fd == apiserv->fd_sync)
418 {
419 event = OSPF_APISERVER_SYNC_READ;
420 apiserv->t_sync_read = NULL;
421
422 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000423 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000424 inet_ntoa (apiserv->peer_sync.sin_addr),
425 ntohs (apiserv->peer_sync.sin_port));
426 }
427#ifdef USE_ASYNC_READ
428 else if (fd == apiserv->fd_async)
429 {
430 event = OSPF_APISERVER_ASYNC_READ;
431 apiserv->t_async_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_async.sin_addr),
436 ntohs (apiserv->peer_async.sin_port));
437 }
438#endif /* USE_ASYNC_READ */
439 else
440 {
441 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
442 ospf_apiserver_free (apiserv);
443 goto out;
444 }
445
446 /* Read message from fd. */
447 msg = msg_read (fd);
448 if (msg == NULL)
449 {
450 zlog_warn
451 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
452
453 /* Perform cleanup. */
454 ospf_apiserver_free (apiserv);
455 goto out;
456 }
457
458 if (IS_DEBUG_OSPF_EVENT)
459 msg_print (msg);
460
461 /* Dispatch to corresponding message handler. */
462 rc = ospf_apiserver_handle_msg (apiserv, msg);
463
464 /* Prepare for next message, add read thread. */
465 ospf_apiserver_event (event, fd, apiserv);
466
467 msg_free (msg);
468
469out:
470 return rc;
471}
472
473int
474ospf_apiserver_sync_write (struct thread *thread)
475{
476 struct ospf_apiserver *apiserv;
477 struct msg *msg;
478 int fd;
479 int rc = -1;
480
481 apiserv = THREAD_ARG (thread);
482 assert (apiserv);
483 fd = THREAD_FD (thread);
484
485 apiserv->t_sync_write = NULL;
486
487 /* Sanity check */
488 if (fd != apiserv->fd_sync)
489 {
490 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
491 goto out;
492 }
493
494 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000495 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000496 inet_ntoa (apiserv->peer_sync.sin_addr),
497 ntohs (apiserv->peer_sync.sin_port));
498
499 /* Check whether there is really a message in the fifo. */
500 msg = msg_fifo_pop (apiserv->out_sync_fifo);
501 if (!msg)
502 {
503 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
504 return 0;
505 }
506
507 if (IS_DEBUG_OSPF_EVENT)
508 msg_print (msg);
509
510 rc = msg_write (fd, msg);
511
512 /* Once a message is dequeued, it should be freed anyway. */
513 msg_free (msg);
514
515 if (rc < 0)
516 {
517 zlog_warn
518 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
519 goto out;
520 }
521
522
523 /* If more messages are in sync message fifo, schedule write thread. */
524 if (msg_fifo_head (apiserv->out_sync_fifo))
525 {
526 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
527 apiserv);
528 }
529
530 out:
531
532 if (rc < 0)
533 {
534 /* Perform cleanup and disconnect with peer */
535 ospf_apiserver_free (apiserv);
536 }
537
538 return rc;
539}
540
541
542int
543ospf_apiserver_async_write (struct thread *thread)
544{
545 struct ospf_apiserver *apiserv;
546 struct msg *msg;
547 int fd;
548 int rc = -1;
549
550 apiserv = THREAD_ARG (thread);
551 assert (apiserv);
552 fd = THREAD_FD (thread);
553
554 apiserv->t_async_write = NULL;
555
556 /* Sanity check */
557 if (fd != apiserv->fd_async)
558 {
559 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
560 goto out;
561 }
562
563 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000564 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000565 inet_ntoa (apiserv->peer_async.sin_addr),
566 ntohs (apiserv->peer_async.sin_port));
567
568 /* Check whether there is really a message in the fifo. */
569 msg = msg_fifo_pop (apiserv->out_async_fifo);
570 if (!msg)
571 {
572 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
573 return 0;
574 }
575
576 if (IS_DEBUG_OSPF_EVENT)
577 msg_print (msg);
578
579 rc = msg_write (fd, msg);
580
581 /* Once a message is dequeued, it should be freed anyway. */
582 msg_free (msg);
583
584 if (rc < 0)
585 {
586 zlog_warn
587 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
588 goto out;
589 }
590
591
592 /* If more messages are in async message fifo, schedule write thread. */
593 if (msg_fifo_head (apiserv->out_async_fifo))
594 {
595 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
596 apiserv);
597 }
598
599 out:
600
601 if (rc < 0)
602 {
603 /* Perform cleanup and disconnect with peer */
604 ospf_apiserver_free (apiserv);
605 }
606
607 return rc;
608}
609
610
611int
612ospf_apiserver_serv_sock_family (unsigned short port, int family)
613{
614 union sockunion su;
615 int accept_sock;
616 int rc;
617
618 memset (&su, 0, sizeof (union sockunion));
619 su.sa.sa_family = family;
620
621 /* Make new socket */
622 accept_sock = sockunion_stream_socket (&su);
623 if (accept_sock < 0)
624 return accept_sock;
625
626 /* This is a server, so reuse address and port */
627 sockopt_reuseaddr (accept_sock);
628 sockopt_reuseport (accept_sock);
629
630 /* Bind socket to address and given port. */
631 rc = sockunion_bind (accept_sock, &su, port, NULL);
632 if (rc < 0)
633 {
634 close (accept_sock); /* Close socket */
635 return rc;
636 }
637
638 /* Listen socket under queue length 3. */
639 rc = listen (accept_sock, 3);
640 if (rc < 0)
641 {
642 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
ajs6099b3b2004-11-20 02:06:59 +0000643 safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000644 close (accept_sock); /* Close socket */
645 return rc;
646 }
647 return accept_sock;
648}
649
650
651/* Accept connection request from external applications. For each
652 accepted connection allocate own connection instance. */
653int
654ospf_apiserver_accept (struct thread *thread)
655{
656 int accept_sock;
657 int new_sync_sock;
658 int new_async_sock;
659 union sockunion su;
660 struct ospf_apiserver *apiserv;
661 struct sockaddr_in peer_async;
662 struct sockaddr_in peer_sync;
paul36238142005-10-11 04:12:54 +0000663 unsigned int peerlen;
paul2d33f152003-03-17 01:10:58 +0000664 int ret;
665
666 /* THREAD_ARG (thread) is NULL */
667 accept_sock = THREAD_FD (thread);
668
669 /* Keep hearing on socket for further connections. */
670 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
671
672 memset (&su, 0, sizeof (union sockunion));
673 /* Accept connection for synchronous messages */
674 new_sync_sock = sockunion_accept (accept_sock, &su);
675 if (new_sync_sock < 0)
676 {
ajs6099b3b2004-11-20 02:06:59 +0000677 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000678 return -1;
679 }
680
681 /* Get port address and port number of peer to make reverse connection.
682 The reverse channel uses the port number of the peer port+1. */
683
684 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
685 peerlen = sizeof (struct sockaddr_in);
686
687 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
688 if (ret < 0)
689 {
ajs6099b3b2004-11-20 02:06:59 +0000690 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000691 close (new_sync_sock);
692 return -1;
693 }
694
695 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000696 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000697 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
698
699 /* Create new socket for asynchronous messages. */
700 peer_async = peer_sync;
701 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
702
703 /* Check if remote port number to make reverse connection is valid one. */
704 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
705 {
706 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
707 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
708 close (new_sync_sock);
709 return -1;
710 }
711
712 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
713 if (new_async_sock < 0)
714 {
ajs6099b3b2004-11-20 02:06:59 +0000715 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000716 close (new_sync_sock);
717 return -1;
718 }
719
720 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
721 sizeof (struct sockaddr_in));
722
723 if (ret < 0)
724 {
ajs6099b3b2004-11-20 02:06:59 +0000725 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000726 close (new_sync_sock);
727 close (new_async_sock);
728 return -1;
729 }
730
731#ifdef USE_ASYNC_READ
732#else /* USE_ASYNC_READ */
733 /* Make the asynchronous channel write-only. */
734 ret = shutdown (new_async_sock, SHUT_RD);
735 if (ret < 0)
736 {
ajs6099b3b2004-11-20 02:06:59 +0000737 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000738 close (new_sync_sock);
739 close (new_async_sock);
740 return -1;
741 }
742#endif /* USE_ASYNC_READ */
743
744 /* Allocate new server-side connection structure */
745 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
746
747 /* Add to active connection list */
748 listnode_add (apiserver_list, apiserv);
749 apiserv->peer_sync = peer_sync;
750 apiserv->peer_async = peer_async;
751
752 /* And add read threads for new connection */
753 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
754#ifdef USE_ASYNC_READ
755 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
756#endif /* USE_ASYNC_READ */
757
758 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000759 zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000760
761 return 0;
762}
763
764
765/* -----------------------------------------------------------
766 * Send reply with return code to client application
767 * -----------------------------------------------------------
768 */
769
paul4dadc292005-05-06 21:37:42 +0000770static int
paul2d33f152003-03-17 01:10:58 +0000771ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
772{
773 struct msg_fifo *fifo;
774 struct msg *msg2;
775 enum event event;
776 int fd;
777
778 switch (msg->hdr.msgtype)
779 {
780 case MSG_REPLY:
781 fifo = apiserv->out_sync_fifo;
782 fd = apiserv->fd_sync;
783 event = OSPF_APISERVER_SYNC_WRITE;
784 break;
785 case MSG_READY_NOTIFY:
786 case MSG_LSA_UPDATE_NOTIFY:
787 case MSG_LSA_DELETE_NOTIFY:
788 case MSG_NEW_IF:
789 case MSG_DEL_IF:
790 case MSG_ISM_CHANGE:
791 case MSG_NSM_CHANGE:
792 fifo = apiserv->out_async_fifo;
793 fd = apiserv->fd_async;
794 event = OSPF_APISERVER_ASYNC_WRITE;
795 break;
796 default:
797 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
798 msg->hdr.msgtype);
799 return -1;
800 }
801
802 /* Make a copy of the message and put in the fifo. Once the fifo
803 gets drained by the write thread, the message will be freed. */
804 /* NB: Given "msg" is untouched in this function. */
805 msg2 = msg_dup (msg);
806
807 /* Enqueue message into corresponding fifo queue */
808 msg_fifo_push (fifo, msg2);
809
810 /* Schedule write thread */
811 ospf_apiserver_event (event, fd, apiserv);
812 return 0;
813}
814
815int
816ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
817 u_char rc)
818{
819 struct msg *msg = new_msg_reply (seqnr, rc);
820 int ret;
821
822 if (!msg)
823 {
824 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
825#ifdef NOTYET
826 /* Cannot allocate new message. What should we do? */
827 ospf_apiserver_free (apiserv);
828#endif
829 return -1;
830 }
831
832 ret = ospf_apiserver_send_msg (apiserv, msg);
833 msg_free (msg);
834 return ret;
835}
836
837
838/* -----------------------------------------------------------
839 * Generic message dispatching handler function
840 * -----------------------------------------------------------
841 */
842
843int
844ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
845{
846 int rc;
847
848 /* Call corresponding message handler function. */
849 switch (msg->hdr.msgtype)
850 {
851 case MSG_REGISTER_OPAQUETYPE:
852 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
853 break;
854 case MSG_UNREGISTER_OPAQUETYPE:
855 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
856 break;
857 case MSG_REGISTER_EVENT:
858 rc = ospf_apiserver_handle_register_event (apiserv, msg);
859 break;
860 case MSG_SYNC_LSDB:
861 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
862 break;
863 case MSG_ORIGINATE_REQUEST:
864 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
865 break;
866 case MSG_DELETE_REQUEST:
867 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
868 break;
869 default:
870 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
871 msg->hdr.msgtype);
872 rc = -1;
873 }
874 return rc;
875}
876
877
878/* -----------------------------------------------------------
879 * Following are functions for opaque type registration
880 * -----------------------------------------------------------
881 */
882
883int
884ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
885 u_char lsa_type, u_char opaque_type)
886{
887 struct registered_opaque_type *regtype;
888 int (*originator_func) (void *arg);
889 int rc;
890
891 switch (lsa_type)
892 {
893 case OSPF_OPAQUE_LINK_LSA:
894 originator_func = ospf_apiserver_lsa9_originator;
895 break;
896 case OSPF_OPAQUE_AREA_LSA:
897 originator_func = ospf_apiserver_lsa10_originator;
898 break;
899 case OSPF_OPAQUE_AS_LSA:
900 originator_func = ospf_apiserver_lsa11_originator;
901 break;
902 default:
903 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
904 lsa_type);
905 return OSPF_API_ILLEGALLSATYPE;
906 }
907
908
909 /* Register opaque function table */
910 /* NB: Duplicated registration will be detected inside the function. */
911 rc =
912 ospf_register_opaque_functab (lsa_type, opaque_type,
913 NULL, /* ospf_apiserver_new_if */
914 NULL, /* ospf_apiserver_del_if */
915 NULL, /* ospf_apiserver_ism_change */
916 NULL, /* ospf_apiserver_nsm_change */
917 NULL,
918 NULL,
919 NULL,
920 ospf_apiserver_show_info,
921 originator_func,
922 ospf_apiserver_lsa_refresher,
923 NULL, /* ospf_apiserver_lsa_update */
924 NULL /* ospf_apiserver_lsa_delete */);
925
926 if (rc != 0)
927 {
928 zlog_warn ("Failed to register opaque type [%d/%d]",
929 lsa_type, opaque_type);
930 return OSPF_API_OPAQUETYPEINUSE;
931 }
932
933 /* Remember the opaque type that application registers so when
934 connection shuts down, we can flush all LSAs of this opaque
935 type. */
936
937 regtype =
938 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
939 memset (regtype, 0, sizeof (struct registered_opaque_type));
940 regtype->lsa_type = lsa_type;
941 regtype->opaque_type = opaque_type;
942
943 /* Add to list of registered opaque types */
944 listnode_add (apiserv->opaque_types, regtype);
945
946 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000947 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
paul87d6f872004-09-24 08:01:38 +0000948 " apiserv(%p), total#(%d)",
949 lsa_type, opaque_type, apiserv,
950 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000951
952 return 0;
953}
954
955int
956ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
957 u_char lsa_type, u_char opaque_type)
958{
paul1eb8ef22005-04-07 07:30:20 +0000959 struct listnode *node, *nnode;
gdt54ade992004-10-07 19:38:20 +0000960 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000961
paul1eb8ef22005-04-07 07:30:20 +0000962 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +0000963 {
paul2d33f152003-03-17 01:10:58 +0000964 /* Check if we really registered this opaque type */
965 if (regtype->lsa_type == lsa_type &&
966 regtype->opaque_type == opaque_type)
967 {
968
969 /* Yes, we registered this opaque type. Flush
970 all existing opaque LSAs of this type */
971
972 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
973 ospf_delete_opaque_functab (lsa_type, opaque_type);
974
975 /* Remove from list of registered opaque types */
976 listnode_delete (apiserv->opaque_types, regtype);
977
978 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000979 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
paul87d6f872004-09-24 08:01:38 +0000980 " from apiserv(%p), total#(%d)",
981 lsa_type, opaque_type, apiserv,
982 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000983
984 return 0;
985 }
986 }
987
988 /* Opaque type is not registered */
989 zlog_warn ("Failed to unregister opaque type [%d/%d]",
990 lsa_type, opaque_type);
991 return OSPF_API_OPAQUETYPENOTREGISTERED;
992}
993
994
paul4dadc292005-05-06 21:37:42 +0000995static int
paul2d33f152003-03-17 01:10:58 +0000996apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
997 u_char lsa_type, u_char opaque_type)
998{
paul1eb8ef22005-04-07 07:30:20 +0000999 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001000 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001001
paul87d6f872004-09-24 08:01:38 +00001002 /* XXX: how many types are there? if few, why not just a bitmap? */
paul1eb8ef22005-04-07 07:30:20 +00001003 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +00001004 {
paul2d33f152003-03-17 01:10:58 +00001005 /* Check if we really registered this opaque type */
1006 if (regtype->lsa_type == lsa_type &&
1007 regtype->opaque_type == opaque_type)
1008 {
1009 /* Yes registered */
1010 return 1;
1011 }
1012 }
1013 /* Not registered */
1014 return 0;
1015}
1016
1017int
1018ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1019 struct msg *msg)
1020{
1021 struct msg_register_opaque_type *rmsg;
1022 u_char lsa_type;
1023 u_char opaque_type;
1024 int rc = 0;
1025
1026 /* Extract parameters from register opaque type message */
1027 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1028
1029 lsa_type = rmsg->lsatype;
1030 opaque_type = rmsg->opaquetype;
1031
1032 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1033
1034 /* Send a reply back to client including return code */
1035 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1036 if (rc < 0)
1037 goto out;
1038
1039 /* Now inform application about opaque types that are ready */
1040 switch (lsa_type)
1041 {
1042 case OSPF_OPAQUE_LINK_LSA:
1043 ospf_apiserver_notify_ready_type9 (apiserv);
1044 break;
1045 case OSPF_OPAQUE_AREA_LSA:
1046 ospf_apiserver_notify_ready_type10 (apiserv);
1047 break;
1048 case OSPF_OPAQUE_AS_LSA:
1049 ospf_apiserver_notify_ready_type11 (apiserv);
1050 break;
1051 }
1052out:
1053 return rc;
1054}
1055
1056
1057/* Notify specific client about all opaque types 9 that are ready. */
1058void
1059ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1060{
paul1eb8ef22005-04-07 07:30:20 +00001061 struct listnode *node, *nnode;
1062 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001063 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001064 struct ospf_interface *oi;
1065 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001066
paul99b7c5d2003-04-06 01:19:28 +00001067 ospf = ospf_lookup ();
1068
paul1eb8ef22005-04-07 07:30:20 +00001069 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul2d33f152003-03-17 01:10:58 +00001070 {
paul2d33f152003-03-17 01:10:58 +00001071 /* Check if this interface is indeed ready for type 9 */
1072 if (!ospf_apiserver_is_ready_type9 (oi))
1073 continue;
1074
1075 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001076 /* XXX: loop-de-loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001077 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001078 {
paul2d33f152003-03-17 01:10:58 +00001079 struct msg *msg;
1080
1081 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1082 {
1083
1084 /* Yes, this opaque type is ready */
1085 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1086 r->opaque_type,
1087 oi->address->u.prefix4);
1088 if (!msg)
1089 {
1090 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1091#ifdef NOTYET
1092 /* Cannot allocate new message. What should we do? */
1093 ospf_apiserver_free (apiserv);
1094#endif
1095 goto out;
1096 }
1097 ospf_apiserver_send_msg (apiserv, msg);
1098 msg_free (msg);
1099 }
1100 }
1101 }
1102
1103out:
1104 return;
1105}
1106
1107
1108/* Notify specific client about all opaque types 10 that are ready. */
1109void
1110ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1111{
paul1eb8ef22005-04-07 07:30:20 +00001112 struct listnode *node, *nnode;
1113 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001114 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001115 struct ospf_area *area;
1116
paul99b7c5d2003-04-06 01:19:28 +00001117 ospf = ospf_lookup ();
1118
paul1eb8ef22005-04-07 07:30:20 +00001119 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001120 {
paul87d6f872004-09-24 08:01:38 +00001121 struct registered_opaque_type *r;
1122
paul2d33f152003-03-17 01:10:58 +00001123 if (!ospf_apiserver_is_ready_type10 (area))
1124 {
1125 continue;
1126 }
1127
1128 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001129 /* XXX: loop in loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001130 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001131 {
paul2d33f152003-03-17 01:10:58 +00001132 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001133
paul2d33f152003-03-17 01:10:58 +00001134 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1135 {
1136 /* Yes, this opaque type is ready */
1137 msg =
1138 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1139 r->opaque_type, area->area_id);
1140 if (!msg)
1141 {
1142 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1143#ifdef NOTYET
1144 /* Cannot allocate new message. What should we do? */
1145 ospf_apiserver_free (apiserv);
1146#endif
1147 goto out;
1148 }
1149 ospf_apiserver_send_msg (apiserv, msg);
1150 msg_free (msg);
1151 }
1152 }
1153 }
1154
1155out:
1156 return;
1157}
1158
1159/* Notify specific client about all opaque types 11 that are ready */
1160void
1161ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1162{
paul1eb8ef22005-04-07 07:30:20 +00001163 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00001164 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001165 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001166
1167 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001168
1169 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001170 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001171 goto out;
paul2d33f152003-03-17 01:10:58 +00001172
1173 /* Check for registered opaque type 11 types */
paul1eb8ef22005-04-07 07:30:20 +00001174 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
paul2d33f152003-03-17 01:10:58 +00001175 {
paul2d33f152003-03-17 01:10:58 +00001176 struct msg *msg;
paul36238142005-10-11 04:12:54 +00001177 struct in_addr noarea_id = { .s_addr = 0L };
1178
paul2d33f152003-03-17 01:10:58 +00001179 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1180 {
1181 /* Yes, this opaque type is ready */
1182 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1183 r->opaque_type, noarea_id);
1184
1185 if (!msg)
1186 {
1187 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1188#ifdef NOTYET
1189 /* Cannot allocate new message. What should we do? */
1190 ospf_apiserver_free (apiserv);
1191#endif
1192 goto out;
1193 }
1194 ospf_apiserver_send_msg (apiserv, msg);
1195 msg_free (msg);
1196 }
1197 }
1198
1199out:
1200 return;
1201}
1202
1203int
1204ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1205 struct msg *msg)
1206{
1207 struct msg_unregister_opaque_type *umsg;
1208 u_char ltype;
1209 u_char otype;
1210 int rc = 0;
1211
1212 /* Extract parameters from unregister opaque type message */
1213 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1214
1215 ltype = umsg->lsatype;
1216 otype = umsg->opaquetype;
1217
1218 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1219
1220 /* Send a reply back to client including return code */
1221 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1222
1223 return rc;
1224}
1225
1226
1227/* -----------------------------------------------------------
1228 * Following are functions for event (filter) registration.
1229 * -----------------------------------------------------------
1230 */
1231int
1232ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1233 struct msg *msg)
1234{
1235 struct msg_register_event *rmsg;
1236 int rc;
1237 u_int32_t seqnum;
1238
1239 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1240
1241 /* Get request sequence number */
1242 seqnum = msg_get_seq (msg);
1243
1244 /* Free existing filter in apiserv. */
1245 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1246 /* Alloc new space for filter. */
1247
1248 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1249 ntohs (msg->hdr.msglen));
1250 if (apiserv->filter)
1251 {
1252 /* copy it over. */
1253 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1254 rc = OSPF_API_OK;
1255 }
1256 else
1257 {
1258 rc = OSPF_API_NOMEMORY;
1259 }
1260 /* Send a reply back to client with return code */
1261 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1262 return rc;
1263}
1264
1265
1266/* -----------------------------------------------------------
1267 * Followings are functions for LSDB synchronization.
1268 * -----------------------------------------------------------
1269 */
1270
paul4dadc292005-05-06 21:37:42 +00001271static int
paul2d33f152003-03-17 01:10:58 +00001272apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1273{
1274 struct ospf_apiserver *apiserv;
1275 int seqnum;
1276 struct msg *msg;
1277 struct param_t
1278 {
1279 struct ospf_apiserver *apiserv;
1280 struct lsa_filter_type *filter;
1281 }
1282 *param;
1283 int rc = -1;
1284
1285 /* Sanity check */
1286 assert (lsa->data);
1287 assert (p_arg);
1288
1289 param = (struct param_t *) p_arg;
1290 apiserv = param->apiserv;
1291 seqnum = (u_int32_t) int_arg;
1292
1293 /* Check origin in filter. */
1294 if ((param->filter->origin == ANY_ORIGIN) ||
1295 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1296 {
1297
1298 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00001299 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00001300
1301 /* Default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00001302 struct in_addr ifaddr = { .s_addr = 0L };;
1303
paul2d33f152003-03-17 01:10:58 +00001304 if (lsa->area)
1305 {
1306 area_id = lsa->area->area_id;
1307 }
1308 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1309 {
1310 ifaddr = lsa->oi->address->u.prefix4;
1311 }
1312
1313 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1314 seqnum,
1315 ifaddr, area_id,
1316 lsa->flags & OSPF_LSA_SELF, lsa->data);
1317 if (!msg)
1318 {
1319 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1320#ifdef NOTYET
1321 /* Cannot allocate new message. What should we do? */
1322/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1323#endif
1324 goto out;
1325 }
1326
1327 /* Send LSA */
1328 ospf_apiserver_send_msg (apiserv, msg);
1329 msg_free (msg);
1330 }
1331 rc = 0;
1332
1333out:
1334 return rc;
1335}
1336
1337int
1338ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1339 struct msg *msg)
1340{
paul1eb8ef22005-04-07 07:30:20 +00001341 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00001342 u_int32_t seqnum;
1343 int rc = 0;
1344 struct msg_sync_lsdb *smsg;
paul1eb8ef22005-04-07 07:30:20 +00001345 struct ospf_apiserver_param_t
paul2d33f152003-03-17 01:10:58 +00001346 {
1347 struct ospf_apiserver *apiserv;
1348 struct lsa_filter_type *filter;
paul1eb8ef22005-04-07 07:30:20 +00001349 } param;
paul2d33f152003-03-17 01:10:58 +00001350 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001351 struct route_node *rn;
1352 struct ospf_lsa *lsa;
1353 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001354 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001355
1356 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001357
1358 /* Get request sequence number */
1359 seqnum = msg_get_seq (msg);
1360 /* Set sync msg. */
1361 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1362
1363 /* Set parameter struct. */
1364 param.apiserv = apiserv;
1365 param.filter = &smsg->filter;
1366
1367 /* Remember mask. */
1368 mask = ntohs (smsg->filter.typemask);
1369
1370 /* Iterate over all areas. */
paul1eb8ef22005-04-07 07:30:20 +00001371 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001372 {
paul2d33f152003-03-17 01:10:58 +00001373 int i;
1374 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001375
paul2d33f152003-03-17 01:10:58 +00001376 /* Compare area_id with area_ids in sync request. */
1377 if ((i = smsg->filter.num_areas) > 0)
1378 {
1379 /* Let area_id point to the list of area IDs,
1380 * which is at the end of smsg->filter. */
1381 area_id = (u_int32_t *) (&smsg->filter + 1);
1382 while (i)
1383 {
1384 if (*area_id == area->area_id.s_addr)
1385 {
1386 break;
1387 }
1388 i--;
1389 area_id++;
1390 }
1391 }
1392 else
1393 {
1394 i = 1;
1395 }
1396
1397 /* If area was found, then i>0 here. */
1398 if (i)
1399 {
1400 /* Check msg type. */
1401 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001402 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1403 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001404 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001405 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1406 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001407 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001408 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1409 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001410 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001411 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1412 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001413 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001414 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1415 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001416 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001417 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1418 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001419 }
1420 }
1421
1422 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001423 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001424 {
1425 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001426 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1427 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001428 }
1429
1430 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001431 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001432 {
1433 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001434 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1435 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001436 }
1437
1438 /* Send a reply back to client with return code */
1439 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1440 return rc;
1441}
1442
1443
1444/* -----------------------------------------------------------
1445 * Followings are functions to originate or update LSA
1446 * from an application.
1447 * -----------------------------------------------------------
1448 */
1449
1450/* Create a new internal opaque LSA by taking prototype and filling in
1451 missing fields such as age, sequence number, advertising router,
1452 checksum and so on. The interface parameter is used for type 9
1453 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1454 nor interface. */
1455
1456struct ospf_lsa *
1457ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1458 struct ospf_interface *oi,
1459 struct lsa_header *protolsa)
1460{
1461 struct stream *s;
1462 struct lsa_header *newlsa;
1463 struct ospf_lsa *new = NULL;
1464 u_char options = 0x0;
1465 u_int16_t length;
1466
paul99b7c5d2003-04-06 01:19:28 +00001467 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001468
paul99b7c5d2003-04-06 01:19:28 +00001469 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001470 assert(ospf);
1471
paul2d33f152003-03-17 01:10:58 +00001472 /* Create a stream for internal opaque LSA */
1473 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1474 {
1475 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1476 return NULL;
1477 }
1478
1479 newlsa = (struct lsa_header *) STREAM_DATA (s);
1480
1481 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1482 have to set options? */
1483
1484 if (area)
1485 {
1486 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001487 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001488 }
1489
1490 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1491
1492 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1493 {
ajse84cc642004-12-08 17:28:56 +00001494 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
paul2d33f152003-03-17 01:10:58 +00001495 protolsa->type, inet_ntoa (protolsa->id));
1496 }
1497
1498 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001499 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001500 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001501
1502 /* Set opaque-LSA body fields. */
1503 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1504 ntohs (protolsa->length) - sizeof (struct lsa_header));
1505
1506 /* Determine length of LSA. */
1507 length = stream_get_endp (s);
1508 newlsa->length = htons (length);
1509
1510 /* Create OSPF LSA. */
1511 if ((new = ospf_lsa_new ()) == NULL)
1512 {
1513 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1514 stream_free (s);
1515 return NULL;
1516 }
1517
1518 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1519 {
1520 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
paul788dab12004-11-15 11:48:37 +00001521 ospf_lsa_unlock (new);
paul2d33f152003-03-17 01:10:58 +00001522 stream_free (s);
1523 return NULL;
1524 }
1525
1526 new->area = area;
1527 new->oi = oi;
1528
1529 SET_FLAG (new->flags, OSPF_LSA_SELF);
1530 memcpy (new->data, newlsa, length);
1531 stream_free (s);
1532
1533 return new;
1534}
1535
1536
1537int
1538ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1539{
1540 /* Type 9 opaque LSA can be originated if there is at least one
1541 active opaque-capable neighbor attached to the outgoing
1542 interface. */
1543
paula15f45d2003-03-28 01:50:03 +00001544 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001545}
1546
1547int
1548ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1549{
1550 /* Type 10 opaque LSA can be originated if there is at least one
1551 interface belonging to the area that has an active opaque-capable
1552 neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001553 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001554 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001555
paul1eb8ef22005-04-07 07:30:20 +00001556 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001557 /* Is there an active neighbor attached to this interface? */
1558 if (ospf_apiserver_is_ready_type9 (oi))
1559 return 1;
paul2d33f152003-03-17 01:10:58 +00001560
paul2d33f152003-03-17 01:10:58 +00001561 /* No active neighbor in area */
1562 return 0;
1563}
1564
1565int
1566ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1567{
1568 /* Type 11 opaque LSA can be originated if there is at least one interface
1569 that has an active opaque-capable neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001570 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001571 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001572
paul1eb8ef22005-04-07 07:30:20 +00001573 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001574 /* Is there an active neighbor attached to this interface? */
1575 if (ospf_apiserver_is_ready_type9 (oi))
1576 return 1;
paul2d33f152003-03-17 01:10:58 +00001577
paul2d33f152003-03-17 01:10:58 +00001578 /* No active neighbor at all */
1579 return 0;
1580}
1581
1582
1583int
1584ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1585 struct msg *msg)
1586{
1587 struct msg_originate_request *omsg;
1588 struct lsa_header *data;
1589 struct ospf_lsa *new;
1590 struct ospf_lsa *old;
1591 struct ospf_area *area = NULL;
1592 struct ospf_interface *oi = NULL;
1593 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001594 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001595 int lsa_type, opaque_type;
1596 int ready = 0;
1597 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001598
paul99b7c5d2003-04-06 01:19:28 +00001599 ospf = ospf_lookup();
1600
paul2d33f152003-03-17 01:10:58 +00001601 /* Extract opaque LSA data from message */
1602 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1603 data = &omsg->data;
1604
1605 /* Determine interface for type9 or area for type10 LSAs. */
1606 switch (data->type)
1607 {
1608 case OSPF_OPAQUE_LINK_LSA:
1609 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1610 if (!oi)
1611 {
1612 zlog_warn ("apiserver_originate: unknown interface %s",
1613 inet_ntoa (omsg->ifaddr));
1614 rc = OSPF_API_NOSUCHINTERFACE;
1615 goto out;
1616 }
1617 area = oi->area;
1618 lsdb = area->lsdb;
1619 break;
1620 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001621 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001622 if (!area)
1623 {
1624 zlog_warn ("apiserver_originate: unknown area %s",
1625 inet_ntoa (omsg->area_id));
1626 rc = OSPF_API_NOSUCHAREA;
1627 goto out;
1628 }
1629 lsdb = area->lsdb;
1630 break;
1631 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001632 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001633 break;
1634 default:
1635 /* We can only handle opaque types here */
1636 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1637 data->type);
1638 rc = OSPF_API_ILLEGALLSATYPE;
1639 goto out;
1640 }
1641
1642 /* Check if we registered this opaque type */
1643 lsa_type = data->type;
1644 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1645
1646 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1647 {
1648 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1649 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1650 goto out;
1651 }
1652
1653 /* Make sure that the neighbors are ready before we can originate */
1654 switch (data->type)
1655 {
1656 case OSPF_OPAQUE_LINK_LSA:
1657 ready = ospf_apiserver_is_ready_type9 (oi);
1658 break;
1659 case OSPF_OPAQUE_AREA_LSA:
1660 ready = ospf_apiserver_is_ready_type10 (area);
1661 break;
1662 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001663 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001664 break;
1665 default:
1666 break;
1667 }
1668
1669 if (!ready)
1670 {
1671 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1672 rc = OSPF_API_NOTREADY;
1673 goto out;
1674 }
1675
1676 /* Create OSPF's internal opaque LSA representation */
1677 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1678 if (!new)
1679 {
1680 rc = OSPF_API_NOMEMORY; /* XXX */
1681 goto out;
1682 }
1683
1684 /* Determine if LSA is new or an update for an existing one. */
1685 old = ospf_lsdb_lookup (lsdb, new);
1686
1687 if (!old)
1688 {
1689 /* New LSA install in LSDB. */
1690 rc = ospf_apiserver_originate1 (new);
1691 }
1692 else
1693 {
1694 /*
1695 * Keep the new LSA instance in the "waiting place" until the next
1696 * refresh timing. If several LSA update requests for the same LSID
1697 * have issued by peer, the last one takes effect.
1698 */
1699 new->lsdb = &apiserv->reserve;
1700 ospf_lsdb_add (&apiserv->reserve, new);
1701
1702 /* Kick the scheduler function. */
1703 ospf_opaque_lsa_refresh_schedule (old);
1704 }
1705
1706out:
1707
1708 /* Send a reply back to client with return code */
1709 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1710 return rc;
1711}
1712
1713
1714/* -----------------------------------------------------------
1715 * Flood an LSA within its flooding scope.
1716 * -----------------------------------------------------------
1717 */
1718
1719/* XXX We can probably use ospf_flood_through instead of this function
1720 but then we need the neighbor parameter. If we set nbr to
1721 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1722
1723void
1724ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1725{
1726 assert (lsa);
1727
1728 switch (lsa->data->type)
1729 {
1730 case OSPF_OPAQUE_LINK_LSA:
1731 /* Increment counters? XXX */
1732
1733 /* Flood LSA through local network. */
1734 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1735 break;
1736 case OSPF_OPAQUE_AREA_LSA:
1737 /* Update LSA origination count. */
1738 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001739 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001740
1741 /* Flood LSA through area. */
1742 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1743 break;
1744 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001745 {
paul99b7c5d2003-04-06 01:19:28 +00001746 struct ospf *ospf;
1747
1748 ospf = ospf_lookup();
1749 assert(ospf);
1750
paul7d5e2682003-04-05 19:41:07 +00001751 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001752
paul7d5e2682003-04-05 19:41:07 +00001753 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001754 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001755 break;
1756 }
paul2d33f152003-03-17 01:10:58 +00001757 }
1758}
1759
1760int
1761ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1762{
paul99b7c5d2003-04-06 01:19:28 +00001763 struct ospf *ospf;
1764
1765 ospf = ospf_lookup();
1766 assert(ospf);
1767
paul2d33f152003-03-17 01:10:58 +00001768 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001769 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001770 {
1771 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1772 return -1;
1773 }
1774
1775 /* Flood LSA within scope */
1776
1777#ifdef NOTYET
1778 /*
1779 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1780 * parameter, and thus it does not cause SIGSEGV error.
1781 */
1782 ospf_flood_through (NULL /*nbr */ , lsa);
1783#else /* NOTYET */
1784
1785 ospf_apiserver_flood_opaque_lsa (lsa);
1786#endif /* NOTYET */
1787
1788 return 0;
1789}
1790
1791
1792/* Opaque LSAs of type 9 on a specific interface can now be
1793 originated. Tell clients that registered type 9. */
1794int
1795ospf_apiserver_lsa9_originator (void *arg)
1796{
1797 struct ospf_interface *oi;
1798
1799 oi = (struct ospf_interface *) arg;
1800 if (listcount (apiserver_list) > 0) {
1801 ospf_apiserver_clients_notify_ready_type9 (oi);
1802 }
1803 return 0;
1804}
1805
1806int
1807ospf_apiserver_lsa10_originator (void *arg)
1808{
1809 struct ospf_area *area;
1810
1811 area = (struct ospf_area *) arg;
1812 if (listcount (apiserver_list) > 0) {
1813 ospf_apiserver_clients_notify_ready_type10 (area);
1814 }
1815 return 0;
1816}
1817
1818int
1819ospf_apiserver_lsa11_originator (void *arg)
1820{
1821 struct ospf *ospf;
1822
1823 ospf = (struct ospf *) arg;
1824 if (listcount (apiserver_list) > 0) {
1825 ospf_apiserver_clients_notify_ready_type11 (ospf);
1826 }
1827 return 0;
1828}
1829
1830
1831/* Periodically refresh opaque LSAs so that they do not expire in
1832 other routers. */
1833void
1834ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1835{
1836 struct ospf_apiserver *apiserv;
1837 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001838 struct ospf * ospf;
1839
1840 ospf = ospf_lookup();
1841 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001842
1843 apiserv = lookup_apiserver_by_lsa (lsa);
1844 if (!apiserv)
1845 {
1846 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1847 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1848 }
1849
1850 if (IS_LSA_MAXAGE (lsa))
1851 {
1852 ospf_opaque_lsa_flush_schedule (lsa);
1853 goto out;
1854 }
1855
1856 /* Check if updated version of LSA instance has already prepared. */
1857 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1858 if (!new)
1859 {
1860 /* This is a periodic refresh, driven by core OSPF mechanism. */
1861 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1862 if (!new)
1863 {
1864 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1865 goto out;
1866 }
1867 }
1868 else
1869 {
1870 /* This is a forcible refresh, requested by OSPF-API client. */
1871 ospf_lsdb_delete (&apiserv->reserve, new);
1872 new->lsdb = NULL;
1873 }
1874
1875 /* Increment sequence number */
1876 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1877
1878 /* New LSA is in same area. */
1879 new->area = lsa->area;
1880 SET_FLAG (new->flags, OSPF_LSA_SELF);
1881
1882 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001883 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001884 {
1885 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
paul788dab12004-11-15 11:48:37 +00001886 ospf_lsa_unlock (new);
paul2d33f152003-03-17 01:10:58 +00001887 goto out;
1888 }
1889
1890 /* Flood updated LSA through interface, area or AS */
1891
1892#ifdef NOTYET
1893 ospf_flood_through (NULL /*nbr */ , new);
1894#endif /* NOTYET */
1895 ospf_apiserver_flood_opaque_lsa (new);
1896
1897 /* Debug logging. */
1898 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1899 {
ajse84cc642004-12-08 17:28:56 +00001900 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
paul2d33f152003-03-17 01:10:58 +00001901 new->data->type, inet_ntoa (new->data->id));
1902 ospf_lsa_header_dump (new->data);
1903 }
1904
1905out:
1906 return;
1907}
1908
1909
1910/* -----------------------------------------------------------
1911 * Followings are functions to delete LSAs
1912 * -----------------------------------------------------------
1913 */
1914
1915int
1916ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1917 struct msg *msg)
1918{
1919 struct msg_delete_request *dmsg;
1920 struct ospf_lsa *old;
1921 struct ospf_area *area = NULL;
1922 struct in_addr id;
1923 int lsa_type, opaque_type;
1924 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001925 struct ospf * ospf;
1926
1927 ospf = ospf_lookup();
1928 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001929
1930 /* Extract opaque LSA from message */
1931 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1932
1933 /* Lookup area for link-local and area-local opaque LSAs */
1934 switch (dmsg->lsa_type)
1935 {
1936 case OSPF_OPAQUE_LINK_LSA:
1937 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001938 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001939 if (!area)
1940 {
1941 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1942 inet_ntoa (dmsg->area_id));
1943 rc = OSPF_API_NOSUCHAREA;
1944 goto out;
1945 }
1946 break;
1947 case OSPF_OPAQUE_AS_LSA:
1948 /* AS-external opaque LSAs have no designated area */
1949 area = NULL;
1950 break;
1951 default:
1952 zlog_warn
1953 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1954 dmsg->lsa_type);
1955 rc = OSPF_API_ILLEGALLSATYPE;
1956 goto out;
1957 }
1958
1959 /* Check if we registered this opaque type */
1960 lsa_type = dmsg->lsa_type;
1961 opaque_type = dmsg->opaque_type;
1962
1963 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1964 {
1965 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1966 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1967 goto out;
1968 }
1969
1970 /* opaque_id is in network byte order */
1971 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1972 ntohl (dmsg->opaque_id)));
1973
1974 /*
1975 * Even if the target LSA has once scheduled to flush, it remains in
1976 * the LSDB until it is finally handled by the maxage remover thread.
1977 * Therefore, the lookup function below may return non-NULL result.
1978 */
paul99b7c5d2003-04-06 01:19:28 +00001979 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001980 if (!old)
1981 {
1982 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1983 dmsg->lsa_type, inet_ntoa (id));
1984 rc = OSPF_API_NOSUCHLSA;
1985 goto out;
1986 }
1987
1988 /* Schedule flushing of LSA from LSDB */
1989 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1990 ospf_opaque_lsa_flush_schedule (old);
1991
1992out:
1993
1994 /* Send reply back to client including return code */
1995 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1996 return rc;
1997}
1998
1999/* Flush self-originated opaque LSA */
paul4dadc292005-05-06 21:37:42 +00002000static int
paul2d33f152003-03-17 01:10:58 +00002001apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2002 void *p_arg, int int_arg)
2003{
2004 struct param_t
2005 {
2006 struct ospf_apiserver *apiserv;
2007 u_char lsa_type;
2008 u_char opaque_type;
2009 }
2010 *param;
2011
2012 /* Sanity check */
2013 assert (lsa->data);
2014 assert (p_arg);
2015 param = (struct param_t *) p_arg;
2016
2017 /* If LSA matches type and opaque type then delete it */
2018 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2019 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2020 {
2021 ospf_opaque_lsa_flush_schedule (lsa);
2022 }
2023 return 0;
2024}
2025
2026/* Delete self-originated opaque LSAs of a given opaque type. This
2027 function is called when an application unregisters a given opaque
2028 type or a connection to an application closes and all those opaque
2029 LSAs need to be flushed the LSDB. */
2030void
2031ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2032 u_char lsa_type, u_char opaque_type)
2033{
2034 struct param_t
2035 {
2036 struct ospf_apiserver *apiserv;
2037 u_char lsa_type;
2038 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002039 } param;
paul1eb8ef22005-04-07 07:30:20 +00002040 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00002041 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002042 struct ospf_area *area;
2043
paul99b7c5d2003-04-06 01:19:28 +00002044 ospf = ospf_lookup();
2045 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002046
2047 /* Set parameter struct. */
2048 param.apiserv = apiserv;
2049 param.lsa_type = lsa_type;
2050 param.opaque_type = opaque_type;
2051
paul2d33f152003-03-17 01:10:58 +00002052 switch (lsa_type)
2053 {
paul99b7c5d2003-04-06 01:19:28 +00002054 struct route_node *rn;
2055 struct ospf_lsa *lsa;
2056
paul2d33f152003-03-17 01:10:58 +00002057 case OSPF_OPAQUE_LINK_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002058 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002059 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2060 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002061 break;
2062 case OSPF_OPAQUE_AREA_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002063 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002064 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2065 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002066 break;
2067 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002068 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2069 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002070 break;
2071 default:
2072 break;
2073 }
2074 return;
paul2d33f152003-03-17 01:10:58 +00002075}
2076
2077
2078/* -----------------------------------------------------------
2079 * Followings are callback functions to handle opaque types
2080 * -----------------------------------------------------------
2081 */
2082
2083int
2084ospf_apiserver_new_if (struct interface *ifp)
2085{
2086 struct ospf_interface *oi;
2087
2088 /* For some strange reason it seems possible that we are invoked
2089 with an interface that has no name. This seems to happen during
2090 initialization. Return if this happens */
2091
2092 if (ifp->name[0] == '\0') {
2093 /* interface has empty name */
2094 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2095 return 0;
2096 }
2097
2098 /* zlog_warn for debugging */
2099 zlog_warn ("ospf_apiserver_new_if");
2100 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2101 ifp->ifindex);
2102
2103 if (ifp->name[0] == '\0') {
2104 /* interface has empty name */
2105 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2106 return 0;
2107 }
2108
2109 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2110
2111 if (!oi) {
2112 /* This interface is known to Zebra but not to OSPF daemon yet. */
2113 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2114 ifp->name);
2115 return 0;
2116 }
2117
2118 assert (oi);
2119
2120 /* New interface added to OSPF, tell clients about it */
2121 if (listcount (apiserver_list) > 0) {
2122 ospf_apiserver_clients_notify_new_if (oi);
2123 }
2124 return 0;
2125}
2126
2127int
2128ospf_apiserver_del_if (struct interface *ifp)
2129{
2130 struct ospf_interface *oi;
2131
2132 /* zlog_warn for debugging */
2133 zlog_warn ("ospf_apiserver_del_if");
2134 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2135 ifp->ifindex);
2136
2137 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002138
2139 if (!oi) {
2140 /* This interface is known to Zebra but not to OSPF daemon
2141 anymore. No need to tell clients about it */
2142 return 0;
2143 }
paul2d33f152003-03-17 01:10:58 +00002144
2145 /* Interface deleted, tell clients about it */
2146 if (listcount (apiserver_list) > 0) {
2147 ospf_apiserver_clients_notify_del_if (oi);
2148 }
2149 return 0;
2150}
2151
2152void
2153ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2154{
2155 /* Tell clients about interface change */
2156
2157 /* zlog_warn for debugging */
2158 zlog_warn ("ospf_apiserver_ism_change");
2159 if (listcount (apiserver_list) > 0) {
2160 ospf_apiserver_clients_notify_ism_change (oi);
2161 }
2162
2163 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2164 zlog_warn ("old_state=%d", old_state);
2165 zlog_warn ("oi->state=%d", oi->state);
2166}
2167
2168void
2169ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2170{
2171 /* Neighbor status changed, tell clients about it */
2172 zlog_warn ("ospf_apiserver_nsm_change");
2173 if (listcount (apiserver_list) > 0) {
2174 ospf_apiserver_clients_notify_nsm_change (nbr);
2175 }
2176}
2177
2178void
2179ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2180{
2181 struct opaque_lsa
2182 {
2183 struct lsa_header header;
2184 u_char data[1]; /* opaque data have variable length. This is start
2185 address */
2186 };
2187 struct opaque_lsa *olsa;
2188 int opaquelen;
2189
2190 olsa = (struct opaque_lsa *) lsa->data;
2191
2192 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002193 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002194 else
paul87d6f872004-09-24 08:01:38 +00002195 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002196
2197 /* Output information about opaque LSAs */
2198 if (vty != NULL)
2199 {
2200 int i;
2201 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2202 opaquelen,
2203 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2204 VTY_NEWLINE);
2205 vty_out (vty, " Opaque data: ");
2206
2207 for (i = 0; i < opaquelen; i++)
2208 {
2209 vty_out (vty, "0x%x ", olsa->data[i]);
2210 }
2211 vty_out (vty, "%s", VTY_NEWLINE);
2212 }
2213 else
2214 {
2215 int i;
ajse84cc642004-12-08 17:28:56 +00002216 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
paul2d33f152003-03-17 01:10:58 +00002217 opaquelen,
2218 VALID_OPAQUE_INFO_LEN (lsa->
2219 data) ? "" : "(Invalid length?)");
ajse84cc642004-12-08 17:28:56 +00002220 zlog_debug (" Opaque data: ");
paul2d33f152003-03-17 01:10:58 +00002221
2222 for (i = 0; i < opaquelen; i++)
2223 {
ajse84cc642004-12-08 17:28:56 +00002224 zlog_debug ("0x%x ", olsa->data[i]);
paul2d33f152003-03-17 01:10:58 +00002225 }
ajse84cc642004-12-08 17:28:56 +00002226 zlog_debug ("\n");
paul2d33f152003-03-17 01:10:58 +00002227 }
2228 return;
2229}
2230
2231/* -----------------------------------------------------------
2232 * Followings are functions to notify clients about events
2233 * -----------------------------------------------------------
2234 */
2235
2236/* Send a message to all clients. This is useful for messages
2237 that need to be notified to all clients (such as interface
2238 changes) */
2239
2240void
2241ospf_apiserver_clients_notify_all (struct msg *msg)
2242{
paul1eb8ef22005-04-07 07:30:20 +00002243 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002244 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002245
2246 /* Send message to all clients */
paul1eb8ef22005-04-07 07:30:20 +00002247 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul87d6f872004-09-24 08:01:38 +00002248 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002249}
2250
2251/* An interface is now ready to accept opaque LSAs. Notify all
2252 clients that registered to use this opaque type */
2253void
2254ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2255{
paul1eb8ef22005-04-07 07:30:20 +00002256 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002257 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002258 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002259
2260 assert (oi);
2261 if (!oi->address)
2262 {
2263 zlog_warn ("Interface has no address?");
2264 return;
2265 }
2266
2267 if (!ospf_apiserver_is_ready_type9 (oi))
2268 {
2269 zlog_warn ("Interface not ready for type 9?");
2270 return;
2271 }
2272
paul1eb8ef22005-04-07 07:30:20 +00002273 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002274 {
paul1eb8ef22005-04-07 07:30:20 +00002275 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002276 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002277
paul1eb8ef22005-04-07 07:30:20 +00002278 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002279 {
paul2d33f152003-03-17 01:10:58 +00002280 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2281 {
2282 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2283 r->opaque_type,
2284 oi->address->u.prefix4);
2285 if (!msg)
2286 {
2287 zlog_warn
2288 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2289#ifdef NOTYET
2290 /* Cannot allocate new message. What should we do? */
2291 ospf_apiserver_free (apiserv);
2292#endif
2293 goto out;
2294 }
2295
2296 ospf_apiserver_send_msg (apiserv, msg);
2297 msg_free (msg);
2298 }
2299 }
2300 }
2301
2302out:
2303 return;
2304}
2305
2306void
2307ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2308{
paul1eb8ef22005-04-07 07:30:20 +00002309 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002310 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002311 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002312
2313 assert (area);
2314
2315 if (!ospf_apiserver_is_ready_type10 (area))
2316 {
2317 zlog_warn ("Area not ready for type 10?");
2318 return;
2319 }
2320
paul1eb8ef22005-04-07 07:30:20 +00002321 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002322 {
paul1eb8ef22005-04-07 07:30:20 +00002323 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002324 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002325
paul1eb8ef22005-04-07 07:30:20 +00002326 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002327 {
paul2d33f152003-03-17 01:10:58 +00002328 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2329 {
2330 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2331 r->opaque_type, area->area_id);
2332 if (!msg)
2333 {
2334 zlog_warn
2335 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2336#ifdef NOTYET
2337 /* Cannot allocate new message. What should we do? */
2338 ospf_apiserver_free (apiserv);
2339#endif
paul87d6f872004-09-24 08:01:38 +00002340 goto out;
paul2d33f152003-03-17 01:10:58 +00002341 }
2342
2343 ospf_apiserver_send_msg (apiserv, msg);
2344 msg_free (msg);
2345 }
2346 }
2347 }
2348
2349out:
2350 return;
2351}
2352
2353
2354void
2355ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2356{
paul1eb8ef22005-04-07 07:30:20 +00002357 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002358 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002359 struct in_addr id_null = { .s_addr = 0L };
paul87d6f872004-09-24 08:01:38 +00002360 struct ospf_apiserver *apiserv;
paul36238142005-10-11 04:12:54 +00002361
paul2d33f152003-03-17 01:10:58 +00002362 assert (top);
paul36238142005-10-11 04:12:54 +00002363
paul2d33f152003-03-17 01:10:58 +00002364 if (!ospf_apiserver_is_ready_type11 (top))
2365 {
2366 zlog_warn ("AS not ready for type 11?");
2367 return;
2368 }
2369
paul1eb8ef22005-04-07 07:30:20 +00002370 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002371 {
paul1eb8ef22005-04-07 07:30:20 +00002372 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002373 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002374
paul1eb8ef22005-04-07 07:30:20 +00002375 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002376 {
paul2d33f152003-03-17 01:10:58 +00002377 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2378 {
2379 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2380 r->opaque_type, id_null);
2381 if (!msg)
2382 {
2383 zlog_warn
2384 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2385#ifdef NOTYET
2386 /* Cannot allocate new message. What should we do? */
2387 ospf_apiserver_free (apiserv);
2388#endif
2389 goto out;
2390 }
2391
2392 ospf_apiserver_send_msg (apiserv, msg);
2393 msg_free (msg);
2394 }
2395 }
2396 }
2397
2398out:
2399 return;
2400}
2401
2402void
2403ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2404{
2405 struct msg *msg;
2406
2407 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2408 if (msg != NULL)
2409 {
2410 ospf_apiserver_clients_notify_all (msg);
2411 msg_free (msg);
2412 }
2413}
2414
2415void
2416ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2417{
2418 struct msg *msg;
2419
2420 msg = new_msg_del_if (0, oi->address->u.prefix4);
2421 if (msg != NULL)
2422 {
2423 ospf_apiserver_clients_notify_all (msg);
2424 msg_free (msg);
2425 }
2426}
2427
2428void
2429ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2430{
2431 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002432 struct in_addr ifaddr = { .s_addr = 0L };
2433 struct in_addr area_id = { .s_addr = 0L };
2434
paul2d33f152003-03-17 01:10:58 +00002435 assert (oi);
2436 assert (oi->ifp);
paul36238142005-10-11 04:12:54 +00002437
paul2d33f152003-03-17 01:10:58 +00002438 if (oi->address)
2439 {
2440 ifaddr = oi->address->u.prefix4;
2441 }
2442 if (oi->area)
2443 {
2444 area_id = oi->area->area_id;
2445 }
2446
hasso1ddd7292005-06-07 19:54:04 +00002447 msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
paul2d33f152003-03-17 01:10:58 +00002448 if (!msg)
2449 {
2450 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2451 return;
2452 }
2453
2454 ospf_apiserver_clients_notify_all (msg);
2455 msg_free (msg);
2456}
2457
2458void
2459ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2460{
2461 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002462 struct in_addr ifaddr = { .s_addr = 0L };
2463 struct in_addr nbraddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002464
2465 assert (nbr);
2466
2467 if (nbr->oi)
2468 {
2469 ifaddr = nbr->oi->address->u.prefix4;
2470 }
2471
2472 nbraddr = nbr->address.u.prefix4;
2473
2474 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2475 if (!msg)
2476 {
2477 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2478 return;
2479 }
2480
2481 ospf_apiserver_clients_notify_all (msg);
2482 msg_free (msg);
2483}
2484
paul4dadc292005-05-06 21:37:42 +00002485static void
paul2d33f152003-03-17 01:10:58 +00002486apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2487{
2488 struct msg *msg;
paul1eb8ef22005-04-07 07:30:20 +00002489 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002490 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002491
2492 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002493 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002494
2495 /* Default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002496 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002497
2498 if (lsa->area)
2499 {
2500 area_id = lsa->area->area_id;
2501 }
2502 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2503 {
2504 assert (lsa->oi);
2505 ifaddr = lsa->oi->address->u.prefix4;
2506 }
2507
2508 /* Prepare message that can be sent to clients that have a matching
2509 filter */
2510 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2511 ifaddr, area_id,
2512 lsa->flags & OSPF_LSA_SELF, lsa->data);
2513 if (!msg)
2514 {
2515 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2516 return;
2517 }
2518
2519 /* Now send message to all clients with a matching filter */
paul1eb8ef22005-04-07 07:30:20 +00002520 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002521 {
paul2d33f152003-03-17 01:10:58 +00002522 struct lsa_filter_type *filter;
2523 u_int16_t mask;
2524 u_int32_t *area;
2525 int i;
2526
2527 /* Check filter for this client. */
2528 filter = apiserv->filter;
2529
2530 /* Check area IDs in case of non AS-E LSAs.
2531 * If filter has areas (num_areas > 0),
2532 * then one of the areas must match the area ID of this LSA. */
2533
2534 i = filter->num_areas;
2535 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2536 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2537 {
2538 i = 0;
2539 }
2540
2541 if (i > 0)
2542 {
2543 area = (u_int32_t *) (filter + 1);
2544 while (i)
2545 {
2546 if (*area == area_id.s_addr)
2547 {
2548 break;
2549 }
2550 i--;
2551 area++;
2552 }
2553 }
2554 else
2555 {
2556 i = 1;
2557 }
2558
2559 if (i > 0)
2560 {
2561 /* Area match. Check LSA type. */
2562 mask = ntohs (filter->typemask);
2563
2564 if (mask & Power2[lsa->data->type])
2565 {
2566 /* Type also matches. Check origin. */
2567 if ((filter->origin == ANY_ORIGIN) ||
2568 (filter->origin == IS_LSA_SELF (lsa)))
2569 {
2570 ospf_apiserver_send_msg (apiserv, msg);
2571 }
2572 }
2573 }
2574 }
2575 /* Free message since it is not used anymore */
2576 msg_free (msg);
2577}
2578
2579
2580/* -------------------------------------------------------------
2581 * Followings are hooks invoked when LSAs are updated or deleted
2582 * -------------------------------------------------------------
2583 */
2584
2585
paul4dadc292005-05-06 21:37:42 +00002586static int
paul2d33f152003-03-17 01:10:58 +00002587apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2588{
2589 struct msg *msg;
2590 /* default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002591 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002592
2593 /* default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002594 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002595
2596 /* Only notify this update if the LSA's age is smaller than
2597 MAXAGE. Otherwise clients would see LSA updates with max age just
2598 before they are deleted from the LSDB. LSA delete messages have
2599 MAXAGE too but should not be filtered. */
2600 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2601 return 0;
2602 }
2603
2604 if (lsa->area)
2605 {
2606 area_id = lsa->area->area_id;
2607 }
2608 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2609 {
2610 ifaddr = lsa->oi->address->u.prefix4;
2611 }
2612 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2613 ifaddr, area_id,
2614 lsa->flags & OSPF_LSA_SELF, lsa->data);
2615 if (!msg)
2616 {
2617 zlog_warn ("notify_clients_lsa: msg_new failed");
2618 return -1;
2619 }
2620 /* Notify all clients that new LSA is added/updated */
2621 apiserver_clients_lsa_change_notify (msgtype, lsa);
2622
2623 /* Clients made their own copies of msg so we can free msg here */
2624 msg_free (msg);
2625
2626 return 0;
2627}
2628
2629int
2630ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2631{
2632 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2633}
2634
2635int
2636ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2637{
2638 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2639}
2640
2641#endif /* SUPPORT_OSPF_API */
2642