blob: aac8ef4b8b529974aa192fcf4cb44b4ecc5a61c1 [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
paul2d33f152003-03-17 01:10:58 +000026
27#include "linklist.h"
28#include "prefix.h"
29#include "if.h"
30#include "table.h"
31#include "memory.h"
32#include "command.h"
33#include "vty.h"
34#include "stream.h"
35#include "log.h"
36#include "thread.h"
37#include "hash.h"
38#include "sockunion.h" /* for inet_aton() */
39#include "buffer.h"
40
41#include <sys/types.h>
42
43#include "ospfd/ospfd.h" /* for "struct thread_master" */
44#include "ospfd/ospf_interface.h"
45#include "ospfd/ospf_ism.h"
46#include "ospfd/ospf_asbr.h"
47#include "ospfd/ospf_lsa.h"
48#include "ospfd/ospf_lsdb.h"
49#include "ospfd/ospf_neighbor.h"
50#include "ospfd/ospf_nsm.h"
51#include "ospfd/ospf_flood.h"
52#include "ospfd/ospf_packet.h"
53#include "ospfd/ospf_spf.h"
54#include "ospfd/ospf_dump.h"
55#include "ospfd/ospf_route.h"
56#include "ospfd/ospf_ase.h"
57#include "ospfd/ospf_zebra.h"
58
59#include "ospfd/ospf_api.h"
60#include "ospfd/ospf_apiserver.h"
61
62/* This is an implementation of an API to the OSPF daemon that allows
63 * external applications to access the OSPF daemon through socket
64 * connections. The application can use this API to inject its own
65 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
66 * daemons then receive these LSAs and inform applications through the
67 * API by sending a corresponding message. The application can also
68 * register to receive all LSA types (in addition to opaque types) and
69 * use this information to reconstruct the OSPF's LSDB. The OSPF
70 * daemon supports multiple applications concurrently. */
71
72/* List of all active connections. */
paul87d6f872004-09-24 08:01:38 +000073struct list *apiserver_list;
paul2d33f152003-03-17 01:10:58 +000074
75/* -----------------------------------------------------------
76 * Functions to lookup interfaces
77 * -----------------------------------------------------------
78 */
79
80struct ospf_interface *
81ospf_apiserver_if_lookup_by_addr (struct in_addr address)
82{
paul1eb8ef22005-04-07 07:30:20 +000083 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +000084 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +000085 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +000086
paulafbacce2003-07-09 16:09:20 +000087 if (!(ospf = ospf_lookup ()))
paul5549c6b2003-07-09 15:46:33 +000088 return NULL;
paul99b7c5d2003-04-06 01:19:28 +000089
paul1eb8ef22005-04-07 07:30:20 +000090 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +000091 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
92 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
93 return oi;
94
paul2d33f152003-03-17 01:10:58 +000095 return NULL;
96}
97
98struct ospf_interface *
99ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
100{
paul1eb8ef22005-04-07 07:30:20 +0000101 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +0000102 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +0000103 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000104
Hasso Tepper8c9ed272012-10-11 11:15:18 +0000105 if (!(ospf = ospf_lookup ()))
paul5549c6b2003-07-09 15:46:33 +0000106 return NULL;
paul99b7c5d2003-04-06 01:19:28 +0000107
paul1eb8ef22005-04-07 07:30:20 +0000108 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +0000109 if (oi->ifp == ifp)
110 return oi;
111
paul2d33f152003-03-17 01:10:58 +0000112 return NULL;
113}
114
115/* -----------------------------------------------------------
116 * Initialization
117 * -----------------------------------------------------------
118 */
119
120unsigned short
121ospf_apiserver_getport (void)
122{
123 struct servent *sp = getservbyname ("ospfapi", "tcp");
124
125 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
126}
127
128/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
129int
130ospf_apiserver_init (void)
131{
132 int fd;
133 int rc = -1;
134
135 /* Create new socket for synchronous messages. */
136 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
137
138 if (fd < 0)
139 goto out;
140
141 /* Schedule new thread that handles accepted connections. */
142 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
143
144 /* Initialize list that keeps track of all connections. */
145 apiserver_list = list_new ();
146
147 /* Register opaque-independent call back functions. These functions
148 are invoked on ISM, NSM changes and LSA update and LSA deletes */
149 rc =
150 ospf_register_opaque_functab (0 /* all LSAs */,
151 0 /* all opaque types */,
152 ospf_apiserver_new_if,
153 ospf_apiserver_del_if,
154 ospf_apiserver_ism_change,
155 ospf_apiserver_nsm_change,
156 NULL,
157 NULL,
158 NULL,
159 NULL, /* ospf_apiserver_show_info */
160 NULL, /* originator_func */
161 NULL, /* ospf_apiserver_lsa_refresher */
162 ospf_apiserver_lsa_update,
163 ospf_apiserver_lsa_delete);
164 if (rc != 0)
165 {
166 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
167 }
168
169 rc = 0;
170
171out:
172 return rc;
173}
174
175/* Terminate OSPF API module. */
176void
177ospf_apiserver_term (void)
178{
paul87d6f872004-09-24 08:01:38 +0000179 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +0000180
181 /* Unregister wildcard [0/0] type */
182 ospf_delete_opaque_functab (0 /* all LSAs */,
183 0 /* all opaque types */);
184
gdt3fb9de72004-12-09 16:30:04 +0000185 /*
186 * Free all client instances. ospf_apiserver_free removes the node
187 * from the list, so we examine the head of the list anew each time.
188 */
paule029d442005-10-23 15:26:24 +0000189 while ( apiserver_list &&
190 (apiserv = listgetdata (listhead (apiserver_list))) != NULL)
paul87d6f872004-09-24 08:01:38 +0000191 ospf_apiserver_free (apiserv);
paul2d33f152003-03-17 01:10:58 +0000192
193 /* Free client list itself */
paule029d442005-10-23 15:26:24 +0000194 if (apiserver_list)
195 list_delete (apiserver_list);
paul2d33f152003-03-17 01:10:58 +0000196
197 /* Free wildcard list */
198 /* XXX */
199}
200
201static struct ospf_apiserver *
202lookup_apiserver (u_char lsa_type, u_char opaque_type)
203{
paul87d6f872004-09-24 08:01:38 +0000204 struct listnode *n1, *n2;
paul2d33f152003-03-17 01:10:58 +0000205 struct registered_opaque_type *r;
206 struct ospf_apiserver *apiserv, *found = NULL;
207
paul87d6f872004-09-24 08:01:38 +0000208 /* XXX: this approaches O(n**2) */
paul1eb8ef22005-04-07 07:30:20 +0000209 for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv))
paul2d33f152003-03-17 01:10:58 +0000210 {
paul1eb8ef22005-04-07 07:30:20 +0000211 for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r))
212 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
213 {
214 found = apiserv;
215 goto out;
216 }
paul2d33f152003-03-17 01:10:58 +0000217 }
218out:
219 return found;
220}
221
222static struct ospf_apiserver *
223lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
224{
225 struct lsa_header *lsah = lsa->data;
226 struct ospf_apiserver *found = NULL;
227
228 if (IS_OPAQUE_LSA (lsah->type))
229 {
230 found = lookup_apiserver (lsah->type,
231 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
232 }
233 return found;
234}
235
236/* -----------------------------------------------------------
237 * Followings are functions to manage client connections.
238 * -----------------------------------------------------------
239 */
240static int
241ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
242{
243 if (IS_DEBUG_OSPF_EVENT)
David Lampartereed3c482015-03-03 08:51:53 +0100244 zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", (void *)lsa,
245 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)
David Lampartereed3c482015-03-03 08:51:53 +0100253 zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", (void *)lsa,
254 dump_lsa_key (lsa), lsa->lsdb->total);
paul2d33f152003-03-17 01:10:58 +0000255 return 0;
256}
257
258/* Allocate new connection structure. */
259struct ospf_apiserver *
260ospf_apiserver_new (int fd_sync, int fd_async)
261{
262 struct ospf_apiserver *new =
263 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
264
265 new->filter =
266 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
267
268 new->fd_sync = fd_sync;
269 new->fd_async = fd_async;
270
271 /* list of registered opaque types that application uses */
272 new->opaque_types = list_new ();
273
274 /* Initialize temporary strage for LSA instances to be refreshed. */
275 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
276 ospf_lsdb_init (&new->reserve);
277
278 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
279 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
280
281 new->out_sync_fifo = msg_fifo_new ();
282 new->out_async_fifo = msg_fifo_new ();
283 new->t_sync_read = NULL;
284#ifdef USE_ASYNC_READ
285 new->t_async_read = NULL;
286#endif /* USE_ASYNC_READ */
287 new->t_sync_write = NULL;
288 new->t_async_write = NULL;
289
290 new->filter->typemask = 0; /* filter all LSAs */
291 new->filter->origin = ANY_ORIGIN;
292 new->filter->num_areas = 0;
293
294 return new;
295}
296
297void
298ospf_apiserver_event (enum event event, int fd,
299 struct ospf_apiserver *apiserv)
300{
paul2d33f152003-03-17 01:10:58 +0000301 switch (event)
302 {
303 case OSPF_APISERVER_ACCEPT:
Andrew Certain0798cee2012-12-04 13:43:42 -0800304 (void)thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
paul2d33f152003-03-17 01:10:58 +0000305 break;
306 case OSPF_APISERVER_SYNC_READ:
307 apiserv->t_sync_read =
308 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
309 break;
310#ifdef USE_ASYNC_READ
311 case OSPF_APISERVER_ASYNC_READ:
312 apiserv->t_async_read =
313 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
314 break;
315#endif /* USE_ASYNC_READ */
316 case OSPF_APISERVER_SYNC_WRITE:
317 if (!apiserv->t_sync_write)
318 {
319 apiserv->t_sync_write =
320 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
321 }
322 break;
323 case OSPF_APISERVER_ASYNC_WRITE:
324 if (!apiserv->t_async_write)
325 {
326 apiserv->t_async_write =
327 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
328 }
329 break;
330 }
331}
332
333/* Free instance. First unregister all opaque types used by
334 application, flush opaque LSAs injected by application
335 from network and close connection. */
336void
337ospf_apiserver_free (struct ospf_apiserver *apiserv)
338{
paul87d6f872004-09-24 08:01:38 +0000339 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000340
341 /* Cancel read and write threads. */
342 if (apiserv->t_sync_read)
343 {
344 thread_cancel (apiserv->t_sync_read);
345 }
346#ifdef USE_ASYNC_READ
347 if (apiserv->t_async_read)
348 {
349 thread_cancel (apiserv->t_async_read);
350 }
351#endif /* USE_ASYNC_READ */
352 if (apiserv->t_sync_write)
353 {
354 thread_cancel (apiserv->t_sync_write);
355 }
356
357 if (apiserv->t_async_write)
358 {
359 thread_cancel (apiserv->t_async_write);
360 }
361
362 /* Unregister all opaque types that application registered
363 and flush opaque LSAs if still in LSDB. */
364
365 while ((node = listhead (apiserv->opaque_types)) != NULL)
366 {
paul1eb8ef22005-04-07 07:30:20 +0000367 struct registered_opaque_type *regtype = listgetdata(node);
paul2d33f152003-03-17 01:10:58 +0000368
369 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
370 regtype->opaque_type);
371
372 }
373
374 /* Close connections to OSPFd. */
375 if (apiserv->fd_sync > 0)
376 {
377 close (apiserv->fd_sync);
378 }
379
380 if (apiserv->fd_async > 0)
381 {
382 close (apiserv->fd_async);
383 }
384
385 /* Free fifos */
386 msg_fifo_free (apiserv->out_sync_fifo);
387 msg_fifo_free (apiserv->out_async_fifo);
388
389 /* Clear temporary strage for LSA instances to be refreshed. */
390 ospf_lsdb_delete_all (&apiserv->reserve);
391 ospf_lsdb_cleanup (&apiserv->reserve);
392
393 /* Remove from the list of active clients. */
394 listnode_delete (apiserver_list, apiserv);
395
396 if (IS_DEBUG_OSPF_EVENT)
David Lampartereed3c482015-03-03 08:51:53 +0100397 zlog_debug ("API: Delete apiserv(%p), total#(%d)",
398 (void *)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)
David Lampartereed3c482015-03-03 08:51:53 +0100758 zlog_debug ("API: New apiserv(%p), total#(%d)",
759 (void *)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 =
Stephen Hemminger393deb92008-08-18 14:13:29 -0700938 XCALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
paul2d33f152003-03-17 01:10:58 +0000939 regtype->lsa_type = lsa_type;
940 regtype->opaque_type = opaque_type;
941
942 /* Add to list of registered opaque types */
943 listnode_add (apiserv->opaque_types, regtype);
944
945 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000946 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
paul87d6f872004-09-24 08:01:38 +0000947 " apiserv(%p), total#(%d)",
David Lampartereed3c482015-03-03 08:51:53 +0100948 lsa_type, opaque_type, (void *)apiserv,
paul87d6f872004-09-24 08:01:38 +0000949 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000950
951 return 0;
952}
953
954int
955ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
956 u_char lsa_type, u_char opaque_type)
957{
paul1eb8ef22005-04-07 07:30:20 +0000958 struct listnode *node, *nnode;
gdt54ade992004-10-07 19:38:20 +0000959 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000960
paul1eb8ef22005-04-07 07:30:20 +0000961 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +0000962 {
paul2d33f152003-03-17 01:10:58 +0000963 /* Check if we really registered this opaque type */
964 if (regtype->lsa_type == lsa_type &&
965 regtype->opaque_type == opaque_type)
966 {
967
968 /* Yes, we registered this opaque type. Flush
969 all existing opaque LSAs of this type */
970
971 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
972 ospf_delete_opaque_functab (lsa_type, opaque_type);
973
974 /* Remove from list of registered opaque types */
975 listnode_delete (apiserv->opaque_types, regtype);
976
977 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000978 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
paul87d6f872004-09-24 08:01:38 +0000979 " from apiserv(%p), total#(%d)",
David Lampartereed3c482015-03-03 08:51:53 +0100980 lsa_type, opaque_type, (void *)apiserv,
paul87d6f872004-09-24 08:01:38 +0000981 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000982
983 return 0;
984 }
985 }
986
987 /* Opaque type is not registered */
988 zlog_warn ("Failed to unregister opaque type [%d/%d]",
989 lsa_type, opaque_type);
990 return OSPF_API_OPAQUETYPENOTREGISTERED;
991}
992
993
paul4dadc292005-05-06 21:37:42 +0000994static int
paul2d33f152003-03-17 01:10:58 +0000995apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
996 u_char lsa_type, u_char opaque_type)
997{
paul1eb8ef22005-04-07 07:30:20 +0000998 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +0000999 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001000
paul87d6f872004-09-24 08:01:38 +00001001 /* XXX: how many types are there? if few, why not just a bitmap? */
paul1eb8ef22005-04-07 07:30:20 +00001002 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +00001003 {
paul2d33f152003-03-17 01:10:58 +00001004 /* Check if we really registered this opaque type */
1005 if (regtype->lsa_type == lsa_type &&
1006 regtype->opaque_type == opaque_type)
1007 {
1008 /* Yes registered */
1009 return 1;
1010 }
1011 }
1012 /* Not registered */
1013 return 0;
1014}
1015
1016int
1017ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1018 struct msg *msg)
1019{
1020 struct msg_register_opaque_type *rmsg;
1021 u_char lsa_type;
1022 u_char opaque_type;
1023 int rc = 0;
1024
1025 /* Extract parameters from register opaque type message */
1026 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1027
1028 lsa_type = rmsg->lsatype;
1029 opaque_type = rmsg->opaquetype;
1030
1031 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1032
1033 /* Send a reply back to client including return code */
1034 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1035 if (rc < 0)
1036 goto out;
1037
1038 /* Now inform application about opaque types that are ready */
1039 switch (lsa_type)
1040 {
1041 case OSPF_OPAQUE_LINK_LSA:
1042 ospf_apiserver_notify_ready_type9 (apiserv);
1043 break;
1044 case OSPF_OPAQUE_AREA_LSA:
1045 ospf_apiserver_notify_ready_type10 (apiserv);
1046 break;
1047 case OSPF_OPAQUE_AS_LSA:
1048 ospf_apiserver_notify_ready_type11 (apiserv);
1049 break;
1050 }
1051out:
1052 return rc;
1053}
1054
1055
1056/* Notify specific client about all opaque types 9 that are ready. */
1057void
1058ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1059{
paul1eb8ef22005-04-07 07:30:20 +00001060 struct listnode *node, *nnode;
1061 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001062 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001063 struct ospf_interface *oi;
1064 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001065
paul99b7c5d2003-04-06 01:19:28 +00001066 ospf = ospf_lookup ();
1067
paul1eb8ef22005-04-07 07:30:20 +00001068 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul2d33f152003-03-17 01:10:58 +00001069 {
paul2d33f152003-03-17 01:10:58 +00001070 /* Check if this interface is indeed ready for type 9 */
1071 if (!ospf_apiserver_is_ready_type9 (oi))
1072 continue;
1073
1074 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001075 /* XXX: loop-de-loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001076 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001077 {
paul2d33f152003-03-17 01:10:58 +00001078 struct msg *msg;
1079
1080 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1081 {
1082
1083 /* Yes, this opaque type is ready */
1084 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1085 r->opaque_type,
1086 oi->address->u.prefix4);
1087 if (!msg)
1088 {
1089 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1090#ifdef NOTYET
1091 /* Cannot allocate new message. What should we do? */
1092 ospf_apiserver_free (apiserv);
1093#endif
1094 goto out;
1095 }
1096 ospf_apiserver_send_msg (apiserv, msg);
1097 msg_free (msg);
1098 }
1099 }
1100 }
1101
1102out:
1103 return;
1104}
1105
1106
1107/* Notify specific client about all opaque types 10 that are ready. */
1108void
1109ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1110{
paul1eb8ef22005-04-07 07:30:20 +00001111 struct listnode *node, *nnode;
1112 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001113 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001114 struct ospf_area *area;
1115
paul99b7c5d2003-04-06 01:19:28 +00001116 ospf = ospf_lookup ();
1117
paul1eb8ef22005-04-07 07:30:20 +00001118 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001119 {
paul87d6f872004-09-24 08:01:38 +00001120 struct registered_opaque_type *r;
1121
paul2d33f152003-03-17 01:10:58 +00001122 if (!ospf_apiserver_is_ready_type10 (area))
1123 {
1124 continue;
1125 }
1126
1127 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001128 /* XXX: loop in loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001129 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001130 {
paul2d33f152003-03-17 01:10:58 +00001131 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001132
paul2d33f152003-03-17 01:10:58 +00001133 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1134 {
1135 /* Yes, this opaque type is ready */
1136 msg =
1137 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1138 r->opaque_type, area->area_id);
1139 if (!msg)
1140 {
1141 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1142#ifdef NOTYET
1143 /* Cannot allocate new message. What should we do? */
1144 ospf_apiserver_free (apiserv);
1145#endif
1146 goto out;
1147 }
1148 ospf_apiserver_send_msg (apiserv, msg);
1149 msg_free (msg);
1150 }
1151 }
1152 }
1153
1154out:
1155 return;
1156}
1157
1158/* Notify specific client about all opaque types 11 that are ready */
1159void
1160ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1161{
paul1eb8ef22005-04-07 07:30:20 +00001162 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00001163 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001164 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001165
1166 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001167
1168 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001169 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001170 goto out;
paul2d33f152003-03-17 01:10:58 +00001171
1172 /* Check for registered opaque type 11 types */
paul1eb8ef22005-04-07 07:30:20 +00001173 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
paul2d33f152003-03-17 01:10:58 +00001174 {
paul2d33f152003-03-17 01:10:58 +00001175 struct msg *msg;
paul36238142005-10-11 04:12:54 +00001176 struct in_addr noarea_id = { .s_addr = 0L };
1177
paul2d33f152003-03-17 01:10:58 +00001178 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1179 {
1180 /* Yes, this opaque type is ready */
1181 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1182 r->opaque_type, noarea_id);
1183
1184 if (!msg)
1185 {
1186 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1187#ifdef NOTYET
1188 /* Cannot allocate new message. What should we do? */
1189 ospf_apiserver_free (apiserv);
1190#endif
1191 goto out;
1192 }
1193 ospf_apiserver_send_msg (apiserv, msg);
1194 msg_free (msg);
1195 }
1196 }
1197
1198out:
1199 return;
1200}
1201
1202int
1203ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1204 struct msg *msg)
1205{
1206 struct msg_unregister_opaque_type *umsg;
1207 u_char ltype;
1208 u_char otype;
1209 int rc = 0;
1210
1211 /* Extract parameters from unregister opaque type message */
1212 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1213
1214 ltype = umsg->lsatype;
1215 otype = umsg->opaquetype;
1216
1217 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1218
1219 /* Send a reply back to client including return code */
1220 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1221
1222 return rc;
1223}
1224
1225
1226/* -----------------------------------------------------------
1227 * Following are functions for event (filter) registration.
1228 * -----------------------------------------------------------
1229 */
1230int
1231ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1232 struct msg *msg)
1233{
1234 struct msg_register_event *rmsg;
1235 int rc;
1236 u_int32_t seqnum;
1237
1238 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1239
1240 /* Get request sequence number */
1241 seqnum = msg_get_seq (msg);
1242
1243 /* Free existing filter in apiserv. */
1244 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1245 /* Alloc new space for filter. */
1246
1247 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1248 ntohs (msg->hdr.msglen));
1249 if (apiserv->filter)
1250 {
1251 /* copy it over. */
1252 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1253 rc = OSPF_API_OK;
1254 }
1255 else
1256 {
1257 rc = OSPF_API_NOMEMORY;
1258 }
1259 /* Send a reply back to client with return code */
1260 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1261 return rc;
1262}
1263
1264
1265/* -----------------------------------------------------------
1266 * Followings are functions for LSDB synchronization.
1267 * -----------------------------------------------------------
1268 */
1269
paul4dadc292005-05-06 21:37:42 +00001270static int
paul2d33f152003-03-17 01:10:58 +00001271apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1272{
1273 struct ospf_apiserver *apiserv;
1274 int seqnum;
1275 struct msg *msg;
1276 struct param_t
1277 {
1278 struct ospf_apiserver *apiserv;
1279 struct lsa_filter_type *filter;
1280 }
1281 *param;
1282 int rc = -1;
1283
1284 /* Sanity check */
1285 assert (lsa->data);
1286 assert (p_arg);
1287
1288 param = (struct param_t *) p_arg;
1289 apiserv = param->apiserv;
1290 seqnum = (u_int32_t) int_arg;
1291
1292 /* Check origin in filter. */
1293 if ((param->filter->origin == ANY_ORIGIN) ||
1294 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1295 {
1296
1297 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00001298 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00001299
1300 /* Default interface for non Opaque9 LSAs */
paul484315f2005-11-03 09:08:29 +00001301 struct in_addr ifaddr = { .s_addr = 0L };
paul36238142005-10-11 04:12:54 +00001302
paul2d33f152003-03-17 01:10:58 +00001303 if (lsa->area)
1304 {
1305 area_id = lsa->area->area_id;
1306 }
1307 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1308 {
1309 ifaddr = lsa->oi->address->u.prefix4;
1310 }
1311
1312 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1313 seqnum,
1314 ifaddr, area_id,
1315 lsa->flags & OSPF_LSA_SELF, lsa->data);
1316 if (!msg)
1317 {
1318 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1319#ifdef NOTYET
1320 /* Cannot allocate new message. What should we do? */
1321/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1322#endif
1323 goto out;
1324 }
1325
1326 /* Send LSA */
1327 ospf_apiserver_send_msg (apiserv, msg);
1328 msg_free (msg);
1329 }
1330 rc = 0;
1331
1332out:
1333 return rc;
1334}
1335
1336int
1337ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1338 struct msg *msg)
1339{
paul1eb8ef22005-04-07 07:30:20 +00001340 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00001341 u_int32_t seqnum;
1342 int rc = 0;
1343 struct msg_sync_lsdb *smsg;
paul1eb8ef22005-04-07 07:30:20 +00001344 struct ospf_apiserver_param_t
paul2d33f152003-03-17 01:10:58 +00001345 {
1346 struct ospf_apiserver *apiserv;
1347 struct lsa_filter_type *filter;
paul1eb8ef22005-04-07 07:30:20 +00001348 } param;
paul2d33f152003-03-17 01:10:58 +00001349 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001350 struct route_node *rn;
1351 struct ospf_lsa *lsa;
1352 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001353 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001354
1355 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001356
1357 /* Get request sequence number */
1358 seqnum = msg_get_seq (msg);
1359 /* Set sync msg. */
1360 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1361
1362 /* Set parameter struct. */
1363 param.apiserv = apiserv;
1364 param.filter = &smsg->filter;
1365
1366 /* Remember mask. */
1367 mask = ntohs (smsg->filter.typemask);
1368
1369 /* Iterate over all areas. */
paul1eb8ef22005-04-07 07:30:20 +00001370 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001371 {
paul2d33f152003-03-17 01:10:58 +00001372 int i;
1373 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001374
paul2d33f152003-03-17 01:10:58 +00001375 /* Compare area_id with area_ids in sync request. */
1376 if ((i = smsg->filter.num_areas) > 0)
1377 {
1378 /* Let area_id point to the list of area IDs,
1379 * which is at the end of smsg->filter. */
1380 area_id = (u_int32_t *) (&smsg->filter + 1);
1381 while (i)
1382 {
1383 if (*area_id == area->area_id.s_addr)
1384 {
1385 break;
1386 }
1387 i--;
1388 area_id++;
1389 }
1390 }
1391 else
1392 {
1393 i = 1;
1394 }
1395
1396 /* If area was found, then i>0 here. */
1397 if (i)
1398 {
1399 /* Check msg type. */
1400 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001401 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1402 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001403 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001404 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1405 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001406 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001407 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1408 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001409 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001410 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1411 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001412 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001413 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1414 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001415 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001416 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1417 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001418 }
1419 }
1420
1421 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001422 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001423 {
1424 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001425 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1426 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001427 }
1428
1429 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001430 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001431 {
1432 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001433 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1434 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001435 }
1436
1437 /* Send a reply back to client with return code */
1438 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1439 return rc;
1440}
1441
1442
1443/* -----------------------------------------------------------
1444 * Followings are functions to originate or update LSA
1445 * from an application.
1446 * -----------------------------------------------------------
1447 */
1448
1449/* Create a new internal opaque LSA by taking prototype and filling in
1450 missing fields such as age, sequence number, advertising router,
1451 checksum and so on. The interface parameter is used for type 9
1452 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1453 nor interface. */
1454
1455struct ospf_lsa *
1456ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1457 struct ospf_interface *oi,
1458 struct lsa_header *protolsa)
1459{
1460 struct stream *s;
1461 struct lsa_header *newlsa;
1462 struct ospf_lsa *new = NULL;
1463 u_char options = 0x0;
1464 u_int16_t length;
1465
paul99b7c5d2003-04-06 01:19:28 +00001466 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001467
paul99b7c5d2003-04-06 01:19:28 +00001468 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001469 assert(ospf);
1470
paul2d33f152003-03-17 01:10:58 +00001471 /* Create a stream for internal opaque LSA */
1472 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1473 {
1474 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1475 return NULL;
1476 }
1477
1478 newlsa = (struct lsa_header *) STREAM_DATA (s);
1479
1480 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1481 have to set options? */
1482
1483 if (area)
1484 {
1485 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001486 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001487 }
1488
1489 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1490
1491 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1492 {
ajse84cc642004-12-08 17:28:56 +00001493 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
paul2d33f152003-03-17 01:10:58 +00001494 protolsa->type, inet_ntoa (protolsa->id));
1495 }
1496
1497 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001498 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001499 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001500
1501 /* Set opaque-LSA body fields. */
1502 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1503 ntohs (protolsa->length) - sizeof (struct lsa_header));
1504
1505 /* Determine length of LSA. */
1506 length = stream_get_endp (s);
1507 newlsa->length = htons (length);
1508
1509 /* Create OSPF LSA. */
1510 if ((new = ospf_lsa_new ()) == NULL)
1511 {
1512 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1513 stream_free (s);
1514 return NULL;
1515 }
1516
1517 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1518 {
1519 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001520 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001521 stream_free (s);
1522 return NULL;
1523 }
1524
1525 new->area = area;
1526 new->oi = oi;
1527
1528 SET_FLAG (new->flags, OSPF_LSA_SELF);
1529 memcpy (new->data, newlsa, length);
1530 stream_free (s);
1531
1532 return new;
1533}
1534
1535
1536int
1537ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1538{
1539 /* Type 9 opaque LSA can be originated if there is at least one
1540 active opaque-capable neighbor attached to the outgoing
1541 interface. */
1542
paula15f45d2003-03-28 01:50:03 +00001543 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001544}
1545
1546int
1547ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1548{
1549 /* Type 10 opaque LSA can be originated if there is at least one
1550 interface belonging to the area that has an active opaque-capable
1551 neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001552 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001553 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001554
paul1eb8ef22005-04-07 07:30:20 +00001555 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001556 /* Is there an active neighbor attached to this interface? */
1557 if (ospf_apiserver_is_ready_type9 (oi))
1558 return 1;
paul2d33f152003-03-17 01:10:58 +00001559
paul2d33f152003-03-17 01:10:58 +00001560 /* No active neighbor in area */
1561 return 0;
1562}
1563
1564int
1565ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1566{
1567 /* Type 11 opaque LSA can be originated if there is at least one interface
1568 that has an active opaque-capable neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001569 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001570 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001571
paul1eb8ef22005-04-07 07:30:20 +00001572 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001573 /* Is there an active neighbor attached to this interface? */
1574 if (ospf_apiserver_is_ready_type9 (oi))
1575 return 1;
paul2d33f152003-03-17 01:10:58 +00001576
paul2d33f152003-03-17 01:10:58 +00001577 /* No active neighbor at all */
1578 return 0;
1579}
1580
1581
1582int
1583ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1584 struct msg *msg)
1585{
1586 struct msg_originate_request *omsg;
1587 struct lsa_header *data;
1588 struct ospf_lsa *new;
1589 struct ospf_lsa *old;
1590 struct ospf_area *area = NULL;
1591 struct ospf_interface *oi = NULL;
1592 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001593 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001594 int lsa_type, opaque_type;
1595 int ready = 0;
1596 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001597
paul99b7c5d2003-04-06 01:19:28 +00001598 ospf = ospf_lookup();
1599
paul2d33f152003-03-17 01:10:58 +00001600 /* Extract opaque LSA data from message */
1601 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1602 data = &omsg->data;
1603
1604 /* Determine interface for type9 or area for type10 LSAs. */
1605 switch (data->type)
1606 {
1607 case OSPF_OPAQUE_LINK_LSA:
1608 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1609 if (!oi)
1610 {
1611 zlog_warn ("apiserver_originate: unknown interface %s",
1612 inet_ntoa (omsg->ifaddr));
1613 rc = OSPF_API_NOSUCHINTERFACE;
1614 goto out;
1615 }
1616 area = oi->area;
1617 lsdb = area->lsdb;
1618 break;
1619 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001620 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001621 if (!area)
1622 {
1623 zlog_warn ("apiserver_originate: unknown area %s",
1624 inet_ntoa (omsg->area_id));
1625 rc = OSPF_API_NOSUCHAREA;
1626 goto out;
1627 }
1628 lsdb = area->lsdb;
1629 break;
1630 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001631 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001632 break;
1633 default:
1634 /* We can only handle opaque types here */
1635 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1636 data->type);
1637 rc = OSPF_API_ILLEGALLSATYPE;
1638 goto out;
1639 }
1640
1641 /* Check if we registered this opaque type */
1642 lsa_type = data->type;
1643 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1644
1645 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1646 {
1647 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1648 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1649 goto out;
1650 }
1651
1652 /* Make sure that the neighbors are ready before we can originate */
1653 switch (data->type)
1654 {
1655 case OSPF_OPAQUE_LINK_LSA:
1656 ready = ospf_apiserver_is_ready_type9 (oi);
1657 break;
1658 case OSPF_OPAQUE_AREA_LSA:
1659 ready = ospf_apiserver_is_ready_type10 (area);
1660 break;
1661 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001662 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001663 break;
1664 default:
1665 break;
1666 }
1667
1668 if (!ready)
1669 {
1670 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1671 rc = OSPF_API_NOTREADY;
1672 goto out;
1673 }
1674
1675 /* Create OSPF's internal opaque LSA representation */
1676 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1677 if (!new)
1678 {
1679 rc = OSPF_API_NOMEMORY; /* XXX */
1680 goto out;
1681 }
1682
1683 /* Determine if LSA is new or an update for an existing one. */
1684 old = ospf_lsdb_lookup (lsdb, new);
1685
1686 if (!old)
1687 {
1688 /* New LSA install in LSDB. */
1689 rc = ospf_apiserver_originate1 (new);
1690 }
1691 else
1692 {
1693 /*
1694 * Keep the new LSA instance in the "waiting place" until the next
1695 * refresh timing. If several LSA update requests for the same LSID
1696 * have issued by peer, the last one takes effect.
1697 */
1698 new->lsdb = &apiserv->reserve;
1699 ospf_lsdb_add (&apiserv->reserve, new);
1700
1701 /* Kick the scheduler function. */
1702 ospf_opaque_lsa_refresh_schedule (old);
1703 }
1704
1705out:
1706
1707 /* Send a reply back to client with return code */
1708 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1709 return rc;
1710}
1711
1712
1713/* -----------------------------------------------------------
1714 * Flood an LSA within its flooding scope.
1715 * -----------------------------------------------------------
1716 */
1717
1718/* XXX We can probably use ospf_flood_through instead of this function
1719 but then we need the neighbor parameter. If we set nbr to
1720 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1721
1722void
1723ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1724{
1725 assert (lsa);
1726
1727 switch (lsa->data->type)
1728 {
1729 case OSPF_OPAQUE_LINK_LSA:
1730 /* Increment counters? XXX */
1731
1732 /* Flood LSA through local network. */
1733 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1734 break;
1735 case OSPF_OPAQUE_AREA_LSA:
1736 /* Update LSA origination count. */
1737 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001738 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001739
1740 /* Flood LSA through area. */
1741 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1742 break;
1743 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001744 {
paul99b7c5d2003-04-06 01:19:28 +00001745 struct ospf *ospf;
1746
1747 ospf = ospf_lookup();
1748 assert(ospf);
1749
paul7d5e2682003-04-05 19:41:07 +00001750 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001751
paul7d5e2682003-04-05 19:41:07 +00001752 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001753 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001754 break;
1755 }
paul2d33f152003-03-17 01:10:58 +00001756 }
1757}
1758
1759int
1760ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1761{
paul99b7c5d2003-04-06 01:19:28 +00001762 struct ospf *ospf;
1763
1764 ospf = ospf_lookup();
1765 assert(ospf);
1766
paul2d33f152003-03-17 01:10:58 +00001767 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001768 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001769 {
1770 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1771 return -1;
1772 }
1773
1774 /* Flood LSA within scope */
1775
1776#ifdef NOTYET
1777 /*
1778 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1779 * parameter, and thus it does not cause SIGSEGV error.
1780 */
1781 ospf_flood_through (NULL /*nbr */ , lsa);
1782#else /* NOTYET */
1783
1784 ospf_apiserver_flood_opaque_lsa (lsa);
1785#endif /* NOTYET */
1786
1787 return 0;
1788}
1789
1790
1791/* Opaque LSAs of type 9 on a specific interface can now be
1792 originated. Tell clients that registered type 9. */
1793int
1794ospf_apiserver_lsa9_originator (void *arg)
1795{
1796 struct ospf_interface *oi;
1797
1798 oi = (struct ospf_interface *) arg;
1799 if (listcount (apiserver_list) > 0) {
1800 ospf_apiserver_clients_notify_ready_type9 (oi);
1801 }
1802 return 0;
1803}
1804
1805int
1806ospf_apiserver_lsa10_originator (void *arg)
1807{
1808 struct ospf_area *area;
1809
1810 area = (struct ospf_area *) arg;
1811 if (listcount (apiserver_list) > 0) {
1812 ospf_apiserver_clients_notify_ready_type10 (area);
1813 }
1814 return 0;
1815}
1816
1817int
1818ospf_apiserver_lsa11_originator (void *arg)
1819{
1820 struct ospf *ospf;
1821
1822 ospf = (struct ospf *) arg;
1823 if (listcount (apiserver_list) > 0) {
1824 ospf_apiserver_clients_notify_ready_type11 (ospf);
1825 }
1826 return 0;
1827}
1828
1829
1830/* Periodically refresh opaque LSAs so that they do not expire in
1831 other routers. */
Paul Jakma072990e2011-04-11 16:28:16 +01001832struct ospf_lsa *
paul2d33f152003-03-17 01:10:58 +00001833ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1834{
1835 struct ospf_apiserver *apiserv;
1836 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001837 struct ospf * ospf;
1838
1839 ospf = ospf_lookup();
1840 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001841
1842 apiserv = lookup_apiserver_by_lsa (lsa);
1843 if (!apiserv)
1844 {
1845 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1846 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1847 }
1848
1849 if (IS_LSA_MAXAGE (lsa))
1850 {
1851 ospf_opaque_lsa_flush_schedule (lsa);
1852 goto out;
1853 }
1854
1855 /* Check if updated version of LSA instance has already prepared. */
1856 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1857 if (!new)
1858 {
1859 /* This is a periodic refresh, driven by core OSPF mechanism. */
1860 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1861 if (!new)
1862 {
1863 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1864 goto out;
1865 }
1866 }
1867 else
1868 {
1869 /* This is a forcible refresh, requested by OSPF-API client. */
1870 ospf_lsdb_delete (&apiserv->reserve, new);
1871 new->lsdb = NULL;
1872 }
1873
1874 /* Increment sequence number */
1875 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1876
1877 /* New LSA is in same area. */
1878 new->area = lsa->area;
1879 SET_FLAG (new->flags, OSPF_LSA_SELF);
1880
1881 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001882 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001883 {
1884 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001885 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001886 goto out;
1887 }
1888
1889 /* Flood updated LSA through interface, area or AS */
1890
1891#ifdef NOTYET
1892 ospf_flood_through (NULL /*nbr */ , new);
1893#endif /* NOTYET */
1894 ospf_apiserver_flood_opaque_lsa (new);
1895
1896 /* Debug logging. */
1897 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1898 {
ajse84cc642004-12-08 17:28:56 +00001899 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
paul2d33f152003-03-17 01:10:58 +00001900 new->data->type, inet_ntoa (new->data->id));
1901 ospf_lsa_header_dump (new->data);
1902 }
1903
1904out:
Paul Jakma072990e2011-04-11 16:28:16 +01001905 return new;
paul2d33f152003-03-17 01:10:58 +00001906}
1907
1908
1909/* -----------------------------------------------------------
1910 * Followings are functions to delete LSAs
1911 * -----------------------------------------------------------
1912 */
1913
1914int
1915ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1916 struct msg *msg)
1917{
1918 struct msg_delete_request *dmsg;
1919 struct ospf_lsa *old;
1920 struct ospf_area *area = NULL;
1921 struct in_addr id;
1922 int lsa_type, opaque_type;
1923 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001924 struct ospf * ospf;
1925
1926 ospf = ospf_lookup();
1927 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001928
1929 /* Extract opaque LSA from message */
1930 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1931
1932 /* Lookup area for link-local and area-local opaque LSAs */
1933 switch (dmsg->lsa_type)
1934 {
1935 case OSPF_OPAQUE_LINK_LSA:
1936 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001937 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001938 if (!area)
1939 {
1940 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1941 inet_ntoa (dmsg->area_id));
1942 rc = OSPF_API_NOSUCHAREA;
1943 goto out;
1944 }
1945 break;
1946 case OSPF_OPAQUE_AS_LSA:
1947 /* AS-external opaque LSAs have no designated area */
1948 area = NULL;
1949 break;
1950 default:
1951 zlog_warn
1952 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1953 dmsg->lsa_type);
1954 rc = OSPF_API_ILLEGALLSATYPE;
1955 goto out;
1956 }
1957
1958 /* Check if we registered this opaque type */
1959 lsa_type = dmsg->lsa_type;
1960 opaque_type = dmsg->opaque_type;
1961
1962 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1963 {
1964 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1965 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1966 goto out;
1967 }
1968
1969 /* opaque_id is in network byte order */
1970 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1971 ntohl (dmsg->opaque_id)));
1972
1973 /*
1974 * Even if the target LSA has once scheduled to flush, it remains in
1975 * the LSDB until it is finally handled by the maxage remover thread.
1976 * Therefore, the lookup function below may return non-NULL result.
1977 */
paul99b7c5d2003-04-06 01:19:28 +00001978 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001979 if (!old)
1980 {
1981 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1982 dmsg->lsa_type, inet_ntoa (id));
1983 rc = OSPF_API_NOSUCHLSA;
1984 goto out;
1985 }
1986
1987 /* Schedule flushing of LSA from LSDB */
1988 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1989 ospf_opaque_lsa_flush_schedule (old);
1990
1991out:
1992
1993 /* Send reply back to client including return code */
1994 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1995 return rc;
1996}
1997
1998/* Flush self-originated opaque LSA */
paul4dadc292005-05-06 21:37:42 +00001999static int
paul2d33f152003-03-17 01:10:58 +00002000apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2001 void *p_arg, int int_arg)
2002{
2003 struct param_t
2004 {
2005 struct ospf_apiserver *apiserv;
2006 u_char lsa_type;
2007 u_char opaque_type;
2008 }
2009 *param;
2010
2011 /* Sanity check */
2012 assert (lsa->data);
2013 assert (p_arg);
2014 param = (struct param_t *) p_arg;
2015
2016 /* If LSA matches type and opaque type then delete it */
2017 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2018 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2019 {
2020 ospf_opaque_lsa_flush_schedule (lsa);
2021 }
2022 return 0;
2023}
2024
2025/* Delete self-originated opaque LSAs of a given opaque type. This
2026 function is called when an application unregisters a given opaque
2027 type or a connection to an application closes and all those opaque
2028 LSAs need to be flushed the LSDB. */
2029void
2030ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2031 u_char lsa_type, u_char opaque_type)
2032{
2033 struct param_t
2034 {
2035 struct ospf_apiserver *apiserv;
2036 u_char lsa_type;
2037 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002038 } param;
paul1eb8ef22005-04-07 07:30:20 +00002039 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00002040 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002041 struct ospf_area *area;
2042
paul99b7c5d2003-04-06 01:19:28 +00002043 ospf = ospf_lookup();
2044 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002045
2046 /* Set parameter struct. */
2047 param.apiserv = apiserv;
2048 param.lsa_type = lsa_type;
2049 param.opaque_type = opaque_type;
2050
paul2d33f152003-03-17 01:10:58 +00002051 switch (lsa_type)
2052 {
paul99b7c5d2003-04-06 01:19:28 +00002053 struct route_node *rn;
2054 struct ospf_lsa *lsa;
2055
paul2d33f152003-03-17 01:10:58 +00002056 case OSPF_OPAQUE_LINK_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002057 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002058 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2059 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002060 break;
2061 case OSPF_OPAQUE_AREA_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002062 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002063 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2064 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002065 break;
2066 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002067 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2068 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002069 break;
2070 default:
2071 break;
2072 }
2073 return;
paul2d33f152003-03-17 01:10:58 +00002074}
2075
2076
2077/* -----------------------------------------------------------
2078 * Followings are callback functions to handle opaque types
2079 * -----------------------------------------------------------
2080 */
2081
2082int
2083ospf_apiserver_new_if (struct interface *ifp)
2084{
2085 struct ospf_interface *oi;
2086
2087 /* For some strange reason it seems possible that we are invoked
2088 with an interface that has no name. This seems to happen during
2089 initialization. Return if this happens */
2090
2091 if (ifp->name[0] == '\0') {
2092 /* interface has empty name */
2093 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2094 return 0;
2095 }
2096
2097 /* zlog_warn for debugging */
2098 zlog_warn ("ospf_apiserver_new_if");
2099 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2100 ifp->ifindex);
2101
2102 if (ifp->name[0] == '\0') {
2103 /* interface has empty name */
2104 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2105 return 0;
2106 }
2107
2108 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2109
2110 if (!oi) {
2111 /* This interface is known to Zebra but not to OSPF daemon yet. */
2112 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2113 ifp->name);
2114 return 0;
2115 }
2116
2117 assert (oi);
2118
2119 /* New interface added to OSPF, tell clients about it */
2120 if (listcount (apiserver_list) > 0) {
2121 ospf_apiserver_clients_notify_new_if (oi);
2122 }
2123 return 0;
2124}
2125
2126int
2127ospf_apiserver_del_if (struct interface *ifp)
2128{
2129 struct ospf_interface *oi;
2130
2131 /* zlog_warn for debugging */
2132 zlog_warn ("ospf_apiserver_del_if");
2133 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2134 ifp->ifindex);
2135
2136 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002137
2138 if (!oi) {
2139 /* This interface is known to Zebra but not to OSPF daemon
2140 anymore. No need to tell clients about it */
2141 return 0;
2142 }
paul2d33f152003-03-17 01:10:58 +00002143
2144 /* Interface deleted, tell clients about it */
2145 if (listcount (apiserver_list) > 0) {
2146 ospf_apiserver_clients_notify_del_if (oi);
2147 }
2148 return 0;
2149}
2150
2151void
2152ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2153{
2154 /* Tell clients about interface change */
2155
2156 /* zlog_warn for debugging */
2157 zlog_warn ("ospf_apiserver_ism_change");
2158 if (listcount (apiserver_list) > 0) {
2159 ospf_apiserver_clients_notify_ism_change (oi);
2160 }
2161
2162 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2163 zlog_warn ("old_state=%d", old_state);
2164 zlog_warn ("oi->state=%d", oi->state);
2165}
2166
2167void
2168ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2169{
2170 /* Neighbor status changed, tell clients about it */
2171 zlog_warn ("ospf_apiserver_nsm_change");
2172 if (listcount (apiserver_list) > 0) {
2173 ospf_apiserver_clients_notify_nsm_change (nbr);
2174 }
2175}
2176
2177void
2178ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2179{
2180 struct opaque_lsa
2181 {
2182 struct lsa_header header;
2183 u_char data[1]; /* opaque data have variable length. This is start
2184 address */
2185 };
2186 struct opaque_lsa *olsa;
2187 int opaquelen;
2188
2189 olsa = (struct opaque_lsa *) lsa->data;
2190
2191 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002192 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002193 else
paul87d6f872004-09-24 08:01:38 +00002194 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002195
2196 /* Output information about opaque LSAs */
2197 if (vty != NULL)
2198 {
2199 int i;
2200 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2201 opaquelen,
2202 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2203 VTY_NEWLINE);
2204 vty_out (vty, " Opaque data: ");
2205
2206 for (i = 0; i < opaquelen; i++)
2207 {
2208 vty_out (vty, "0x%x ", olsa->data[i]);
2209 }
2210 vty_out (vty, "%s", VTY_NEWLINE);
2211 }
2212 else
2213 {
2214 int i;
ajse84cc642004-12-08 17:28:56 +00002215 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
paul2d33f152003-03-17 01:10:58 +00002216 opaquelen,
2217 VALID_OPAQUE_INFO_LEN (lsa->
2218 data) ? "" : "(Invalid length?)");
ajse84cc642004-12-08 17:28:56 +00002219 zlog_debug (" Opaque data: ");
paul2d33f152003-03-17 01:10:58 +00002220
2221 for (i = 0; i < opaquelen; i++)
2222 {
ajse84cc642004-12-08 17:28:56 +00002223 zlog_debug ("0x%x ", olsa->data[i]);
paul2d33f152003-03-17 01:10:58 +00002224 }
ajse84cc642004-12-08 17:28:56 +00002225 zlog_debug ("\n");
paul2d33f152003-03-17 01:10:58 +00002226 }
2227 return;
2228}
2229
2230/* -----------------------------------------------------------
2231 * Followings are functions to notify clients about events
2232 * -----------------------------------------------------------
2233 */
2234
2235/* Send a message to all clients. This is useful for messages
2236 that need to be notified to all clients (such as interface
2237 changes) */
2238
2239void
2240ospf_apiserver_clients_notify_all (struct msg *msg)
2241{
paul1eb8ef22005-04-07 07:30:20 +00002242 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002243 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002244
2245 /* Send message to all clients */
paul1eb8ef22005-04-07 07:30:20 +00002246 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul87d6f872004-09-24 08:01:38 +00002247 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002248}
2249
2250/* An interface is now ready to accept opaque LSAs. Notify all
2251 clients that registered to use this opaque type */
2252void
2253ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2254{
paul1eb8ef22005-04-07 07:30:20 +00002255 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002256 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002257 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002258
2259 assert (oi);
2260 if (!oi->address)
2261 {
2262 zlog_warn ("Interface has no address?");
2263 return;
2264 }
2265
2266 if (!ospf_apiserver_is_ready_type9 (oi))
2267 {
2268 zlog_warn ("Interface not ready for type 9?");
2269 return;
2270 }
2271
paul1eb8ef22005-04-07 07:30:20 +00002272 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002273 {
paul1eb8ef22005-04-07 07:30:20 +00002274 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002275 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002276
paul1eb8ef22005-04-07 07:30:20 +00002277 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002278 {
paul2d33f152003-03-17 01:10:58 +00002279 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2280 {
2281 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2282 r->opaque_type,
2283 oi->address->u.prefix4);
2284 if (!msg)
2285 {
2286 zlog_warn
2287 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2288#ifdef NOTYET
2289 /* Cannot allocate new message. What should we do? */
2290 ospf_apiserver_free (apiserv);
2291#endif
2292 goto out;
2293 }
2294
2295 ospf_apiserver_send_msg (apiserv, msg);
2296 msg_free (msg);
2297 }
2298 }
2299 }
2300
2301out:
2302 return;
2303}
2304
2305void
2306ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2307{
paul1eb8ef22005-04-07 07:30:20 +00002308 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002309 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002310 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002311
2312 assert (area);
2313
2314 if (!ospf_apiserver_is_ready_type10 (area))
2315 {
2316 zlog_warn ("Area not ready for type 10?");
2317 return;
2318 }
2319
paul1eb8ef22005-04-07 07:30:20 +00002320 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002321 {
paul1eb8ef22005-04-07 07:30:20 +00002322 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002323 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002324
paul1eb8ef22005-04-07 07:30:20 +00002325 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002326 {
paul2d33f152003-03-17 01:10:58 +00002327 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2328 {
2329 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2330 r->opaque_type, area->area_id);
2331 if (!msg)
2332 {
2333 zlog_warn
2334 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2335#ifdef NOTYET
2336 /* Cannot allocate new message. What should we do? */
2337 ospf_apiserver_free (apiserv);
2338#endif
paul87d6f872004-09-24 08:01:38 +00002339 goto out;
paul2d33f152003-03-17 01:10:58 +00002340 }
2341
2342 ospf_apiserver_send_msg (apiserv, msg);
2343 msg_free (msg);
2344 }
2345 }
2346 }
2347
2348out:
2349 return;
2350}
2351
2352
2353void
2354ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2355{
paul1eb8ef22005-04-07 07:30:20 +00002356 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002357 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002358 struct in_addr id_null = { .s_addr = 0L };
paul87d6f872004-09-24 08:01:38 +00002359 struct ospf_apiserver *apiserv;
paul36238142005-10-11 04:12:54 +00002360
paul2d33f152003-03-17 01:10:58 +00002361 assert (top);
paul36238142005-10-11 04:12:54 +00002362
paul2d33f152003-03-17 01:10:58 +00002363 if (!ospf_apiserver_is_ready_type11 (top))
2364 {
2365 zlog_warn ("AS not ready for type 11?");
2366 return;
2367 }
2368
paul1eb8ef22005-04-07 07:30:20 +00002369 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002370 {
paul1eb8ef22005-04-07 07:30:20 +00002371 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002372 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002373
paul1eb8ef22005-04-07 07:30:20 +00002374 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002375 {
paul2d33f152003-03-17 01:10:58 +00002376 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2377 {
2378 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2379 r->opaque_type, id_null);
2380 if (!msg)
2381 {
2382 zlog_warn
2383 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2384#ifdef NOTYET
2385 /* Cannot allocate new message. What should we do? */
2386 ospf_apiserver_free (apiserv);
2387#endif
2388 goto out;
2389 }
2390
2391 ospf_apiserver_send_msg (apiserv, msg);
2392 msg_free (msg);
2393 }
2394 }
2395 }
2396
2397out:
2398 return;
2399}
2400
2401void
2402ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2403{
2404 struct msg *msg;
2405
2406 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2407 if (msg != NULL)
2408 {
2409 ospf_apiserver_clients_notify_all (msg);
2410 msg_free (msg);
2411 }
2412}
2413
2414void
2415ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2416{
2417 struct msg *msg;
2418
2419 msg = new_msg_del_if (0, oi->address->u.prefix4);
2420 if (msg != NULL)
2421 {
2422 ospf_apiserver_clients_notify_all (msg);
2423 msg_free (msg);
2424 }
2425}
2426
2427void
2428ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2429{
2430 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002431 struct in_addr ifaddr = { .s_addr = 0L };
2432 struct in_addr area_id = { .s_addr = 0L };
2433
paul2d33f152003-03-17 01:10:58 +00002434 assert (oi);
2435 assert (oi->ifp);
paul36238142005-10-11 04:12:54 +00002436
paul2d33f152003-03-17 01:10:58 +00002437 if (oi->address)
2438 {
2439 ifaddr = oi->address->u.prefix4;
2440 }
2441 if (oi->area)
2442 {
2443 area_id = oi->area->area_id;
2444 }
2445
hasso1ddd7292005-06-07 19:54:04 +00002446 msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
paul2d33f152003-03-17 01:10:58 +00002447 if (!msg)
2448 {
2449 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2450 return;
2451 }
2452
2453 ospf_apiserver_clients_notify_all (msg);
2454 msg_free (msg);
2455}
2456
2457void
2458ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2459{
2460 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002461 struct in_addr ifaddr = { .s_addr = 0L };
2462 struct in_addr nbraddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002463
2464 assert (nbr);
2465
2466 if (nbr->oi)
2467 {
2468 ifaddr = nbr->oi->address->u.prefix4;
2469 }
2470
2471 nbraddr = nbr->address.u.prefix4;
2472
2473 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2474 if (!msg)
2475 {
2476 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2477 return;
2478 }
2479
2480 ospf_apiserver_clients_notify_all (msg);
2481 msg_free (msg);
2482}
2483
paul4dadc292005-05-06 21:37:42 +00002484static void
paul2d33f152003-03-17 01:10:58 +00002485apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2486{
2487 struct msg *msg;
paul1eb8ef22005-04-07 07:30:20 +00002488 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002489 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002490
2491 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002492 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002493
2494 /* Default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002495 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002496
2497 if (lsa->area)
2498 {
2499 area_id = lsa->area->area_id;
2500 }
2501 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2502 {
2503 assert (lsa->oi);
2504 ifaddr = lsa->oi->address->u.prefix4;
2505 }
2506
2507 /* Prepare message that can be sent to clients that have a matching
2508 filter */
2509 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2510 ifaddr, area_id,
2511 lsa->flags & OSPF_LSA_SELF, lsa->data);
2512 if (!msg)
2513 {
2514 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2515 return;
2516 }
2517
2518 /* Now send message to all clients with a matching filter */
paul1eb8ef22005-04-07 07:30:20 +00002519 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002520 {
paul2d33f152003-03-17 01:10:58 +00002521 struct lsa_filter_type *filter;
2522 u_int16_t mask;
2523 u_int32_t *area;
2524 int i;
2525
2526 /* Check filter for this client. */
2527 filter = apiserv->filter;
2528
2529 /* Check area IDs in case of non AS-E LSAs.
2530 * If filter has areas (num_areas > 0),
2531 * then one of the areas must match the area ID of this LSA. */
2532
2533 i = filter->num_areas;
2534 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2535 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2536 {
2537 i = 0;
2538 }
2539
2540 if (i > 0)
2541 {
2542 area = (u_int32_t *) (filter + 1);
2543 while (i)
2544 {
2545 if (*area == area_id.s_addr)
2546 {
2547 break;
2548 }
2549 i--;
2550 area++;
2551 }
2552 }
2553 else
2554 {
2555 i = 1;
2556 }
2557
2558 if (i > 0)
2559 {
2560 /* Area match. Check LSA type. */
2561 mask = ntohs (filter->typemask);
2562
2563 if (mask & Power2[lsa->data->type])
2564 {
2565 /* Type also matches. Check origin. */
2566 if ((filter->origin == ANY_ORIGIN) ||
2567 (filter->origin == IS_LSA_SELF (lsa)))
2568 {
2569 ospf_apiserver_send_msg (apiserv, msg);
2570 }
2571 }
2572 }
2573 }
2574 /* Free message since it is not used anymore */
2575 msg_free (msg);
2576}
2577
2578
2579/* -------------------------------------------------------------
2580 * Followings are hooks invoked when LSAs are updated or deleted
2581 * -------------------------------------------------------------
2582 */
2583
2584
paul4dadc292005-05-06 21:37:42 +00002585static int
paul2d33f152003-03-17 01:10:58 +00002586apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2587{
2588 struct msg *msg;
2589 /* default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002590 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002591
2592 /* default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002593 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002594
2595 /* Only notify this update if the LSA's age is smaller than
2596 MAXAGE. Otherwise clients would see LSA updates with max age just
2597 before they are deleted from the LSDB. LSA delete messages have
2598 MAXAGE too but should not be filtered. */
2599 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2600 return 0;
2601 }
2602
2603 if (lsa->area)
2604 {
2605 area_id = lsa->area->area_id;
2606 }
2607 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2608 {
2609 ifaddr = lsa->oi->address->u.prefix4;
2610 }
2611 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2612 ifaddr, area_id,
2613 lsa->flags & OSPF_LSA_SELF, lsa->data);
2614 if (!msg)
2615 {
2616 zlog_warn ("notify_clients_lsa: msg_new failed");
2617 return -1;
2618 }
2619 /* Notify all clients that new LSA is added/updated */
2620 apiserver_clients_lsa_change_notify (msgtype, lsa);
2621
2622 /* Clients made their own copies of msg so we can free msg here */
2623 msg_free (msg);
2624
2625 return 0;
2626}
2627
2628int
2629ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2630{
2631 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2632}
2633
2634int
2635ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2636{
2637 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2638}
2639
2640#endif /* SUPPORT_OSPF_API */
2641