blob: db1ccda72ae0137d2c88d7d3f919f1e6f1bd0e64 [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
Hasso Tepper8c9ed272012-10-11 11:15:18 +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 */
paule029d442005-10-23 15:26:24 +0000192 while ( apiserver_list &&
193 (apiserv = listgetdata (listhead (apiserver_list))) != NULL)
paul87d6f872004-09-24 08:01:38 +0000194 ospf_apiserver_free (apiserv);
paul2d33f152003-03-17 01:10:58 +0000195
196 /* Free client list itself */
paule029d442005-10-23 15:26:24 +0000197 if (apiserver_list)
198 list_delete (apiserver_list);
paul2d33f152003-03-17 01:10:58 +0000199
200 /* Free wildcard list */
201 /* XXX */
202}
203
204static struct ospf_apiserver *
205lookup_apiserver (u_char lsa_type, u_char opaque_type)
206{
paul87d6f872004-09-24 08:01:38 +0000207 struct listnode *n1, *n2;
paul2d33f152003-03-17 01:10:58 +0000208 struct registered_opaque_type *r;
209 struct ospf_apiserver *apiserv, *found = NULL;
210
paul87d6f872004-09-24 08:01:38 +0000211 /* XXX: this approaches O(n**2) */
paul1eb8ef22005-04-07 07:30:20 +0000212 for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv))
paul2d33f152003-03-17 01:10:58 +0000213 {
paul1eb8ef22005-04-07 07:30:20 +0000214 for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r))
215 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
216 {
217 found = apiserv;
218 goto out;
219 }
paul2d33f152003-03-17 01:10:58 +0000220 }
221out:
222 return found;
223}
224
225static struct ospf_apiserver *
226lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
227{
228 struct lsa_header *lsah = lsa->data;
229 struct ospf_apiserver *found = NULL;
230
231 if (IS_OPAQUE_LSA (lsah->type))
232 {
233 found = lookup_apiserver (lsah->type,
234 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
235 }
236 return found;
237}
238
239/* -----------------------------------------------------------
240 * Followings are functions to manage client connections.
241 * -----------------------------------------------------------
242 */
243static int
244ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
245{
246 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000247 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 +0000248 return 0;
249}
250
251static int
252ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
253{
254 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000255 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 +0000256 return 0;
257}
258
259/* Allocate new connection structure. */
260struct ospf_apiserver *
261ospf_apiserver_new (int fd_sync, int fd_async)
262{
263 struct ospf_apiserver *new =
264 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
265
266 new->filter =
267 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
268
269 new->fd_sync = fd_sync;
270 new->fd_async = fd_async;
271
272 /* list of registered opaque types that application uses */
273 new->opaque_types = list_new ();
274
275 /* Initialize temporary strage for LSA instances to be refreshed. */
276 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
277 ospf_lsdb_init (&new->reserve);
278
279 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
280 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
281
282 new->out_sync_fifo = msg_fifo_new ();
283 new->out_async_fifo = msg_fifo_new ();
284 new->t_sync_read = NULL;
285#ifdef USE_ASYNC_READ
286 new->t_async_read = NULL;
287#endif /* USE_ASYNC_READ */
288 new->t_sync_write = NULL;
289 new->t_async_write = NULL;
290
291 new->filter->typemask = 0; /* filter all LSAs */
292 new->filter->origin = ANY_ORIGIN;
293 new->filter->num_areas = 0;
294
295 return new;
296}
297
298void
299ospf_apiserver_event (enum event event, int fd,
300 struct ospf_apiserver *apiserv)
301{
paul2d33f152003-03-17 01:10:58 +0000302 switch (event)
303 {
304 case OSPF_APISERVER_ACCEPT:
Andrew Certain0798cee2012-12-04 13:43:42 -0800305 (void)thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
paul2d33f152003-03-17 01:10:58 +0000306 break;
307 case OSPF_APISERVER_SYNC_READ:
308 apiserv->t_sync_read =
309 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
310 break;
311#ifdef USE_ASYNC_READ
312 case OSPF_APISERVER_ASYNC_READ:
313 apiserv->t_async_read =
314 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
315 break;
316#endif /* USE_ASYNC_READ */
317 case OSPF_APISERVER_SYNC_WRITE:
318 if (!apiserv->t_sync_write)
319 {
320 apiserv->t_sync_write =
321 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
322 }
323 break;
324 case OSPF_APISERVER_ASYNC_WRITE:
325 if (!apiserv->t_async_write)
326 {
327 apiserv->t_async_write =
328 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
329 }
330 break;
331 }
332}
333
334/* Free instance. First unregister all opaque types used by
335 application, flush opaque LSAs injected by application
336 from network and close connection. */
337void
338ospf_apiserver_free (struct ospf_apiserver *apiserv)
339{
paul87d6f872004-09-24 08:01:38 +0000340 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000341
342 /* Cancel read and write threads. */
343 if (apiserv->t_sync_read)
344 {
345 thread_cancel (apiserv->t_sync_read);
346 }
347#ifdef USE_ASYNC_READ
348 if (apiserv->t_async_read)
349 {
350 thread_cancel (apiserv->t_async_read);
351 }
352#endif /* USE_ASYNC_READ */
353 if (apiserv->t_sync_write)
354 {
355 thread_cancel (apiserv->t_sync_write);
356 }
357
358 if (apiserv->t_async_write)
359 {
360 thread_cancel (apiserv->t_async_write);
361 }
362
363 /* Unregister all opaque types that application registered
364 and flush opaque LSAs if still in LSDB. */
365
366 while ((node = listhead (apiserv->opaque_types)) != NULL)
367 {
paul1eb8ef22005-04-07 07:30:20 +0000368 struct registered_opaque_type *regtype = listgetdata(node);
paul2d33f152003-03-17 01:10:58 +0000369
370 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
371 regtype->opaque_type);
372
373 }
374
375 /* Close connections to OSPFd. */
376 if (apiserv->fd_sync > 0)
377 {
378 close (apiserv->fd_sync);
379 }
380
381 if (apiserv->fd_async > 0)
382 {
383 close (apiserv->fd_async);
384 }
385
386 /* Free fifos */
387 msg_fifo_free (apiserv->out_sync_fifo);
388 msg_fifo_free (apiserv->out_async_fifo);
389
390 /* Clear temporary strage for LSA instances to be refreshed. */
391 ospf_lsdb_delete_all (&apiserv->reserve);
392 ospf_lsdb_cleanup (&apiserv->reserve);
393
394 /* Remove from the list of active clients. */
395 listnode_delete (apiserver_list, apiserv);
396
397 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000398 zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000399
400 /* And free instance. */
401 XFREE (MTYPE_OSPF_APISERVER, apiserv);
402}
403
404int
405ospf_apiserver_read (struct thread *thread)
406{
407 struct ospf_apiserver *apiserv;
408 struct msg *msg;
409 int fd;
410 int rc = -1;
411 enum event event;
412
413 apiserv = THREAD_ARG (thread);
414 fd = THREAD_FD (thread);
415
416 if (fd == apiserv->fd_sync)
417 {
418 event = OSPF_APISERVER_SYNC_READ;
419 apiserv->t_sync_read = NULL;
420
421 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000422 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000423 inet_ntoa (apiserv->peer_sync.sin_addr),
424 ntohs (apiserv->peer_sync.sin_port));
425 }
426#ifdef USE_ASYNC_READ
427 else if (fd == apiserv->fd_async)
428 {
429 event = OSPF_APISERVER_ASYNC_READ;
430 apiserv->t_async_read = NULL;
431
432 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000433 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000434 inet_ntoa (apiserv->peer_async.sin_addr),
435 ntohs (apiserv->peer_async.sin_port));
436 }
437#endif /* USE_ASYNC_READ */
438 else
439 {
440 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
441 ospf_apiserver_free (apiserv);
442 goto out;
443 }
444
445 /* Read message from fd. */
446 msg = msg_read (fd);
447 if (msg == NULL)
448 {
449 zlog_warn
450 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
451
452 /* Perform cleanup. */
453 ospf_apiserver_free (apiserv);
454 goto out;
455 }
456
457 if (IS_DEBUG_OSPF_EVENT)
458 msg_print (msg);
459
460 /* Dispatch to corresponding message handler. */
461 rc = ospf_apiserver_handle_msg (apiserv, msg);
462
463 /* Prepare for next message, add read thread. */
464 ospf_apiserver_event (event, fd, apiserv);
465
466 msg_free (msg);
467
468out:
469 return rc;
470}
471
472int
473ospf_apiserver_sync_write (struct thread *thread)
474{
475 struct ospf_apiserver *apiserv;
476 struct msg *msg;
477 int fd;
478 int rc = -1;
479
480 apiserv = THREAD_ARG (thread);
481 assert (apiserv);
482 fd = THREAD_FD (thread);
483
484 apiserv->t_sync_write = NULL;
485
486 /* Sanity check */
487 if (fd != apiserv->fd_sync)
488 {
489 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
490 goto out;
491 }
492
493 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000494 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000495 inet_ntoa (apiserv->peer_sync.sin_addr),
496 ntohs (apiserv->peer_sync.sin_port));
497
498 /* Check whether there is really a message in the fifo. */
499 msg = msg_fifo_pop (apiserv->out_sync_fifo);
500 if (!msg)
501 {
502 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
503 return 0;
504 }
505
506 if (IS_DEBUG_OSPF_EVENT)
507 msg_print (msg);
508
509 rc = msg_write (fd, msg);
510
511 /* Once a message is dequeued, it should be freed anyway. */
512 msg_free (msg);
513
514 if (rc < 0)
515 {
516 zlog_warn
517 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
518 goto out;
519 }
520
521
522 /* If more messages are in sync message fifo, schedule write thread. */
523 if (msg_fifo_head (apiserv->out_sync_fifo))
524 {
525 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
526 apiserv);
527 }
528
529 out:
530
531 if (rc < 0)
532 {
533 /* Perform cleanup and disconnect with peer */
534 ospf_apiserver_free (apiserv);
535 }
536
537 return rc;
538}
539
540
541int
542ospf_apiserver_async_write (struct thread *thread)
543{
544 struct ospf_apiserver *apiserv;
545 struct msg *msg;
546 int fd;
547 int rc = -1;
548
549 apiserv = THREAD_ARG (thread);
550 assert (apiserv);
551 fd = THREAD_FD (thread);
552
553 apiserv->t_async_write = NULL;
554
555 /* Sanity check */
556 if (fd != apiserv->fd_async)
557 {
558 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
559 goto out;
560 }
561
562 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000563 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000564 inet_ntoa (apiserv->peer_async.sin_addr),
565 ntohs (apiserv->peer_async.sin_port));
566
567 /* Check whether there is really a message in the fifo. */
568 msg = msg_fifo_pop (apiserv->out_async_fifo);
569 if (!msg)
570 {
571 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
572 return 0;
573 }
574
575 if (IS_DEBUG_OSPF_EVENT)
576 msg_print (msg);
577
578 rc = msg_write (fd, msg);
579
580 /* Once a message is dequeued, it should be freed anyway. */
581 msg_free (msg);
582
583 if (rc < 0)
584 {
585 zlog_warn
586 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
587 goto out;
588 }
589
590
591 /* If more messages are in async message fifo, schedule write thread. */
592 if (msg_fifo_head (apiserv->out_async_fifo))
593 {
594 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
595 apiserv);
596 }
597
598 out:
599
600 if (rc < 0)
601 {
602 /* Perform cleanup and disconnect with peer */
603 ospf_apiserver_free (apiserv);
604 }
605
606 return rc;
607}
608
609
610int
611ospf_apiserver_serv_sock_family (unsigned short port, int family)
612{
613 union sockunion su;
614 int accept_sock;
615 int rc;
616
617 memset (&su, 0, sizeof (union sockunion));
618 su.sa.sa_family = family;
619
620 /* Make new socket */
621 accept_sock = sockunion_stream_socket (&su);
622 if (accept_sock < 0)
623 return accept_sock;
624
625 /* This is a server, so reuse address and port */
626 sockopt_reuseaddr (accept_sock);
627 sockopt_reuseport (accept_sock);
628
629 /* Bind socket to address and given port. */
630 rc = sockunion_bind (accept_sock, &su, port, NULL);
631 if (rc < 0)
632 {
633 close (accept_sock); /* Close socket */
634 return rc;
635 }
636
637 /* Listen socket under queue length 3. */
638 rc = listen (accept_sock, 3);
639 if (rc < 0)
640 {
641 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
ajs6099b3b2004-11-20 02:06:59 +0000642 safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000643 close (accept_sock); /* Close socket */
644 return rc;
645 }
646 return accept_sock;
647}
648
649
650/* Accept connection request from external applications. For each
651 accepted connection allocate own connection instance. */
652int
653ospf_apiserver_accept (struct thread *thread)
654{
655 int accept_sock;
656 int new_sync_sock;
657 int new_async_sock;
658 union sockunion su;
659 struct ospf_apiserver *apiserv;
660 struct sockaddr_in peer_async;
661 struct sockaddr_in peer_sync;
paul36238142005-10-11 04:12:54 +0000662 unsigned int peerlen;
paul2d33f152003-03-17 01:10:58 +0000663 int ret;
664
665 /* THREAD_ARG (thread) is NULL */
666 accept_sock = THREAD_FD (thread);
667
668 /* Keep hearing on socket for further connections. */
669 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
670
671 memset (&su, 0, sizeof (union sockunion));
672 /* Accept connection for synchronous messages */
673 new_sync_sock = sockunion_accept (accept_sock, &su);
674 if (new_sync_sock < 0)
675 {
ajs6099b3b2004-11-20 02:06:59 +0000676 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000677 return -1;
678 }
679
680 /* Get port address and port number of peer to make reverse connection.
681 The reverse channel uses the port number of the peer port+1. */
682
683 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
684 peerlen = sizeof (struct sockaddr_in);
685
686 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
687 if (ret < 0)
688 {
ajs6099b3b2004-11-20 02:06:59 +0000689 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000690 close (new_sync_sock);
691 return -1;
692 }
693
694 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000695 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000696 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
697
698 /* Create new socket for asynchronous messages. */
699 peer_async = peer_sync;
700 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
701
702 /* Check if remote port number to make reverse connection is valid one. */
703 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
704 {
705 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
706 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
707 close (new_sync_sock);
708 return -1;
709 }
710
711 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
712 if (new_async_sock < 0)
713 {
ajs6099b3b2004-11-20 02:06:59 +0000714 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000715 close (new_sync_sock);
716 return -1;
717 }
718
719 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
720 sizeof (struct sockaddr_in));
721
722 if (ret < 0)
723 {
ajs6099b3b2004-11-20 02:06:59 +0000724 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000725 close (new_sync_sock);
726 close (new_async_sock);
727 return -1;
728 }
729
730#ifdef USE_ASYNC_READ
731#else /* USE_ASYNC_READ */
732 /* Make the asynchronous channel write-only. */
733 ret = shutdown (new_async_sock, SHUT_RD);
734 if (ret < 0)
735 {
ajs6099b3b2004-11-20 02:06:59 +0000736 zlog_warn ("ospf_apiserver_accept: shutdown: %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#endif /* USE_ASYNC_READ */
742
743 /* Allocate new server-side connection structure */
744 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
745
746 /* Add to active connection list */
747 listnode_add (apiserver_list, apiserv);
748 apiserv->peer_sync = peer_sync;
749 apiserv->peer_async = peer_async;
750
751 /* And add read threads for new connection */
752 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
753#ifdef USE_ASYNC_READ
754 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
755#endif /* USE_ASYNC_READ */
756
757 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000758 zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000759
760 return 0;
761}
762
763
764/* -----------------------------------------------------------
765 * Send reply with return code to client application
766 * -----------------------------------------------------------
767 */
768
paul4dadc292005-05-06 21:37:42 +0000769static int
paul2d33f152003-03-17 01:10:58 +0000770ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
771{
772 struct msg_fifo *fifo;
773 struct msg *msg2;
774 enum event event;
775 int fd;
776
777 switch (msg->hdr.msgtype)
778 {
779 case MSG_REPLY:
780 fifo = apiserv->out_sync_fifo;
781 fd = apiserv->fd_sync;
782 event = OSPF_APISERVER_SYNC_WRITE;
783 break;
784 case MSG_READY_NOTIFY:
785 case MSG_LSA_UPDATE_NOTIFY:
786 case MSG_LSA_DELETE_NOTIFY:
787 case MSG_NEW_IF:
788 case MSG_DEL_IF:
789 case MSG_ISM_CHANGE:
790 case MSG_NSM_CHANGE:
791 fifo = apiserv->out_async_fifo;
792 fd = apiserv->fd_async;
793 event = OSPF_APISERVER_ASYNC_WRITE;
794 break;
795 default:
796 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
797 msg->hdr.msgtype);
798 return -1;
799 }
800
801 /* Make a copy of the message and put in the fifo. Once the fifo
802 gets drained by the write thread, the message will be freed. */
803 /* NB: Given "msg" is untouched in this function. */
804 msg2 = msg_dup (msg);
805
806 /* Enqueue message into corresponding fifo queue */
807 msg_fifo_push (fifo, msg2);
808
809 /* Schedule write thread */
810 ospf_apiserver_event (event, fd, apiserv);
811 return 0;
812}
813
814int
815ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
816 u_char rc)
817{
818 struct msg *msg = new_msg_reply (seqnr, rc);
819 int ret;
820
821 if (!msg)
822 {
823 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
824#ifdef NOTYET
825 /* Cannot allocate new message. What should we do? */
826 ospf_apiserver_free (apiserv);
827#endif
828 return -1;
829 }
830
831 ret = ospf_apiserver_send_msg (apiserv, msg);
832 msg_free (msg);
833 return ret;
834}
835
836
837/* -----------------------------------------------------------
838 * Generic message dispatching handler function
839 * -----------------------------------------------------------
840 */
841
842int
843ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
844{
845 int rc;
846
847 /* Call corresponding message handler function. */
848 switch (msg->hdr.msgtype)
849 {
850 case MSG_REGISTER_OPAQUETYPE:
851 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
852 break;
853 case MSG_UNREGISTER_OPAQUETYPE:
854 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
855 break;
856 case MSG_REGISTER_EVENT:
857 rc = ospf_apiserver_handle_register_event (apiserv, msg);
858 break;
859 case MSG_SYNC_LSDB:
860 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
861 break;
862 case MSG_ORIGINATE_REQUEST:
863 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
864 break;
865 case MSG_DELETE_REQUEST:
866 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
867 break;
868 default:
869 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
870 msg->hdr.msgtype);
871 rc = -1;
872 }
873 return rc;
874}
875
876
877/* -----------------------------------------------------------
878 * Following are functions for opaque type registration
879 * -----------------------------------------------------------
880 */
881
882int
883ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
884 u_char lsa_type, u_char opaque_type)
885{
886 struct registered_opaque_type *regtype;
887 int (*originator_func) (void *arg);
888 int rc;
889
890 switch (lsa_type)
891 {
892 case OSPF_OPAQUE_LINK_LSA:
893 originator_func = ospf_apiserver_lsa9_originator;
894 break;
895 case OSPF_OPAQUE_AREA_LSA:
896 originator_func = ospf_apiserver_lsa10_originator;
897 break;
898 case OSPF_OPAQUE_AS_LSA:
899 originator_func = ospf_apiserver_lsa11_originator;
900 break;
901 default:
902 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
903 lsa_type);
904 return OSPF_API_ILLEGALLSATYPE;
905 }
906
907
908 /* Register opaque function table */
909 /* NB: Duplicated registration will be detected inside the function. */
910 rc =
911 ospf_register_opaque_functab (lsa_type, opaque_type,
912 NULL, /* ospf_apiserver_new_if */
913 NULL, /* ospf_apiserver_del_if */
914 NULL, /* ospf_apiserver_ism_change */
915 NULL, /* ospf_apiserver_nsm_change */
916 NULL,
917 NULL,
918 NULL,
919 ospf_apiserver_show_info,
920 originator_func,
921 ospf_apiserver_lsa_refresher,
922 NULL, /* ospf_apiserver_lsa_update */
923 NULL /* ospf_apiserver_lsa_delete */);
924
925 if (rc != 0)
926 {
927 zlog_warn ("Failed to register opaque type [%d/%d]",
928 lsa_type, opaque_type);
929 return OSPF_API_OPAQUETYPEINUSE;
930 }
931
932 /* Remember the opaque type that application registers so when
933 connection shuts down, we can flush all LSAs of this opaque
934 type. */
935
936 regtype =
Stephen Hemminger393deb92008-08-18 14:13:29 -0700937 XCALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
paul2d33f152003-03-17 01:10:58 +0000938 regtype->lsa_type = lsa_type;
939 regtype->opaque_type = opaque_type;
940
941 /* Add to list of registered opaque types */
942 listnode_add (apiserv->opaque_types, regtype);
943
944 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000945 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
paul87d6f872004-09-24 08:01:38 +0000946 " apiserv(%p), total#(%d)",
947 lsa_type, opaque_type, apiserv,
948 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000949
950 return 0;
951}
952
953int
954ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
955 u_char lsa_type, u_char opaque_type)
956{
paul1eb8ef22005-04-07 07:30:20 +0000957 struct listnode *node, *nnode;
gdt54ade992004-10-07 19:38:20 +0000958 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000959
paul1eb8ef22005-04-07 07:30:20 +0000960 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +0000961 {
paul2d33f152003-03-17 01:10:58 +0000962 /* Check if we really registered this opaque type */
963 if (regtype->lsa_type == lsa_type &&
964 regtype->opaque_type == opaque_type)
965 {
966
967 /* Yes, we registered this opaque type. Flush
968 all existing opaque LSAs of this type */
969
970 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
971 ospf_delete_opaque_functab (lsa_type, opaque_type);
972
973 /* Remove from list of registered opaque types */
974 listnode_delete (apiserv->opaque_types, regtype);
975
976 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000977 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
paul87d6f872004-09-24 08:01:38 +0000978 " from apiserv(%p), total#(%d)",
979 lsa_type, opaque_type, apiserv,
980 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000981
982 return 0;
983 }
984 }
985
986 /* Opaque type is not registered */
987 zlog_warn ("Failed to unregister opaque type [%d/%d]",
988 lsa_type, opaque_type);
989 return OSPF_API_OPAQUETYPENOTREGISTERED;
990}
991
992
paul4dadc292005-05-06 21:37:42 +0000993static int
paul2d33f152003-03-17 01:10:58 +0000994apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
995 u_char lsa_type, u_char opaque_type)
996{
paul1eb8ef22005-04-07 07:30:20 +0000997 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +0000998 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000999
paul87d6f872004-09-24 08:01:38 +00001000 /* XXX: how many types are there? if few, why not just a bitmap? */
paul1eb8ef22005-04-07 07:30:20 +00001001 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +00001002 {
paul2d33f152003-03-17 01:10:58 +00001003 /* Check if we really registered this opaque type */
1004 if (regtype->lsa_type == lsa_type &&
1005 regtype->opaque_type == opaque_type)
1006 {
1007 /* Yes registered */
1008 return 1;
1009 }
1010 }
1011 /* Not registered */
1012 return 0;
1013}
1014
1015int
1016ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1017 struct msg *msg)
1018{
1019 struct msg_register_opaque_type *rmsg;
1020 u_char lsa_type;
1021 u_char opaque_type;
1022 int rc = 0;
1023
1024 /* Extract parameters from register opaque type message */
1025 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1026
1027 lsa_type = rmsg->lsatype;
1028 opaque_type = rmsg->opaquetype;
1029
1030 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1031
1032 /* Send a reply back to client including return code */
1033 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1034 if (rc < 0)
1035 goto out;
1036
1037 /* Now inform application about opaque types that are ready */
1038 switch (lsa_type)
1039 {
1040 case OSPF_OPAQUE_LINK_LSA:
1041 ospf_apiserver_notify_ready_type9 (apiserv);
1042 break;
1043 case OSPF_OPAQUE_AREA_LSA:
1044 ospf_apiserver_notify_ready_type10 (apiserv);
1045 break;
1046 case OSPF_OPAQUE_AS_LSA:
1047 ospf_apiserver_notify_ready_type11 (apiserv);
1048 break;
1049 }
1050out:
1051 return rc;
1052}
1053
1054
1055/* Notify specific client about all opaque types 9 that are ready. */
1056void
1057ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1058{
paul1eb8ef22005-04-07 07:30:20 +00001059 struct listnode *node, *nnode;
1060 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001061 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001062 struct ospf_interface *oi;
1063 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001064
paul99b7c5d2003-04-06 01:19:28 +00001065 ospf = ospf_lookup ();
1066
paul1eb8ef22005-04-07 07:30:20 +00001067 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul2d33f152003-03-17 01:10:58 +00001068 {
paul2d33f152003-03-17 01:10:58 +00001069 /* Check if this interface is indeed ready for type 9 */
1070 if (!ospf_apiserver_is_ready_type9 (oi))
1071 continue;
1072
1073 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001074 /* XXX: loop-de-loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001075 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001076 {
paul2d33f152003-03-17 01:10:58 +00001077 struct msg *msg;
1078
1079 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1080 {
1081
1082 /* Yes, this opaque type is ready */
1083 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1084 r->opaque_type,
1085 oi->address->u.prefix4);
1086 if (!msg)
1087 {
1088 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1089#ifdef NOTYET
1090 /* Cannot allocate new message. What should we do? */
1091 ospf_apiserver_free (apiserv);
1092#endif
1093 goto out;
1094 }
1095 ospf_apiserver_send_msg (apiserv, msg);
1096 msg_free (msg);
1097 }
1098 }
1099 }
1100
1101out:
1102 return;
1103}
1104
1105
1106/* Notify specific client about all opaque types 10 that are ready. */
1107void
1108ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1109{
paul1eb8ef22005-04-07 07:30:20 +00001110 struct listnode *node, *nnode;
1111 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001112 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001113 struct ospf_area *area;
1114
paul99b7c5d2003-04-06 01:19:28 +00001115 ospf = ospf_lookup ();
1116
paul1eb8ef22005-04-07 07:30:20 +00001117 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001118 {
paul87d6f872004-09-24 08:01:38 +00001119 struct registered_opaque_type *r;
1120
paul2d33f152003-03-17 01:10:58 +00001121 if (!ospf_apiserver_is_ready_type10 (area))
1122 {
1123 continue;
1124 }
1125
1126 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001127 /* XXX: loop in loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001128 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001129 {
paul2d33f152003-03-17 01:10:58 +00001130 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001131
paul2d33f152003-03-17 01:10:58 +00001132 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1133 {
1134 /* Yes, this opaque type is ready */
1135 msg =
1136 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1137 r->opaque_type, area->area_id);
1138 if (!msg)
1139 {
1140 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1141#ifdef NOTYET
1142 /* Cannot allocate new message. What should we do? */
1143 ospf_apiserver_free (apiserv);
1144#endif
1145 goto out;
1146 }
1147 ospf_apiserver_send_msg (apiserv, msg);
1148 msg_free (msg);
1149 }
1150 }
1151 }
1152
1153out:
1154 return;
1155}
1156
1157/* Notify specific client about all opaque types 11 that are ready */
1158void
1159ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1160{
paul1eb8ef22005-04-07 07:30:20 +00001161 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00001162 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001163 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001164
1165 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001166
1167 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001168 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001169 goto out;
paul2d33f152003-03-17 01:10:58 +00001170
1171 /* Check for registered opaque type 11 types */
paul1eb8ef22005-04-07 07:30:20 +00001172 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
paul2d33f152003-03-17 01:10:58 +00001173 {
paul2d33f152003-03-17 01:10:58 +00001174 struct msg *msg;
paul36238142005-10-11 04:12:54 +00001175 struct in_addr noarea_id = { .s_addr = 0L };
1176
paul2d33f152003-03-17 01:10:58 +00001177 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1178 {
1179 /* Yes, this opaque type is ready */
1180 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1181 r->opaque_type, noarea_id);
1182
1183 if (!msg)
1184 {
1185 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1186#ifdef NOTYET
1187 /* Cannot allocate new message. What should we do? */
1188 ospf_apiserver_free (apiserv);
1189#endif
1190 goto out;
1191 }
1192 ospf_apiserver_send_msg (apiserv, msg);
1193 msg_free (msg);
1194 }
1195 }
1196
1197out:
1198 return;
1199}
1200
1201int
1202ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1203 struct msg *msg)
1204{
1205 struct msg_unregister_opaque_type *umsg;
1206 u_char ltype;
1207 u_char otype;
1208 int rc = 0;
1209
1210 /* Extract parameters from unregister opaque type message */
1211 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1212
1213 ltype = umsg->lsatype;
1214 otype = umsg->opaquetype;
1215
1216 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1217
1218 /* Send a reply back to client including return code */
1219 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1220
1221 return rc;
1222}
1223
1224
1225/* -----------------------------------------------------------
1226 * Following are functions for event (filter) registration.
1227 * -----------------------------------------------------------
1228 */
1229int
1230ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1231 struct msg *msg)
1232{
1233 struct msg_register_event *rmsg;
1234 int rc;
1235 u_int32_t seqnum;
1236
1237 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1238
1239 /* Get request sequence number */
1240 seqnum = msg_get_seq (msg);
1241
1242 /* Free existing filter in apiserv. */
1243 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1244 /* Alloc new space for filter. */
1245
1246 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1247 ntohs (msg->hdr.msglen));
1248 if (apiserv->filter)
1249 {
1250 /* copy it over. */
1251 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1252 rc = OSPF_API_OK;
1253 }
1254 else
1255 {
1256 rc = OSPF_API_NOMEMORY;
1257 }
1258 /* Send a reply back to client with return code */
1259 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1260 return rc;
1261}
1262
1263
1264/* -----------------------------------------------------------
1265 * Followings are functions for LSDB synchronization.
1266 * -----------------------------------------------------------
1267 */
1268
paul4dadc292005-05-06 21:37:42 +00001269static int
paul2d33f152003-03-17 01:10:58 +00001270apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1271{
1272 struct ospf_apiserver *apiserv;
1273 int seqnum;
1274 struct msg *msg;
1275 struct param_t
1276 {
1277 struct ospf_apiserver *apiserv;
1278 struct lsa_filter_type *filter;
1279 }
1280 *param;
1281 int rc = -1;
1282
1283 /* Sanity check */
1284 assert (lsa->data);
1285 assert (p_arg);
1286
1287 param = (struct param_t *) p_arg;
1288 apiserv = param->apiserv;
1289 seqnum = (u_int32_t) int_arg;
1290
1291 /* Check origin in filter. */
1292 if ((param->filter->origin == ANY_ORIGIN) ||
1293 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1294 {
1295
1296 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00001297 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00001298
1299 /* Default interface for non Opaque9 LSAs */
paul484315f2005-11-03 09:08:29 +00001300 struct in_addr ifaddr = { .s_addr = 0L };
paul36238142005-10-11 04:12:54 +00001301
paul2d33f152003-03-17 01:10:58 +00001302 if (lsa->area)
1303 {
1304 area_id = lsa->area->area_id;
1305 }
1306 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1307 {
1308 ifaddr = lsa->oi->address->u.prefix4;
1309 }
1310
1311 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1312 seqnum,
1313 ifaddr, area_id,
1314 lsa->flags & OSPF_LSA_SELF, lsa->data);
1315 if (!msg)
1316 {
1317 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1318#ifdef NOTYET
1319 /* Cannot allocate new message. What should we do? */
1320/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1321#endif
1322 goto out;
1323 }
1324
1325 /* Send LSA */
1326 ospf_apiserver_send_msg (apiserv, msg);
1327 msg_free (msg);
1328 }
1329 rc = 0;
1330
1331out:
1332 return rc;
1333}
1334
1335int
1336ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1337 struct msg *msg)
1338{
paul1eb8ef22005-04-07 07:30:20 +00001339 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00001340 u_int32_t seqnum;
1341 int rc = 0;
1342 struct msg_sync_lsdb *smsg;
paul1eb8ef22005-04-07 07:30:20 +00001343 struct ospf_apiserver_param_t
paul2d33f152003-03-17 01:10:58 +00001344 {
1345 struct ospf_apiserver *apiserv;
1346 struct lsa_filter_type *filter;
paul1eb8ef22005-04-07 07:30:20 +00001347 } param;
paul2d33f152003-03-17 01:10:58 +00001348 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001349 struct route_node *rn;
1350 struct ospf_lsa *lsa;
1351 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001352 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001353
1354 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001355
1356 /* Get request sequence number */
1357 seqnum = msg_get_seq (msg);
1358 /* Set sync msg. */
1359 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1360
1361 /* Set parameter struct. */
1362 param.apiserv = apiserv;
1363 param.filter = &smsg->filter;
1364
1365 /* Remember mask. */
1366 mask = ntohs (smsg->filter.typemask);
1367
1368 /* Iterate over all areas. */
paul1eb8ef22005-04-07 07:30:20 +00001369 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001370 {
paul2d33f152003-03-17 01:10:58 +00001371 int i;
1372 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001373
paul2d33f152003-03-17 01:10:58 +00001374 /* Compare area_id with area_ids in sync request. */
1375 if ((i = smsg->filter.num_areas) > 0)
1376 {
1377 /* Let area_id point to the list of area IDs,
1378 * which is at the end of smsg->filter. */
1379 area_id = (u_int32_t *) (&smsg->filter + 1);
1380 while (i)
1381 {
1382 if (*area_id == area->area_id.s_addr)
1383 {
1384 break;
1385 }
1386 i--;
1387 area_id++;
1388 }
1389 }
1390 else
1391 {
1392 i = 1;
1393 }
1394
1395 /* If area was found, then i>0 here. */
1396 if (i)
1397 {
1398 /* Check msg type. */
1399 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001400 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1401 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001402 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001403 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1404 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001405 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001406 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1407 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001408 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001409 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1410 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001411 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001412 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1413 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001414 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001415 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1416 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001417 }
1418 }
1419
1420 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001421 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001422 {
1423 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001424 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1425 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001426 }
1427
1428 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001429 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001430 {
1431 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001432 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1433 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001434 }
1435
1436 /* Send a reply back to client with return code */
1437 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1438 return rc;
1439}
1440
1441
1442/* -----------------------------------------------------------
1443 * Followings are functions to originate or update LSA
1444 * from an application.
1445 * -----------------------------------------------------------
1446 */
1447
1448/* Create a new internal opaque LSA by taking prototype and filling in
1449 missing fields such as age, sequence number, advertising router,
1450 checksum and so on. The interface parameter is used for type 9
1451 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1452 nor interface. */
1453
1454struct ospf_lsa *
1455ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1456 struct ospf_interface *oi,
1457 struct lsa_header *protolsa)
1458{
1459 struct stream *s;
1460 struct lsa_header *newlsa;
1461 struct ospf_lsa *new = NULL;
1462 u_char options = 0x0;
1463 u_int16_t length;
1464
paul99b7c5d2003-04-06 01:19:28 +00001465 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001466
paul99b7c5d2003-04-06 01:19:28 +00001467 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001468 assert(ospf);
1469
paul2d33f152003-03-17 01:10:58 +00001470 /* Create a stream for internal opaque LSA */
1471 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1472 {
1473 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1474 return NULL;
1475 }
1476
1477 newlsa = (struct lsa_header *) STREAM_DATA (s);
1478
1479 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1480 have to set options? */
1481
1482 if (area)
1483 {
1484 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001485 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001486 }
1487
1488 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1489
1490 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1491 {
ajse84cc642004-12-08 17:28:56 +00001492 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
paul2d33f152003-03-17 01:10:58 +00001493 protolsa->type, inet_ntoa (protolsa->id));
1494 }
1495
1496 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001497 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001498 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001499
1500 /* Set opaque-LSA body fields. */
1501 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1502 ntohs (protolsa->length) - sizeof (struct lsa_header));
1503
1504 /* Determine length of LSA. */
1505 length = stream_get_endp (s);
1506 newlsa->length = htons (length);
1507
1508 /* Create OSPF LSA. */
1509 if ((new = ospf_lsa_new ()) == NULL)
1510 {
1511 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1512 stream_free (s);
1513 return NULL;
1514 }
1515
1516 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1517 {
1518 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001519 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001520 stream_free (s);
1521 return NULL;
1522 }
1523
1524 new->area = area;
1525 new->oi = oi;
1526
1527 SET_FLAG (new->flags, OSPF_LSA_SELF);
1528 memcpy (new->data, newlsa, length);
1529 stream_free (s);
1530
1531 return new;
1532}
1533
1534
1535int
1536ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1537{
1538 /* Type 9 opaque LSA can be originated if there is at least one
1539 active opaque-capable neighbor attached to the outgoing
1540 interface. */
1541
paula15f45d2003-03-28 01:50:03 +00001542 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001543}
1544
1545int
1546ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1547{
1548 /* Type 10 opaque LSA can be originated if there is at least one
1549 interface belonging to the area that has an active opaque-capable
1550 neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001551 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001552 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001553
paul1eb8ef22005-04-07 07:30:20 +00001554 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001555 /* Is there an active neighbor attached to this interface? */
1556 if (ospf_apiserver_is_ready_type9 (oi))
1557 return 1;
paul2d33f152003-03-17 01:10:58 +00001558
paul2d33f152003-03-17 01:10:58 +00001559 /* No active neighbor in area */
1560 return 0;
1561}
1562
1563int
1564ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1565{
1566 /* Type 11 opaque LSA can be originated if there is at least one interface
1567 that has an active opaque-capable neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001568 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001569 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001570
paul1eb8ef22005-04-07 07:30:20 +00001571 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001572 /* Is there an active neighbor attached to this interface? */
1573 if (ospf_apiserver_is_ready_type9 (oi))
1574 return 1;
paul2d33f152003-03-17 01:10:58 +00001575
paul2d33f152003-03-17 01:10:58 +00001576 /* No active neighbor at all */
1577 return 0;
1578}
1579
1580
1581int
1582ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1583 struct msg *msg)
1584{
1585 struct msg_originate_request *omsg;
1586 struct lsa_header *data;
1587 struct ospf_lsa *new;
1588 struct ospf_lsa *old;
1589 struct ospf_area *area = NULL;
1590 struct ospf_interface *oi = NULL;
1591 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001592 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001593 int lsa_type, opaque_type;
1594 int ready = 0;
1595 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001596
paul99b7c5d2003-04-06 01:19:28 +00001597 ospf = ospf_lookup();
1598
paul2d33f152003-03-17 01:10:58 +00001599 /* Extract opaque LSA data from message */
1600 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1601 data = &omsg->data;
1602
1603 /* Determine interface for type9 or area for type10 LSAs. */
1604 switch (data->type)
1605 {
1606 case OSPF_OPAQUE_LINK_LSA:
1607 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1608 if (!oi)
1609 {
1610 zlog_warn ("apiserver_originate: unknown interface %s",
1611 inet_ntoa (omsg->ifaddr));
1612 rc = OSPF_API_NOSUCHINTERFACE;
1613 goto out;
1614 }
1615 area = oi->area;
1616 lsdb = area->lsdb;
1617 break;
1618 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001619 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001620 if (!area)
1621 {
1622 zlog_warn ("apiserver_originate: unknown area %s",
1623 inet_ntoa (omsg->area_id));
1624 rc = OSPF_API_NOSUCHAREA;
1625 goto out;
1626 }
1627 lsdb = area->lsdb;
1628 break;
1629 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001630 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001631 break;
1632 default:
1633 /* We can only handle opaque types here */
1634 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1635 data->type);
1636 rc = OSPF_API_ILLEGALLSATYPE;
1637 goto out;
1638 }
1639
1640 /* Check if we registered this opaque type */
1641 lsa_type = data->type;
1642 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1643
1644 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1645 {
1646 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1647 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1648 goto out;
1649 }
1650
1651 /* Make sure that the neighbors are ready before we can originate */
1652 switch (data->type)
1653 {
1654 case OSPF_OPAQUE_LINK_LSA:
1655 ready = ospf_apiserver_is_ready_type9 (oi);
1656 break;
1657 case OSPF_OPAQUE_AREA_LSA:
1658 ready = ospf_apiserver_is_ready_type10 (area);
1659 break;
1660 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001661 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001662 break;
1663 default:
1664 break;
1665 }
1666
1667 if (!ready)
1668 {
1669 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1670 rc = OSPF_API_NOTREADY;
1671 goto out;
1672 }
1673
1674 /* Create OSPF's internal opaque LSA representation */
1675 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1676 if (!new)
1677 {
1678 rc = OSPF_API_NOMEMORY; /* XXX */
1679 goto out;
1680 }
1681
1682 /* Determine if LSA is new or an update for an existing one. */
1683 old = ospf_lsdb_lookup (lsdb, new);
1684
1685 if (!old)
1686 {
1687 /* New LSA install in LSDB. */
1688 rc = ospf_apiserver_originate1 (new);
1689 }
1690 else
1691 {
1692 /*
1693 * Keep the new LSA instance in the "waiting place" until the next
1694 * refresh timing. If several LSA update requests for the same LSID
1695 * have issued by peer, the last one takes effect.
1696 */
1697 new->lsdb = &apiserv->reserve;
1698 ospf_lsdb_add (&apiserv->reserve, new);
1699
1700 /* Kick the scheduler function. */
1701 ospf_opaque_lsa_refresh_schedule (old);
1702 }
1703
1704out:
1705
1706 /* Send a reply back to client with return code */
1707 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1708 return rc;
1709}
1710
1711
1712/* -----------------------------------------------------------
1713 * Flood an LSA within its flooding scope.
1714 * -----------------------------------------------------------
1715 */
1716
1717/* XXX We can probably use ospf_flood_through instead of this function
1718 but then we need the neighbor parameter. If we set nbr to
1719 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1720
1721void
1722ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1723{
1724 assert (lsa);
1725
1726 switch (lsa->data->type)
1727 {
1728 case OSPF_OPAQUE_LINK_LSA:
1729 /* Increment counters? XXX */
1730
1731 /* Flood LSA through local network. */
1732 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1733 break;
1734 case OSPF_OPAQUE_AREA_LSA:
1735 /* Update LSA origination count. */
1736 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001737 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001738
1739 /* Flood LSA through area. */
1740 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1741 break;
1742 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001743 {
paul99b7c5d2003-04-06 01:19:28 +00001744 struct ospf *ospf;
1745
1746 ospf = ospf_lookup();
1747 assert(ospf);
1748
paul7d5e2682003-04-05 19:41:07 +00001749 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001750
paul7d5e2682003-04-05 19:41:07 +00001751 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001752 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001753 break;
1754 }
paul2d33f152003-03-17 01:10:58 +00001755 }
1756}
1757
1758int
1759ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1760{
paul99b7c5d2003-04-06 01:19:28 +00001761 struct ospf *ospf;
1762
1763 ospf = ospf_lookup();
1764 assert(ospf);
1765
paul2d33f152003-03-17 01:10:58 +00001766 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001767 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001768 {
1769 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1770 return -1;
1771 }
1772
1773 /* Flood LSA within scope */
1774
1775#ifdef NOTYET
1776 /*
1777 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1778 * parameter, and thus it does not cause SIGSEGV error.
1779 */
1780 ospf_flood_through (NULL /*nbr */ , lsa);
1781#else /* NOTYET */
1782
1783 ospf_apiserver_flood_opaque_lsa (lsa);
1784#endif /* NOTYET */
1785
1786 return 0;
1787}
1788
1789
1790/* Opaque LSAs of type 9 on a specific interface can now be
1791 originated. Tell clients that registered type 9. */
1792int
1793ospf_apiserver_lsa9_originator (void *arg)
1794{
1795 struct ospf_interface *oi;
1796
1797 oi = (struct ospf_interface *) arg;
1798 if (listcount (apiserver_list) > 0) {
1799 ospf_apiserver_clients_notify_ready_type9 (oi);
1800 }
1801 return 0;
1802}
1803
1804int
1805ospf_apiserver_lsa10_originator (void *arg)
1806{
1807 struct ospf_area *area;
1808
1809 area = (struct ospf_area *) arg;
1810 if (listcount (apiserver_list) > 0) {
1811 ospf_apiserver_clients_notify_ready_type10 (area);
1812 }
1813 return 0;
1814}
1815
1816int
1817ospf_apiserver_lsa11_originator (void *arg)
1818{
1819 struct ospf *ospf;
1820
1821 ospf = (struct ospf *) arg;
1822 if (listcount (apiserver_list) > 0) {
1823 ospf_apiserver_clients_notify_ready_type11 (ospf);
1824 }
1825 return 0;
1826}
1827
1828
1829/* Periodically refresh opaque LSAs so that they do not expire in
1830 other routers. */
Paul Jakma072990e2011-04-11 16:28:16 +01001831struct ospf_lsa *
paul2d33f152003-03-17 01:10:58 +00001832ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1833{
1834 struct ospf_apiserver *apiserv;
1835 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001836 struct ospf * ospf;
1837
1838 ospf = ospf_lookup();
1839 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001840
1841 apiserv = lookup_apiserver_by_lsa (lsa);
1842 if (!apiserv)
1843 {
1844 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1845 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1846 }
1847
1848 if (IS_LSA_MAXAGE (lsa))
1849 {
1850 ospf_opaque_lsa_flush_schedule (lsa);
1851 goto out;
1852 }
1853
1854 /* Check if updated version of LSA instance has already prepared. */
1855 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1856 if (!new)
1857 {
1858 /* This is a periodic refresh, driven by core OSPF mechanism. */
1859 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1860 if (!new)
1861 {
1862 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1863 goto out;
1864 }
1865 }
1866 else
1867 {
1868 /* This is a forcible refresh, requested by OSPF-API client. */
1869 ospf_lsdb_delete (&apiserv->reserve, new);
1870 new->lsdb = NULL;
1871 }
1872
1873 /* Increment sequence number */
1874 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1875
1876 /* New LSA is in same area. */
1877 new->area = lsa->area;
1878 SET_FLAG (new->flags, OSPF_LSA_SELF);
1879
1880 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001881 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001882 {
1883 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001884 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001885 goto out;
1886 }
1887
1888 /* Flood updated LSA through interface, area or AS */
1889
1890#ifdef NOTYET
1891 ospf_flood_through (NULL /*nbr */ , new);
1892#endif /* NOTYET */
1893 ospf_apiserver_flood_opaque_lsa (new);
1894
1895 /* Debug logging. */
1896 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1897 {
ajse84cc642004-12-08 17:28:56 +00001898 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
paul2d33f152003-03-17 01:10:58 +00001899 new->data->type, inet_ntoa (new->data->id));
1900 ospf_lsa_header_dump (new->data);
1901 }
1902
1903out:
Paul Jakma072990e2011-04-11 16:28:16 +01001904 return new;
paul2d33f152003-03-17 01:10:58 +00001905}
1906
1907
1908/* -----------------------------------------------------------
1909 * Followings are functions to delete LSAs
1910 * -----------------------------------------------------------
1911 */
1912
1913int
1914ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1915 struct msg *msg)
1916{
1917 struct msg_delete_request *dmsg;
1918 struct ospf_lsa *old;
1919 struct ospf_area *area = NULL;
1920 struct in_addr id;
1921 int lsa_type, opaque_type;
1922 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001923 struct ospf * ospf;
1924
1925 ospf = ospf_lookup();
1926 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001927
1928 /* Extract opaque LSA from message */
1929 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1930
1931 /* Lookup area for link-local and area-local opaque LSAs */
1932 switch (dmsg->lsa_type)
1933 {
1934 case OSPF_OPAQUE_LINK_LSA:
1935 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001936 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001937 if (!area)
1938 {
1939 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1940 inet_ntoa (dmsg->area_id));
1941 rc = OSPF_API_NOSUCHAREA;
1942 goto out;
1943 }
1944 break;
1945 case OSPF_OPAQUE_AS_LSA:
1946 /* AS-external opaque LSAs have no designated area */
1947 area = NULL;
1948 break;
1949 default:
1950 zlog_warn
1951 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1952 dmsg->lsa_type);
1953 rc = OSPF_API_ILLEGALLSATYPE;
1954 goto out;
1955 }
1956
1957 /* Check if we registered this opaque type */
1958 lsa_type = dmsg->lsa_type;
1959 opaque_type = dmsg->opaque_type;
1960
1961 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1962 {
1963 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1964 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1965 goto out;
1966 }
1967
1968 /* opaque_id is in network byte order */
1969 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1970 ntohl (dmsg->opaque_id)));
1971
1972 /*
1973 * Even if the target LSA has once scheduled to flush, it remains in
1974 * the LSDB until it is finally handled by the maxage remover thread.
1975 * Therefore, the lookup function below may return non-NULL result.
1976 */
paul99b7c5d2003-04-06 01:19:28 +00001977 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001978 if (!old)
1979 {
1980 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1981 dmsg->lsa_type, inet_ntoa (id));
1982 rc = OSPF_API_NOSUCHLSA;
1983 goto out;
1984 }
1985
1986 /* Schedule flushing of LSA from LSDB */
1987 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1988 ospf_opaque_lsa_flush_schedule (old);
1989
1990out:
1991
1992 /* Send reply back to client including return code */
1993 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1994 return rc;
1995}
1996
1997/* Flush self-originated opaque LSA */
paul4dadc292005-05-06 21:37:42 +00001998static int
paul2d33f152003-03-17 01:10:58 +00001999apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2000 void *p_arg, int int_arg)
2001{
2002 struct param_t
2003 {
2004 struct ospf_apiserver *apiserv;
2005 u_char lsa_type;
2006 u_char opaque_type;
2007 }
2008 *param;
2009
2010 /* Sanity check */
2011 assert (lsa->data);
2012 assert (p_arg);
2013 param = (struct param_t *) p_arg;
2014
2015 /* If LSA matches type and opaque type then delete it */
2016 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2017 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2018 {
2019 ospf_opaque_lsa_flush_schedule (lsa);
2020 }
2021 return 0;
2022}
2023
2024/* Delete self-originated opaque LSAs of a given opaque type. This
2025 function is called when an application unregisters a given opaque
2026 type or a connection to an application closes and all those opaque
2027 LSAs need to be flushed the LSDB. */
2028void
2029ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2030 u_char lsa_type, u_char opaque_type)
2031{
2032 struct param_t
2033 {
2034 struct ospf_apiserver *apiserv;
2035 u_char lsa_type;
2036 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002037 } param;
paul1eb8ef22005-04-07 07:30:20 +00002038 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00002039 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002040 struct ospf_area *area;
2041
paul99b7c5d2003-04-06 01:19:28 +00002042 ospf = ospf_lookup();
2043 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002044
2045 /* Set parameter struct. */
2046 param.apiserv = apiserv;
2047 param.lsa_type = lsa_type;
2048 param.opaque_type = opaque_type;
2049
paul2d33f152003-03-17 01:10:58 +00002050 switch (lsa_type)
2051 {
paul99b7c5d2003-04-06 01:19:28 +00002052 struct route_node *rn;
2053 struct ospf_lsa *lsa;
2054
paul2d33f152003-03-17 01:10:58 +00002055 case OSPF_OPAQUE_LINK_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002056 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002057 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2058 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002059 break;
2060 case OSPF_OPAQUE_AREA_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002061 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002062 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2063 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002064 break;
2065 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002066 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2067 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002068 break;
2069 default:
2070 break;
2071 }
2072 return;
paul2d33f152003-03-17 01:10:58 +00002073}
2074
2075
2076/* -----------------------------------------------------------
2077 * Followings are callback functions to handle opaque types
2078 * -----------------------------------------------------------
2079 */
2080
2081int
2082ospf_apiserver_new_if (struct interface *ifp)
2083{
2084 struct ospf_interface *oi;
2085
2086 /* For some strange reason it seems possible that we are invoked
2087 with an interface that has no name. This seems to happen during
2088 initialization. Return if this happens */
2089
2090 if (ifp->name[0] == '\0') {
2091 /* interface has empty name */
2092 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2093 return 0;
2094 }
2095
2096 /* zlog_warn for debugging */
2097 zlog_warn ("ospf_apiserver_new_if");
2098 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2099 ifp->ifindex);
2100
2101 if (ifp->name[0] == '\0') {
2102 /* interface has empty name */
2103 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2104 return 0;
2105 }
2106
2107 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2108
2109 if (!oi) {
2110 /* This interface is known to Zebra but not to OSPF daemon yet. */
2111 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2112 ifp->name);
2113 return 0;
2114 }
2115
2116 assert (oi);
2117
2118 /* New interface added to OSPF, tell clients about it */
2119 if (listcount (apiserver_list) > 0) {
2120 ospf_apiserver_clients_notify_new_if (oi);
2121 }
2122 return 0;
2123}
2124
2125int
2126ospf_apiserver_del_if (struct interface *ifp)
2127{
2128 struct ospf_interface *oi;
2129
2130 /* zlog_warn for debugging */
2131 zlog_warn ("ospf_apiserver_del_if");
2132 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2133 ifp->ifindex);
2134
2135 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002136
2137 if (!oi) {
2138 /* This interface is known to Zebra but not to OSPF daemon
2139 anymore. No need to tell clients about it */
2140 return 0;
2141 }
paul2d33f152003-03-17 01:10:58 +00002142
2143 /* Interface deleted, tell clients about it */
2144 if (listcount (apiserver_list) > 0) {
2145 ospf_apiserver_clients_notify_del_if (oi);
2146 }
2147 return 0;
2148}
2149
2150void
2151ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2152{
2153 /* Tell clients about interface change */
2154
2155 /* zlog_warn for debugging */
2156 zlog_warn ("ospf_apiserver_ism_change");
2157 if (listcount (apiserver_list) > 0) {
2158 ospf_apiserver_clients_notify_ism_change (oi);
2159 }
2160
2161 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2162 zlog_warn ("old_state=%d", old_state);
2163 zlog_warn ("oi->state=%d", oi->state);
2164}
2165
2166void
2167ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2168{
2169 /* Neighbor status changed, tell clients about it */
2170 zlog_warn ("ospf_apiserver_nsm_change");
2171 if (listcount (apiserver_list) > 0) {
2172 ospf_apiserver_clients_notify_nsm_change (nbr);
2173 }
2174}
2175
2176void
2177ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2178{
2179 struct opaque_lsa
2180 {
2181 struct lsa_header header;
2182 u_char data[1]; /* opaque data have variable length. This is start
2183 address */
2184 };
2185 struct opaque_lsa *olsa;
2186 int opaquelen;
2187
2188 olsa = (struct opaque_lsa *) lsa->data;
2189
2190 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002191 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002192 else
paul87d6f872004-09-24 08:01:38 +00002193 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002194
2195 /* Output information about opaque LSAs */
2196 if (vty != NULL)
2197 {
2198 int i;
2199 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2200 opaquelen,
2201 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2202 VTY_NEWLINE);
2203 vty_out (vty, " Opaque data: ");
2204
2205 for (i = 0; i < opaquelen; i++)
2206 {
2207 vty_out (vty, "0x%x ", olsa->data[i]);
2208 }
2209 vty_out (vty, "%s", VTY_NEWLINE);
2210 }
2211 else
2212 {
2213 int i;
ajse84cc642004-12-08 17:28:56 +00002214 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
paul2d33f152003-03-17 01:10:58 +00002215 opaquelen,
2216 VALID_OPAQUE_INFO_LEN (lsa->
2217 data) ? "" : "(Invalid length?)");
ajse84cc642004-12-08 17:28:56 +00002218 zlog_debug (" Opaque data: ");
paul2d33f152003-03-17 01:10:58 +00002219
2220 for (i = 0; i < opaquelen; i++)
2221 {
ajse84cc642004-12-08 17:28:56 +00002222 zlog_debug ("0x%x ", olsa->data[i]);
paul2d33f152003-03-17 01:10:58 +00002223 }
ajse84cc642004-12-08 17:28:56 +00002224 zlog_debug ("\n");
paul2d33f152003-03-17 01:10:58 +00002225 }
2226 return;
2227}
2228
2229/* -----------------------------------------------------------
2230 * Followings are functions to notify clients about events
2231 * -----------------------------------------------------------
2232 */
2233
2234/* Send a message to all clients. This is useful for messages
2235 that need to be notified to all clients (such as interface
2236 changes) */
2237
2238void
2239ospf_apiserver_clients_notify_all (struct msg *msg)
2240{
paul1eb8ef22005-04-07 07:30:20 +00002241 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002242 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002243
2244 /* Send message to all clients */
paul1eb8ef22005-04-07 07:30:20 +00002245 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul87d6f872004-09-24 08:01:38 +00002246 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002247}
2248
2249/* An interface is now ready to accept opaque LSAs. Notify all
2250 clients that registered to use this opaque type */
2251void
2252ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2253{
paul1eb8ef22005-04-07 07:30:20 +00002254 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002255 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002256 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002257
2258 assert (oi);
2259 if (!oi->address)
2260 {
2261 zlog_warn ("Interface has no address?");
2262 return;
2263 }
2264
2265 if (!ospf_apiserver_is_ready_type9 (oi))
2266 {
2267 zlog_warn ("Interface not ready for type 9?");
2268 return;
2269 }
2270
paul1eb8ef22005-04-07 07:30:20 +00002271 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002272 {
paul1eb8ef22005-04-07 07:30:20 +00002273 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002274 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002275
paul1eb8ef22005-04-07 07:30:20 +00002276 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002277 {
paul2d33f152003-03-17 01:10:58 +00002278 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2279 {
2280 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2281 r->opaque_type,
2282 oi->address->u.prefix4);
2283 if (!msg)
2284 {
2285 zlog_warn
2286 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2287#ifdef NOTYET
2288 /* Cannot allocate new message. What should we do? */
2289 ospf_apiserver_free (apiserv);
2290#endif
2291 goto out;
2292 }
2293
2294 ospf_apiserver_send_msg (apiserv, msg);
2295 msg_free (msg);
2296 }
2297 }
2298 }
2299
2300out:
2301 return;
2302}
2303
2304void
2305ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2306{
paul1eb8ef22005-04-07 07:30:20 +00002307 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002308 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002309 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002310
2311 assert (area);
2312
2313 if (!ospf_apiserver_is_ready_type10 (area))
2314 {
2315 zlog_warn ("Area not ready for type 10?");
2316 return;
2317 }
2318
paul1eb8ef22005-04-07 07:30:20 +00002319 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002320 {
paul1eb8ef22005-04-07 07:30:20 +00002321 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002322 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002323
paul1eb8ef22005-04-07 07:30:20 +00002324 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002325 {
paul2d33f152003-03-17 01:10:58 +00002326 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2327 {
2328 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2329 r->opaque_type, area->area_id);
2330 if (!msg)
2331 {
2332 zlog_warn
2333 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2334#ifdef NOTYET
2335 /* Cannot allocate new message. What should we do? */
2336 ospf_apiserver_free (apiserv);
2337#endif
paul87d6f872004-09-24 08:01:38 +00002338 goto out;
paul2d33f152003-03-17 01:10:58 +00002339 }
2340
2341 ospf_apiserver_send_msg (apiserv, msg);
2342 msg_free (msg);
2343 }
2344 }
2345 }
2346
2347out:
2348 return;
2349}
2350
2351
2352void
2353ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2354{
paul1eb8ef22005-04-07 07:30:20 +00002355 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002356 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002357 struct in_addr id_null = { .s_addr = 0L };
paul87d6f872004-09-24 08:01:38 +00002358 struct ospf_apiserver *apiserv;
paul36238142005-10-11 04:12:54 +00002359
paul2d33f152003-03-17 01:10:58 +00002360 assert (top);
paul36238142005-10-11 04:12:54 +00002361
paul2d33f152003-03-17 01:10:58 +00002362 if (!ospf_apiserver_is_ready_type11 (top))
2363 {
2364 zlog_warn ("AS not ready for type 11?");
2365 return;
2366 }
2367
paul1eb8ef22005-04-07 07:30:20 +00002368 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002369 {
paul1eb8ef22005-04-07 07:30:20 +00002370 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002371 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002372
paul1eb8ef22005-04-07 07:30:20 +00002373 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002374 {
paul2d33f152003-03-17 01:10:58 +00002375 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2376 {
2377 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2378 r->opaque_type, id_null);
2379 if (!msg)
2380 {
2381 zlog_warn
2382 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2383#ifdef NOTYET
2384 /* Cannot allocate new message. What should we do? */
2385 ospf_apiserver_free (apiserv);
2386#endif
2387 goto out;
2388 }
2389
2390 ospf_apiserver_send_msg (apiserv, msg);
2391 msg_free (msg);
2392 }
2393 }
2394 }
2395
2396out:
2397 return;
2398}
2399
2400void
2401ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2402{
2403 struct msg *msg;
2404
2405 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2406 if (msg != NULL)
2407 {
2408 ospf_apiserver_clients_notify_all (msg);
2409 msg_free (msg);
2410 }
2411}
2412
2413void
2414ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2415{
2416 struct msg *msg;
2417
2418 msg = new_msg_del_if (0, oi->address->u.prefix4);
2419 if (msg != NULL)
2420 {
2421 ospf_apiserver_clients_notify_all (msg);
2422 msg_free (msg);
2423 }
2424}
2425
2426void
2427ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2428{
2429 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002430 struct in_addr ifaddr = { .s_addr = 0L };
2431 struct in_addr area_id = { .s_addr = 0L };
2432
paul2d33f152003-03-17 01:10:58 +00002433 assert (oi);
2434 assert (oi->ifp);
paul36238142005-10-11 04:12:54 +00002435
paul2d33f152003-03-17 01:10:58 +00002436 if (oi->address)
2437 {
2438 ifaddr = oi->address->u.prefix4;
2439 }
2440 if (oi->area)
2441 {
2442 area_id = oi->area->area_id;
2443 }
2444
hasso1ddd7292005-06-07 19:54:04 +00002445 msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
paul2d33f152003-03-17 01:10:58 +00002446 if (!msg)
2447 {
2448 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2449 return;
2450 }
2451
2452 ospf_apiserver_clients_notify_all (msg);
2453 msg_free (msg);
2454}
2455
2456void
2457ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2458{
2459 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002460 struct in_addr ifaddr = { .s_addr = 0L };
2461 struct in_addr nbraddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002462
2463 assert (nbr);
2464
2465 if (nbr->oi)
2466 {
2467 ifaddr = nbr->oi->address->u.prefix4;
2468 }
2469
2470 nbraddr = nbr->address.u.prefix4;
2471
2472 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2473 if (!msg)
2474 {
2475 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2476 return;
2477 }
2478
2479 ospf_apiserver_clients_notify_all (msg);
2480 msg_free (msg);
2481}
2482
paul4dadc292005-05-06 21:37:42 +00002483static void
paul2d33f152003-03-17 01:10:58 +00002484apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2485{
2486 struct msg *msg;
paul1eb8ef22005-04-07 07:30:20 +00002487 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002488 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002489
2490 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002491 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002492
2493 /* Default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002494 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002495
2496 if (lsa->area)
2497 {
2498 area_id = lsa->area->area_id;
2499 }
2500 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2501 {
2502 assert (lsa->oi);
2503 ifaddr = lsa->oi->address->u.prefix4;
2504 }
2505
2506 /* Prepare message that can be sent to clients that have a matching
2507 filter */
2508 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2509 ifaddr, area_id,
2510 lsa->flags & OSPF_LSA_SELF, lsa->data);
2511 if (!msg)
2512 {
2513 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2514 return;
2515 }
2516
2517 /* Now send message to all clients with a matching filter */
paul1eb8ef22005-04-07 07:30:20 +00002518 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002519 {
paul2d33f152003-03-17 01:10:58 +00002520 struct lsa_filter_type *filter;
2521 u_int16_t mask;
2522 u_int32_t *area;
2523 int i;
2524
2525 /* Check filter for this client. */
2526 filter = apiserv->filter;
2527
2528 /* Check area IDs in case of non AS-E LSAs.
2529 * If filter has areas (num_areas > 0),
2530 * then one of the areas must match the area ID of this LSA. */
2531
2532 i = filter->num_areas;
2533 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2534 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2535 {
2536 i = 0;
2537 }
2538
2539 if (i > 0)
2540 {
2541 area = (u_int32_t *) (filter + 1);
2542 while (i)
2543 {
2544 if (*area == area_id.s_addr)
2545 {
2546 break;
2547 }
2548 i--;
2549 area++;
2550 }
2551 }
2552 else
2553 {
2554 i = 1;
2555 }
2556
2557 if (i > 0)
2558 {
2559 /* Area match. Check LSA type. */
2560 mask = ntohs (filter->typemask);
2561
2562 if (mask & Power2[lsa->data->type])
2563 {
2564 /* Type also matches. Check origin. */
2565 if ((filter->origin == ANY_ORIGIN) ||
2566 (filter->origin == IS_LSA_SELF (lsa)))
2567 {
2568 ospf_apiserver_send_msg (apiserv, msg);
2569 }
2570 }
2571 }
2572 }
2573 /* Free message since it is not used anymore */
2574 msg_free (msg);
2575}
2576
2577
2578/* -------------------------------------------------------------
2579 * Followings are hooks invoked when LSAs are updated or deleted
2580 * -------------------------------------------------------------
2581 */
2582
2583
paul4dadc292005-05-06 21:37:42 +00002584static int
paul2d33f152003-03-17 01:10:58 +00002585apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2586{
2587 struct msg *msg;
2588 /* default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002589 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002590
2591 /* default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002592 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002593
2594 /* Only notify this update if the LSA's age is smaller than
2595 MAXAGE. Otherwise clients would see LSA updates with max age just
2596 before they are deleted from the LSDB. LSA delete messages have
2597 MAXAGE too but should not be filtered. */
2598 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2599 return 0;
2600 }
2601
2602 if (lsa->area)
2603 {
2604 area_id = lsa->area->area_id;
2605 }
2606 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2607 {
2608 ifaddr = lsa->oi->address->u.prefix4;
2609 }
2610 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2611 ifaddr, area_id,
2612 lsa->flags & OSPF_LSA_SELF, lsa->data);
2613 if (!msg)
2614 {
2615 zlog_warn ("notify_clients_lsa: msg_new failed");
2616 return -1;
2617 }
2618 /* Notify all clients that new LSA is added/updated */
2619 apiserver_clients_lsa_change_notify (msgtype, lsa);
2620
2621 /* Clients made their own copies of msg so we can free msg here */
2622 msg_free (msg);
2623
2624 return 0;
2625}
2626
2627int
2628ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2629{
2630 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2631}
2632
2633int
2634ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2635{
2636 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2637}
2638
2639#endif /* SUPPORT_OSPF_API */
2640