blob: dac4c93fd07fa9fd07884b632ebceb1aa83fbed5 [file] [log] [blame]
paul2d33f152003-03-17 01:10:58 +00001/*
2 * Server side of OSPF API.
3 * Copyright (C) 2001, 2002 Ralph Keller
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#ifdef SUPPORT_OSPF_API
26#ifndef HAVE_OPAQUE_LSA
27#error "Core Opaque-LSA module must be configured."
28#endif /* HAVE_OPAQUE_LSA */
29
30#include "linklist.h"
31#include "prefix.h"
32#include "if.h"
33#include "table.h"
34#include "memory.h"
35#include "command.h"
36#include "vty.h"
37#include "stream.h"
38#include "log.h"
39#include "thread.h"
40#include "hash.h"
41#include "sockunion.h" /* for inet_aton() */
42#include "buffer.h"
43
44#include <sys/types.h>
45
46#include "ospfd/ospfd.h" /* for "struct thread_master" */
47#include "ospfd/ospf_interface.h"
48#include "ospfd/ospf_ism.h"
49#include "ospfd/ospf_asbr.h"
50#include "ospfd/ospf_lsa.h"
51#include "ospfd/ospf_lsdb.h"
52#include "ospfd/ospf_neighbor.h"
53#include "ospfd/ospf_nsm.h"
54#include "ospfd/ospf_flood.h"
55#include "ospfd/ospf_packet.h"
56#include "ospfd/ospf_spf.h"
57#include "ospfd/ospf_dump.h"
58#include "ospfd/ospf_route.h"
59#include "ospfd/ospf_ase.h"
60#include "ospfd/ospf_zebra.h"
61
62#include "ospfd/ospf_api.h"
63#include "ospfd/ospf_apiserver.h"
64
65/* This is an implementation of an API to the OSPF daemon that allows
66 * external applications to access the OSPF daemon through socket
67 * connections. The application can use this API to inject its own
68 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
69 * daemons then receive these LSAs and inform applications through the
70 * API by sending a corresponding message. The application can also
71 * register to receive all LSA types (in addition to opaque types) and
72 * use this information to reconstruct the OSPF's LSDB. The OSPF
73 * daemon supports multiple applications concurrently. */
74
75/* List of all active connections. */
paul87d6f872004-09-24 08:01:38 +000076struct list *apiserver_list;
paul2d33f152003-03-17 01:10:58 +000077
78/* -----------------------------------------------------------
79 * Functions to lookup interfaces
80 * -----------------------------------------------------------
81 */
82
83struct ospf_interface *
84ospf_apiserver_if_lookup_by_addr (struct in_addr address)
85{
paul1eb8ef22005-04-07 07:30:20 +000086 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +000087 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +000088 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +000089
paulafbacce2003-07-09 16:09:20 +000090 if (!(ospf = ospf_lookup ()))
paul5549c6b2003-07-09 15:46:33 +000091 return NULL;
paul99b7c5d2003-04-06 01:19:28 +000092
paul1eb8ef22005-04-07 07:30:20 +000093 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +000094 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
95 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
96 return oi;
97
paul2d33f152003-03-17 01:10:58 +000098 return NULL;
99}
100
101struct ospf_interface *
102ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
103{
paul1eb8ef22005-04-07 07:30:20 +0000104 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +0000105 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +0000106 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000107
paulafbacce2003-07-09 16:09:20 +0000108 if (!(ospf = ospf_lookup ()));
paul5549c6b2003-07-09 15:46:33 +0000109 return NULL;
paul99b7c5d2003-04-06 01:19:28 +0000110
paul1eb8ef22005-04-07 07:30:20 +0000111 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +0000112 if (oi->ifp == ifp)
113 return oi;
114
paul2d33f152003-03-17 01:10:58 +0000115 return NULL;
116}
117
118/* -----------------------------------------------------------
119 * Initialization
120 * -----------------------------------------------------------
121 */
122
123unsigned short
124ospf_apiserver_getport (void)
125{
126 struct servent *sp = getservbyname ("ospfapi", "tcp");
127
128 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
129}
130
131/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
132int
133ospf_apiserver_init (void)
134{
135 int fd;
136 int rc = -1;
137
138 /* Create new socket for synchronous messages. */
139 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
140
141 if (fd < 0)
142 goto out;
143
144 /* Schedule new thread that handles accepted connections. */
145 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
146
147 /* Initialize list that keeps track of all connections. */
148 apiserver_list = list_new ();
149
150 /* Register opaque-independent call back functions. These functions
151 are invoked on ISM, NSM changes and LSA update and LSA deletes */
152 rc =
153 ospf_register_opaque_functab (0 /* all LSAs */,
154 0 /* all opaque types */,
155 ospf_apiserver_new_if,
156 ospf_apiserver_del_if,
157 ospf_apiserver_ism_change,
158 ospf_apiserver_nsm_change,
159 NULL,
160 NULL,
161 NULL,
162 NULL, /* ospf_apiserver_show_info */
163 NULL, /* originator_func */
164 NULL, /* ospf_apiserver_lsa_refresher */
165 ospf_apiserver_lsa_update,
166 ospf_apiserver_lsa_delete);
167 if (rc != 0)
168 {
169 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
170 }
171
172 rc = 0;
173
174out:
175 return rc;
176}
177
178/* Terminate OSPF API module. */
179void
180ospf_apiserver_term (void)
181{
paul87d6f872004-09-24 08:01:38 +0000182 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +0000183
184 /* Unregister wildcard [0/0] type */
185 ospf_delete_opaque_functab (0 /* all LSAs */,
186 0 /* all opaque types */);
187
gdt3fb9de72004-12-09 16:30:04 +0000188 /*
189 * Free all client instances. ospf_apiserver_free removes the node
190 * from the list, so we examine the head of the list anew each time.
191 */
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{
302 struct thread *apiserver_serv_thread;
303
304 switch (event)
305 {
306 case OSPF_APISERVER_ACCEPT:
307 apiserver_serv_thread =
308 thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
309 break;
310 case OSPF_APISERVER_SYNC_READ:
311 apiserv->t_sync_read =
312 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
313 break;
314#ifdef USE_ASYNC_READ
315 case OSPF_APISERVER_ASYNC_READ:
316 apiserv->t_async_read =
317 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
318 break;
319#endif /* USE_ASYNC_READ */
320 case OSPF_APISERVER_SYNC_WRITE:
321 if (!apiserv->t_sync_write)
322 {
323 apiserv->t_sync_write =
324 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
325 }
326 break;
327 case OSPF_APISERVER_ASYNC_WRITE:
328 if (!apiserv->t_async_write)
329 {
330 apiserv->t_async_write =
331 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
332 }
333 break;
334 }
335}
336
337/* Free instance. First unregister all opaque types used by
338 application, flush opaque LSAs injected by application
339 from network and close connection. */
340void
341ospf_apiserver_free (struct ospf_apiserver *apiserv)
342{
paul87d6f872004-09-24 08:01:38 +0000343 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000344
345 /* Cancel read and write threads. */
346 if (apiserv->t_sync_read)
347 {
348 thread_cancel (apiserv->t_sync_read);
349 }
350#ifdef USE_ASYNC_READ
351 if (apiserv->t_async_read)
352 {
353 thread_cancel (apiserv->t_async_read);
354 }
355#endif /* USE_ASYNC_READ */
356 if (apiserv->t_sync_write)
357 {
358 thread_cancel (apiserv->t_sync_write);
359 }
360
361 if (apiserv->t_async_write)
362 {
363 thread_cancel (apiserv->t_async_write);
364 }
365
366 /* Unregister all opaque types that application registered
367 and flush opaque LSAs if still in LSDB. */
368
369 while ((node = listhead (apiserv->opaque_types)) != NULL)
370 {
paul1eb8ef22005-04-07 07:30:20 +0000371 struct registered_opaque_type *regtype = listgetdata(node);
paul2d33f152003-03-17 01:10:58 +0000372
373 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
374 regtype->opaque_type);
375
376 }
377
378 /* Close connections to OSPFd. */
379 if (apiserv->fd_sync > 0)
380 {
381 close (apiserv->fd_sync);
382 }
383
384 if (apiserv->fd_async > 0)
385 {
386 close (apiserv->fd_async);
387 }
388
389 /* Free fifos */
390 msg_fifo_free (apiserv->out_sync_fifo);
391 msg_fifo_free (apiserv->out_async_fifo);
392
393 /* Clear temporary strage for LSA instances to be refreshed. */
394 ospf_lsdb_delete_all (&apiserv->reserve);
395 ospf_lsdb_cleanup (&apiserv->reserve);
396
397 /* Remove from the list of active clients. */
398 listnode_delete (apiserver_list, apiserv);
399
400 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000401 zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000402
403 /* And free instance. */
404 XFREE (MTYPE_OSPF_APISERVER, apiserv);
405}
406
407int
408ospf_apiserver_read (struct thread *thread)
409{
410 struct ospf_apiserver *apiserv;
411 struct msg *msg;
412 int fd;
413 int rc = -1;
414 enum event event;
415
416 apiserv = THREAD_ARG (thread);
417 fd = THREAD_FD (thread);
418
419 if (fd == apiserv->fd_sync)
420 {
421 event = OSPF_APISERVER_SYNC_READ;
422 apiserv->t_sync_read = NULL;
423
424 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000425 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000426 inet_ntoa (apiserv->peer_sync.sin_addr),
427 ntohs (apiserv->peer_sync.sin_port));
428 }
429#ifdef USE_ASYNC_READ
430 else if (fd == apiserv->fd_async)
431 {
432 event = OSPF_APISERVER_ASYNC_READ;
433 apiserv->t_async_read = NULL;
434
435 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000436 zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000437 inet_ntoa (apiserv->peer_async.sin_addr),
438 ntohs (apiserv->peer_async.sin_port));
439 }
440#endif /* USE_ASYNC_READ */
441 else
442 {
443 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
444 ospf_apiserver_free (apiserv);
445 goto out;
446 }
447
448 /* Read message from fd. */
449 msg = msg_read (fd);
450 if (msg == NULL)
451 {
452 zlog_warn
453 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
454
455 /* Perform cleanup. */
456 ospf_apiserver_free (apiserv);
457 goto out;
458 }
459
460 if (IS_DEBUG_OSPF_EVENT)
461 msg_print (msg);
462
463 /* Dispatch to corresponding message handler. */
464 rc = ospf_apiserver_handle_msg (apiserv, msg);
465
466 /* Prepare for next message, add read thread. */
467 ospf_apiserver_event (event, fd, apiserv);
468
469 msg_free (msg);
470
471out:
472 return rc;
473}
474
475int
476ospf_apiserver_sync_write (struct thread *thread)
477{
478 struct ospf_apiserver *apiserv;
479 struct msg *msg;
480 int fd;
481 int rc = -1;
482
483 apiserv = THREAD_ARG (thread);
484 assert (apiserv);
485 fd = THREAD_FD (thread);
486
487 apiserv->t_sync_write = NULL;
488
489 /* Sanity check */
490 if (fd != apiserv->fd_sync)
491 {
492 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
493 goto out;
494 }
495
496 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000497 zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000498 inet_ntoa (apiserv->peer_sync.sin_addr),
499 ntohs (apiserv->peer_sync.sin_port));
500
501 /* Check whether there is really a message in the fifo. */
502 msg = msg_fifo_pop (apiserv->out_sync_fifo);
503 if (!msg)
504 {
505 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
506 return 0;
507 }
508
509 if (IS_DEBUG_OSPF_EVENT)
510 msg_print (msg);
511
512 rc = msg_write (fd, msg);
513
514 /* Once a message is dequeued, it should be freed anyway. */
515 msg_free (msg);
516
517 if (rc < 0)
518 {
519 zlog_warn
520 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
521 goto out;
522 }
523
524
525 /* If more messages are in sync message fifo, schedule write thread. */
526 if (msg_fifo_head (apiserv->out_sync_fifo))
527 {
528 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
529 apiserv);
530 }
531
532 out:
533
534 if (rc < 0)
535 {
536 /* Perform cleanup and disconnect with peer */
537 ospf_apiserver_free (apiserv);
538 }
539
540 return rc;
541}
542
543
544int
545ospf_apiserver_async_write (struct thread *thread)
546{
547 struct ospf_apiserver *apiserv;
548 struct msg *msg;
549 int fd;
550 int rc = -1;
551
552 apiserv = THREAD_ARG (thread);
553 assert (apiserv);
554 fd = THREAD_FD (thread);
555
556 apiserv->t_async_write = NULL;
557
558 /* Sanity check */
559 if (fd != apiserv->fd_async)
560 {
561 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
562 goto out;
563 }
564
565 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000566 zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000567 inet_ntoa (apiserv->peer_async.sin_addr),
568 ntohs (apiserv->peer_async.sin_port));
569
570 /* Check whether there is really a message in the fifo. */
571 msg = msg_fifo_pop (apiserv->out_async_fifo);
572 if (!msg)
573 {
574 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
575 return 0;
576 }
577
578 if (IS_DEBUG_OSPF_EVENT)
579 msg_print (msg);
580
581 rc = msg_write (fd, msg);
582
583 /* Once a message is dequeued, it should be freed anyway. */
584 msg_free (msg);
585
586 if (rc < 0)
587 {
588 zlog_warn
589 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
590 goto out;
591 }
592
593
594 /* If more messages are in async message fifo, schedule write thread. */
595 if (msg_fifo_head (apiserv->out_async_fifo))
596 {
597 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
598 apiserv);
599 }
600
601 out:
602
603 if (rc < 0)
604 {
605 /* Perform cleanup and disconnect with peer */
606 ospf_apiserver_free (apiserv);
607 }
608
609 return rc;
610}
611
612
613int
614ospf_apiserver_serv_sock_family (unsigned short port, int family)
615{
616 union sockunion su;
617 int accept_sock;
618 int rc;
619
620 memset (&su, 0, sizeof (union sockunion));
621 su.sa.sa_family = family;
622
623 /* Make new socket */
624 accept_sock = sockunion_stream_socket (&su);
625 if (accept_sock < 0)
626 return accept_sock;
627
628 /* This is a server, so reuse address and port */
629 sockopt_reuseaddr (accept_sock);
630 sockopt_reuseport (accept_sock);
631
632 /* Bind socket to address and given port. */
633 rc = sockunion_bind (accept_sock, &su, port, NULL);
634 if (rc < 0)
635 {
636 close (accept_sock); /* Close socket */
637 return rc;
638 }
639
640 /* Listen socket under queue length 3. */
641 rc = listen (accept_sock, 3);
642 if (rc < 0)
643 {
644 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
ajs6099b3b2004-11-20 02:06:59 +0000645 safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000646 close (accept_sock); /* Close socket */
647 return rc;
648 }
649 return accept_sock;
650}
651
652
653/* Accept connection request from external applications. For each
654 accepted connection allocate own connection instance. */
655int
656ospf_apiserver_accept (struct thread *thread)
657{
658 int accept_sock;
659 int new_sync_sock;
660 int new_async_sock;
661 union sockunion su;
662 struct ospf_apiserver *apiserv;
663 struct sockaddr_in peer_async;
664 struct sockaddr_in peer_sync;
paul36238142005-10-11 04:12:54 +0000665 unsigned int peerlen;
paul2d33f152003-03-17 01:10:58 +0000666 int ret;
667
668 /* THREAD_ARG (thread) is NULL */
669 accept_sock = THREAD_FD (thread);
670
671 /* Keep hearing on socket for further connections. */
672 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
673
674 memset (&su, 0, sizeof (union sockunion));
675 /* Accept connection for synchronous messages */
676 new_sync_sock = sockunion_accept (accept_sock, &su);
677 if (new_sync_sock < 0)
678 {
ajs6099b3b2004-11-20 02:06:59 +0000679 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000680 return -1;
681 }
682
683 /* Get port address and port number of peer to make reverse connection.
684 The reverse channel uses the port number of the peer port+1. */
685
686 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
687 peerlen = sizeof (struct sockaddr_in);
688
689 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
690 if (ret < 0)
691 {
ajs6099b3b2004-11-20 02:06:59 +0000692 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000693 close (new_sync_sock);
694 return -1;
695 }
696
697 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000698 zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
paul2d33f152003-03-17 01:10:58 +0000699 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
700
701 /* Create new socket for asynchronous messages. */
702 peer_async = peer_sync;
703 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
704
705 /* Check if remote port number to make reverse connection is valid one. */
706 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
707 {
708 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
709 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
710 close (new_sync_sock);
711 return -1;
712 }
713
714 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
715 if (new_async_sock < 0)
716 {
ajs6099b3b2004-11-20 02:06:59 +0000717 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000718 close (new_sync_sock);
719 return -1;
720 }
721
722 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
723 sizeof (struct sockaddr_in));
724
725 if (ret < 0)
726 {
ajs6099b3b2004-11-20 02:06:59 +0000727 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000728 close (new_sync_sock);
729 close (new_async_sock);
730 return -1;
731 }
732
733#ifdef USE_ASYNC_READ
734#else /* USE_ASYNC_READ */
735 /* Make the asynchronous channel write-only. */
736 ret = shutdown (new_async_sock, SHUT_RD);
737 if (ret < 0)
738 {
ajs6099b3b2004-11-20 02:06:59 +0000739 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000740 close (new_sync_sock);
741 close (new_async_sock);
742 return -1;
743 }
744#endif /* USE_ASYNC_READ */
745
746 /* Allocate new server-side connection structure */
747 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
748
749 /* Add to active connection list */
750 listnode_add (apiserver_list, apiserv);
751 apiserv->peer_sync = peer_sync;
752 apiserv->peer_async = peer_async;
753
754 /* And add read threads for new connection */
755 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
756#ifdef USE_ASYNC_READ
757 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
758#endif /* USE_ASYNC_READ */
759
760 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000761 zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
paul2d33f152003-03-17 01:10:58 +0000762
763 return 0;
764}
765
766
767/* -----------------------------------------------------------
768 * Send reply with return code to client application
769 * -----------------------------------------------------------
770 */
771
paul4dadc292005-05-06 21:37:42 +0000772static int
paul2d33f152003-03-17 01:10:58 +0000773ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
774{
775 struct msg_fifo *fifo;
776 struct msg *msg2;
777 enum event event;
778 int fd;
779
780 switch (msg->hdr.msgtype)
781 {
782 case MSG_REPLY:
783 fifo = apiserv->out_sync_fifo;
784 fd = apiserv->fd_sync;
785 event = OSPF_APISERVER_SYNC_WRITE;
786 break;
787 case MSG_READY_NOTIFY:
788 case MSG_LSA_UPDATE_NOTIFY:
789 case MSG_LSA_DELETE_NOTIFY:
790 case MSG_NEW_IF:
791 case MSG_DEL_IF:
792 case MSG_ISM_CHANGE:
793 case MSG_NSM_CHANGE:
794 fifo = apiserv->out_async_fifo;
795 fd = apiserv->fd_async;
796 event = OSPF_APISERVER_ASYNC_WRITE;
797 break;
798 default:
799 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
800 msg->hdr.msgtype);
801 return -1;
802 }
803
804 /* Make a copy of the message and put in the fifo. Once the fifo
805 gets drained by the write thread, the message will be freed. */
806 /* NB: Given "msg" is untouched in this function. */
807 msg2 = msg_dup (msg);
808
809 /* Enqueue message into corresponding fifo queue */
810 msg_fifo_push (fifo, msg2);
811
812 /* Schedule write thread */
813 ospf_apiserver_event (event, fd, apiserv);
814 return 0;
815}
816
817int
818ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
819 u_char rc)
820{
821 struct msg *msg = new_msg_reply (seqnr, rc);
822 int ret;
823
824 if (!msg)
825 {
826 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
827#ifdef NOTYET
828 /* Cannot allocate new message. What should we do? */
829 ospf_apiserver_free (apiserv);
830#endif
831 return -1;
832 }
833
834 ret = ospf_apiserver_send_msg (apiserv, msg);
835 msg_free (msg);
836 return ret;
837}
838
839
840/* -----------------------------------------------------------
841 * Generic message dispatching handler function
842 * -----------------------------------------------------------
843 */
844
845int
846ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
847{
848 int rc;
849
850 /* Call corresponding message handler function. */
851 switch (msg->hdr.msgtype)
852 {
853 case MSG_REGISTER_OPAQUETYPE:
854 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
855 break;
856 case MSG_UNREGISTER_OPAQUETYPE:
857 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
858 break;
859 case MSG_REGISTER_EVENT:
860 rc = ospf_apiserver_handle_register_event (apiserv, msg);
861 break;
862 case MSG_SYNC_LSDB:
863 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
864 break;
865 case MSG_ORIGINATE_REQUEST:
866 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
867 break;
868 case MSG_DELETE_REQUEST:
869 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
870 break;
871 default:
872 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
873 msg->hdr.msgtype);
874 rc = -1;
875 }
876 return rc;
877}
878
879
880/* -----------------------------------------------------------
881 * Following are functions for opaque type registration
882 * -----------------------------------------------------------
883 */
884
885int
886ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
887 u_char lsa_type, u_char opaque_type)
888{
889 struct registered_opaque_type *regtype;
890 int (*originator_func) (void *arg);
891 int rc;
892
893 switch (lsa_type)
894 {
895 case OSPF_OPAQUE_LINK_LSA:
896 originator_func = ospf_apiserver_lsa9_originator;
897 break;
898 case OSPF_OPAQUE_AREA_LSA:
899 originator_func = ospf_apiserver_lsa10_originator;
900 break;
901 case OSPF_OPAQUE_AS_LSA:
902 originator_func = ospf_apiserver_lsa11_originator;
903 break;
904 default:
905 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
906 lsa_type);
907 return OSPF_API_ILLEGALLSATYPE;
908 }
909
910
911 /* Register opaque function table */
912 /* NB: Duplicated registration will be detected inside the function. */
913 rc =
914 ospf_register_opaque_functab (lsa_type, opaque_type,
915 NULL, /* ospf_apiserver_new_if */
916 NULL, /* ospf_apiserver_del_if */
917 NULL, /* ospf_apiserver_ism_change */
918 NULL, /* ospf_apiserver_nsm_change */
919 NULL,
920 NULL,
921 NULL,
922 ospf_apiserver_show_info,
923 originator_func,
924 ospf_apiserver_lsa_refresher,
925 NULL, /* ospf_apiserver_lsa_update */
926 NULL /* ospf_apiserver_lsa_delete */);
927
928 if (rc != 0)
929 {
930 zlog_warn ("Failed to register opaque type [%d/%d]",
931 lsa_type, opaque_type);
932 return OSPF_API_OPAQUETYPEINUSE;
933 }
934
935 /* Remember the opaque type that application registers so when
936 connection shuts down, we can flush all LSAs of this opaque
937 type. */
938
939 regtype =
940 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
941 memset (regtype, 0, sizeof (struct registered_opaque_type));
942 regtype->lsa_type = lsa_type;
943 regtype->opaque_type = opaque_type;
944
945 /* Add to list of registered opaque types */
946 listnode_add (apiserv->opaque_types, regtype);
947
948 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000949 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
paul87d6f872004-09-24 08:01:38 +0000950 " apiserv(%p), total#(%d)",
951 lsa_type, opaque_type, apiserv,
952 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000953
954 return 0;
955}
956
957int
958ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
959 u_char lsa_type, u_char opaque_type)
960{
paul1eb8ef22005-04-07 07:30:20 +0000961 struct listnode *node, *nnode;
gdt54ade992004-10-07 19:38:20 +0000962 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000963
paul1eb8ef22005-04-07 07:30:20 +0000964 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +0000965 {
paul2d33f152003-03-17 01:10:58 +0000966 /* Check if we really registered this opaque type */
967 if (regtype->lsa_type == lsa_type &&
968 regtype->opaque_type == opaque_type)
969 {
970
971 /* Yes, we registered this opaque type. Flush
972 all existing opaque LSAs of this type */
973
974 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
975 ospf_delete_opaque_functab (lsa_type, opaque_type);
976
977 /* Remove from list of registered opaque types */
978 listnode_delete (apiserv->opaque_types, regtype);
979
980 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000981 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
paul87d6f872004-09-24 08:01:38 +0000982 " from apiserv(%p), total#(%d)",
983 lsa_type, opaque_type, apiserv,
984 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000985
986 return 0;
987 }
988 }
989
990 /* Opaque type is not registered */
991 zlog_warn ("Failed to unregister opaque type [%d/%d]",
992 lsa_type, opaque_type);
993 return OSPF_API_OPAQUETYPENOTREGISTERED;
994}
995
996
paul4dadc292005-05-06 21:37:42 +0000997static int
paul2d33f152003-03-17 01:10:58 +0000998apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
999 u_char lsa_type, u_char opaque_type)
1000{
paul1eb8ef22005-04-07 07:30:20 +00001001 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001002 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001003
paul87d6f872004-09-24 08:01:38 +00001004 /* XXX: how many types are there? if few, why not just a bitmap? */
paul1eb8ef22005-04-07 07:30:20 +00001005 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +00001006 {
paul2d33f152003-03-17 01:10:58 +00001007 /* Check if we really registered this opaque type */
1008 if (regtype->lsa_type == lsa_type &&
1009 regtype->opaque_type == opaque_type)
1010 {
1011 /* Yes registered */
1012 return 1;
1013 }
1014 }
1015 /* Not registered */
1016 return 0;
1017}
1018
1019int
1020ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1021 struct msg *msg)
1022{
1023 struct msg_register_opaque_type *rmsg;
1024 u_char lsa_type;
1025 u_char opaque_type;
1026 int rc = 0;
1027
1028 /* Extract parameters from register opaque type message */
1029 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1030
1031 lsa_type = rmsg->lsatype;
1032 opaque_type = rmsg->opaquetype;
1033
1034 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1035
1036 /* Send a reply back to client including return code */
1037 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1038 if (rc < 0)
1039 goto out;
1040
1041 /* Now inform application about opaque types that are ready */
1042 switch (lsa_type)
1043 {
1044 case OSPF_OPAQUE_LINK_LSA:
1045 ospf_apiserver_notify_ready_type9 (apiserv);
1046 break;
1047 case OSPF_OPAQUE_AREA_LSA:
1048 ospf_apiserver_notify_ready_type10 (apiserv);
1049 break;
1050 case OSPF_OPAQUE_AS_LSA:
1051 ospf_apiserver_notify_ready_type11 (apiserv);
1052 break;
1053 }
1054out:
1055 return rc;
1056}
1057
1058
1059/* Notify specific client about all opaque types 9 that are ready. */
1060void
1061ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1062{
paul1eb8ef22005-04-07 07:30:20 +00001063 struct listnode *node, *nnode;
1064 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001065 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001066 struct ospf_interface *oi;
1067 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001068
paul99b7c5d2003-04-06 01:19:28 +00001069 ospf = ospf_lookup ();
1070
paul1eb8ef22005-04-07 07:30:20 +00001071 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul2d33f152003-03-17 01:10:58 +00001072 {
paul2d33f152003-03-17 01:10:58 +00001073 /* Check if this interface is indeed ready for type 9 */
1074 if (!ospf_apiserver_is_ready_type9 (oi))
1075 continue;
1076
1077 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001078 /* XXX: loop-de-loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001079 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001080 {
paul2d33f152003-03-17 01:10:58 +00001081 struct msg *msg;
1082
1083 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1084 {
1085
1086 /* Yes, this opaque type is ready */
1087 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1088 r->opaque_type,
1089 oi->address->u.prefix4);
1090 if (!msg)
1091 {
1092 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1093#ifdef NOTYET
1094 /* Cannot allocate new message. What should we do? */
1095 ospf_apiserver_free (apiserv);
1096#endif
1097 goto out;
1098 }
1099 ospf_apiserver_send_msg (apiserv, msg);
1100 msg_free (msg);
1101 }
1102 }
1103 }
1104
1105out:
1106 return;
1107}
1108
1109
1110/* Notify specific client about all opaque types 10 that are ready. */
1111void
1112ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1113{
paul1eb8ef22005-04-07 07:30:20 +00001114 struct listnode *node, *nnode;
1115 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001116 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001117 struct ospf_area *area;
1118
paul99b7c5d2003-04-06 01:19:28 +00001119 ospf = ospf_lookup ();
1120
paul1eb8ef22005-04-07 07:30:20 +00001121 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001122 {
paul87d6f872004-09-24 08:01:38 +00001123 struct registered_opaque_type *r;
1124
paul2d33f152003-03-17 01:10:58 +00001125 if (!ospf_apiserver_is_ready_type10 (area))
1126 {
1127 continue;
1128 }
1129
1130 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001131 /* XXX: loop in loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001132 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001133 {
paul2d33f152003-03-17 01:10:58 +00001134 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001135
paul2d33f152003-03-17 01:10:58 +00001136 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1137 {
1138 /* Yes, this opaque type is ready */
1139 msg =
1140 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1141 r->opaque_type, area->area_id);
1142 if (!msg)
1143 {
1144 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1145#ifdef NOTYET
1146 /* Cannot allocate new message. What should we do? */
1147 ospf_apiserver_free (apiserv);
1148#endif
1149 goto out;
1150 }
1151 ospf_apiserver_send_msg (apiserv, msg);
1152 msg_free (msg);
1153 }
1154 }
1155 }
1156
1157out:
1158 return;
1159}
1160
1161/* Notify specific client about all opaque types 11 that are ready */
1162void
1163ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1164{
paul1eb8ef22005-04-07 07:30:20 +00001165 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00001166 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001167 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001168
1169 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001170
1171 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001172 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001173 goto out;
paul2d33f152003-03-17 01:10:58 +00001174
1175 /* Check for registered opaque type 11 types */
paul1eb8ef22005-04-07 07:30:20 +00001176 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
paul2d33f152003-03-17 01:10:58 +00001177 {
paul2d33f152003-03-17 01:10:58 +00001178 struct msg *msg;
paul36238142005-10-11 04:12:54 +00001179 struct in_addr noarea_id = { .s_addr = 0L };
1180
paul2d33f152003-03-17 01:10:58 +00001181 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1182 {
1183 /* Yes, this opaque type is ready */
1184 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1185 r->opaque_type, noarea_id);
1186
1187 if (!msg)
1188 {
1189 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1190#ifdef NOTYET
1191 /* Cannot allocate new message. What should we do? */
1192 ospf_apiserver_free (apiserv);
1193#endif
1194 goto out;
1195 }
1196 ospf_apiserver_send_msg (apiserv, msg);
1197 msg_free (msg);
1198 }
1199 }
1200
1201out:
1202 return;
1203}
1204
1205int
1206ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1207 struct msg *msg)
1208{
1209 struct msg_unregister_opaque_type *umsg;
1210 u_char ltype;
1211 u_char otype;
1212 int rc = 0;
1213
1214 /* Extract parameters from unregister opaque type message */
1215 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1216
1217 ltype = umsg->lsatype;
1218 otype = umsg->opaquetype;
1219
1220 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1221
1222 /* Send a reply back to client including return code */
1223 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1224
1225 return rc;
1226}
1227
1228
1229/* -----------------------------------------------------------
1230 * Following are functions for event (filter) registration.
1231 * -----------------------------------------------------------
1232 */
1233int
1234ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1235 struct msg *msg)
1236{
1237 struct msg_register_event *rmsg;
1238 int rc;
1239 u_int32_t seqnum;
1240
1241 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1242
1243 /* Get request sequence number */
1244 seqnum = msg_get_seq (msg);
1245
1246 /* Free existing filter in apiserv. */
1247 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1248 /* Alloc new space for filter. */
1249
1250 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1251 ntohs (msg->hdr.msglen));
1252 if (apiserv->filter)
1253 {
1254 /* copy it over. */
1255 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1256 rc = OSPF_API_OK;
1257 }
1258 else
1259 {
1260 rc = OSPF_API_NOMEMORY;
1261 }
1262 /* Send a reply back to client with return code */
1263 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1264 return rc;
1265}
1266
1267
1268/* -----------------------------------------------------------
1269 * Followings are functions for LSDB synchronization.
1270 * -----------------------------------------------------------
1271 */
1272
paul4dadc292005-05-06 21:37:42 +00001273static int
paul2d33f152003-03-17 01:10:58 +00001274apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1275{
1276 struct ospf_apiserver *apiserv;
1277 int seqnum;
1278 struct msg *msg;
1279 struct param_t
1280 {
1281 struct ospf_apiserver *apiserv;
1282 struct lsa_filter_type *filter;
1283 }
1284 *param;
1285 int rc = -1;
1286
1287 /* Sanity check */
1288 assert (lsa->data);
1289 assert (p_arg);
1290
1291 param = (struct param_t *) p_arg;
1292 apiserv = param->apiserv;
1293 seqnum = (u_int32_t) int_arg;
1294
1295 /* Check origin in filter. */
1296 if ((param->filter->origin == ANY_ORIGIN) ||
1297 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1298 {
1299
1300 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00001301 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00001302
1303 /* Default interface for non Opaque9 LSAs */
paul484315f2005-11-03 09:08:29 +00001304 struct in_addr ifaddr = { .s_addr = 0L };
paul36238142005-10-11 04:12:54 +00001305
paul2d33f152003-03-17 01:10:58 +00001306 if (lsa->area)
1307 {
1308 area_id = lsa->area->area_id;
1309 }
1310 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1311 {
1312 ifaddr = lsa->oi->address->u.prefix4;
1313 }
1314
1315 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1316 seqnum,
1317 ifaddr, area_id,
1318 lsa->flags & OSPF_LSA_SELF, lsa->data);
1319 if (!msg)
1320 {
1321 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1322#ifdef NOTYET
1323 /* Cannot allocate new message. What should we do? */
1324/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1325#endif
1326 goto out;
1327 }
1328
1329 /* Send LSA */
1330 ospf_apiserver_send_msg (apiserv, msg);
1331 msg_free (msg);
1332 }
1333 rc = 0;
1334
1335out:
1336 return rc;
1337}
1338
1339int
1340ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1341 struct msg *msg)
1342{
paul1eb8ef22005-04-07 07:30:20 +00001343 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00001344 u_int32_t seqnum;
1345 int rc = 0;
1346 struct msg_sync_lsdb *smsg;
paul1eb8ef22005-04-07 07:30:20 +00001347 struct ospf_apiserver_param_t
paul2d33f152003-03-17 01:10:58 +00001348 {
1349 struct ospf_apiserver *apiserv;
1350 struct lsa_filter_type *filter;
paul1eb8ef22005-04-07 07:30:20 +00001351 } param;
paul2d33f152003-03-17 01:10:58 +00001352 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001353 struct route_node *rn;
1354 struct ospf_lsa *lsa;
1355 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001356 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001357
1358 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001359
1360 /* Get request sequence number */
1361 seqnum = msg_get_seq (msg);
1362 /* Set sync msg. */
1363 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1364
1365 /* Set parameter struct. */
1366 param.apiserv = apiserv;
1367 param.filter = &smsg->filter;
1368
1369 /* Remember mask. */
1370 mask = ntohs (smsg->filter.typemask);
1371
1372 /* Iterate over all areas. */
paul1eb8ef22005-04-07 07:30:20 +00001373 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001374 {
paul2d33f152003-03-17 01:10:58 +00001375 int i;
1376 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001377
paul2d33f152003-03-17 01:10:58 +00001378 /* Compare area_id with area_ids in sync request. */
1379 if ((i = smsg->filter.num_areas) > 0)
1380 {
1381 /* Let area_id point to the list of area IDs,
1382 * which is at the end of smsg->filter. */
1383 area_id = (u_int32_t *) (&smsg->filter + 1);
1384 while (i)
1385 {
1386 if (*area_id == area->area_id.s_addr)
1387 {
1388 break;
1389 }
1390 i--;
1391 area_id++;
1392 }
1393 }
1394 else
1395 {
1396 i = 1;
1397 }
1398
1399 /* If area was found, then i>0 here. */
1400 if (i)
1401 {
1402 /* Check msg type. */
1403 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001404 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1405 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001406 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001407 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1408 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001409 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001410 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1411 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001412 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001413 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1414 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001415 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001416 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1417 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001418 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001419 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1420 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001421 }
1422 }
1423
1424 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001425 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001426 {
1427 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001428 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1429 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001430 }
1431
1432 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001433 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001434 {
1435 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001436 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1437 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001438 }
1439
1440 /* Send a reply back to client with return code */
1441 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1442 return rc;
1443}
1444
1445
1446/* -----------------------------------------------------------
1447 * Followings are functions to originate or update LSA
1448 * from an application.
1449 * -----------------------------------------------------------
1450 */
1451
1452/* Create a new internal opaque LSA by taking prototype and filling in
1453 missing fields such as age, sequence number, advertising router,
1454 checksum and so on. The interface parameter is used for type 9
1455 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1456 nor interface. */
1457
1458struct ospf_lsa *
1459ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1460 struct ospf_interface *oi,
1461 struct lsa_header *protolsa)
1462{
1463 struct stream *s;
1464 struct lsa_header *newlsa;
1465 struct ospf_lsa *new = NULL;
1466 u_char options = 0x0;
1467 u_int16_t length;
1468
paul99b7c5d2003-04-06 01:19:28 +00001469 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001470
paul99b7c5d2003-04-06 01:19:28 +00001471 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001472 assert(ospf);
1473
paul2d33f152003-03-17 01:10:58 +00001474 /* Create a stream for internal opaque LSA */
1475 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1476 {
1477 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1478 return NULL;
1479 }
1480
1481 newlsa = (struct lsa_header *) STREAM_DATA (s);
1482
1483 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1484 have to set options? */
1485
1486 if (area)
1487 {
1488 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001489 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001490 }
1491
1492 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1493
1494 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1495 {
ajse84cc642004-12-08 17:28:56 +00001496 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
paul2d33f152003-03-17 01:10:58 +00001497 protolsa->type, inet_ntoa (protolsa->id));
1498 }
1499
1500 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001501 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001502 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001503
1504 /* Set opaque-LSA body fields. */
1505 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1506 ntohs (protolsa->length) - sizeof (struct lsa_header));
1507
1508 /* Determine length of LSA. */
1509 length = stream_get_endp (s);
1510 newlsa->length = htons (length);
1511
1512 /* Create OSPF LSA. */
1513 if ((new = ospf_lsa_new ()) == NULL)
1514 {
1515 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1516 stream_free (s);
1517 return NULL;
1518 }
1519
1520 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1521 {
1522 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001523 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001524 stream_free (s);
1525 return NULL;
1526 }
1527
1528 new->area = area;
1529 new->oi = oi;
1530
1531 SET_FLAG (new->flags, OSPF_LSA_SELF);
1532 memcpy (new->data, newlsa, length);
1533 stream_free (s);
1534
1535 return new;
1536}
1537
1538
1539int
1540ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1541{
1542 /* Type 9 opaque LSA can be originated if there is at least one
1543 active opaque-capable neighbor attached to the outgoing
1544 interface. */
1545
paula15f45d2003-03-28 01:50:03 +00001546 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001547}
1548
1549int
1550ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1551{
1552 /* Type 10 opaque LSA can be originated if there is at least one
1553 interface belonging to the area that has an active opaque-capable
1554 neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001555 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001556 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001557
paul1eb8ef22005-04-07 07:30:20 +00001558 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001559 /* Is there an active neighbor attached to this interface? */
1560 if (ospf_apiserver_is_ready_type9 (oi))
1561 return 1;
paul2d33f152003-03-17 01:10:58 +00001562
paul2d33f152003-03-17 01:10:58 +00001563 /* No active neighbor in area */
1564 return 0;
1565}
1566
1567int
1568ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1569{
1570 /* Type 11 opaque LSA can be originated if there is at least one interface
1571 that has an active opaque-capable neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001572 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001573 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001574
paul1eb8ef22005-04-07 07:30:20 +00001575 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001576 /* Is there an active neighbor attached to this interface? */
1577 if (ospf_apiserver_is_ready_type9 (oi))
1578 return 1;
paul2d33f152003-03-17 01:10:58 +00001579
paul2d33f152003-03-17 01:10:58 +00001580 /* No active neighbor at all */
1581 return 0;
1582}
1583
1584
1585int
1586ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1587 struct msg *msg)
1588{
1589 struct msg_originate_request *omsg;
1590 struct lsa_header *data;
1591 struct ospf_lsa *new;
1592 struct ospf_lsa *old;
1593 struct ospf_area *area = NULL;
1594 struct ospf_interface *oi = NULL;
1595 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001596 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001597 int lsa_type, opaque_type;
1598 int ready = 0;
1599 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001600
paul99b7c5d2003-04-06 01:19:28 +00001601 ospf = ospf_lookup();
1602
paul2d33f152003-03-17 01:10:58 +00001603 /* Extract opaque LSA data from message */
1604 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1605 data = &omsg->data;
1606
1607 /* Determine interface for type9 or area for type10 LSAs. */
1608 switch (data->type)
1609 {
1610 case OSPF_OPAQUE_LINK_LSA:
1611 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1612 if (!oi)
1613 {
1614 zlog_warn ("apiserver_originate: unknown interface %s",
1615 inet_ntoa (omsg->ifaddr));
1616 rc = OSPF_API_NOSUCHINTERFACE;
1617 goto out;
1618 }
1619 area = oi->area;
1620 lsdb = area->lsdb;
1621 break;
1622 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001623 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001624 if (!area)
1625 {
1626 zlog_warn ("apiserver_originate: unknown area %s",
1627 inet_ntoa (omsg->area_id));
1628 rc = OSPF_API_NOSUCHAREA;
1629 goto out;
1630 }
1631 lsdb = area->lsdb;
1632 break;
1633 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001634 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001635 break;
1636 default:
1637 /* We can only handle opaque types here */
1638 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1639 data->type);
1640 rc = OSPF_API_ILLEGALLSATYPE;
1641 goto out;
1642 }
1643
1644 /* Check if we registered this opaque type */
1645 lsa_type = data->type;
1646 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1647
1648 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1649 {
1650 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1651 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1652 goto out;
1653 }
1654
1655 /* Make sure that the neighbors are ready before we can originate */
1656 switch (data->type)
1657 {
1658 case OSPF_OPAQUE_LINK_LSA:
1659 ready = ospf_apiserver_is_ready_type9 (oi);
1660 break;
1661 case OSPF_OPAQUE_AREA_LSA:
1662 ready = ospf_apiserver_is_ready_type10 (area);
1663 break;
1664 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001665 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001666 break;
1667 default:
1668 break;
1669 }
1670
1671 if (!ready)
1672 {
1673 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1674 rc = OSPF_API_NOTREADY;
1675 goto out;
1676 }
1677
1678 /* Create OSPF's internal opaque LSA representation */
1679 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1680 if (!new)
1681 {
1682 rc = OSPF_API_NOMEMORY; /* XXX */
1683 goto out;
1684 }
1685
1686 /* Determine if LSA is new or an update for an existing one. */
1687 old = ospf_lsdb_lookup (lsdb, new);
1688
1689 if (!old)
1690 {
1691 /* New LSA install in LSDB. */
1692 rc = ospf_apiserver_originate1 (new);
1693 }
1694 else
1695 {
1696 /*
1697 * Keep the new LSA instance in the "waiting place" until the next
1698 * refresh timing. If several LSA update requests for the same LSID
1699 * have issued by peer, the last one takes effect.
1700 */
1701 new->lsdb = &apiserv->reserve;
1702 ospf_lsdb_add (&apiserv->reserve, new);
1703
1704 /* Kick the scheduler function. */
1705 ospf_opaque_lsa_refresh_schedule (old);
1706 }
1707
1708out:
1709
1710 /* Send a reply back to client with return code */
1711 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1712 return rc;
1713}
1714
1715
1716/* -----------------------------------------------------------
1717 * Flood an LSA within its flooding scope.
1718 * -----------------------------------------------------------
1719 */
1720
1721/* XXX We can probably use ospf_flood_through instead of this function
1722 but then we need the neighbor parameter. If we set nbr to
1723 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1724
1725void
1726ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1727{
1728 assert (lsa);
1729
1730 switch (lsa->data->type)
1731 {
1732 case OSPF_OPAQUE_LINK_LSA:
1733 /* Increment counters? XXX */
1734
1735 /* Flood LSA through local network. */
1736 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1737 break;
1738 case OSPF_OPAQUE_AREA_LSA:
1739 /* Update LSA origination count. */
1740 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001741 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001742
1743 /* Flood LSA through area. */
1744 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1745 break;
1746 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001747 {
paul99b7c5d2003-04-06 01:19:28 +00001748 struct ospf *ospf;
1749
1750 ospf = ospf_lookup();
1751 assert(ospf);
1752
paul7d5e2682003-04-05 19:41:07 +00001753 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001754
paul7d5e2682003-04-05 19:41:07 +00001755 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001756 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001757 break;
1758 }
paul2d33f152003-03-17 01:10:58 +00001759 }
1760}
1761
1762int
1763ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1764{
paul99b7c5d2003-04-06 01:19:28 +00001765 struct ospf *ospf;
1766
1767 ospf = ospf_lookup();
1768 assert(ospf);
1769
paul2d33f152003-03-17 01:10:58 +00001770 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001771 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001772 {
1773 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1774 return -1;
1775 }
1776
1777 /* Flood LSA within scope */
1778
1779#ifdef NOTYET
1780 /*
1781 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1782 * parameter, and thus it does not cause SIGSEGV error.
1783 */
1784 ospf_flood_through (NULL /*nbr */ , lsa);
1785#else /* NOTYET */
1786
1787 ospf_apiserver_flood_opaque_lsa (lsa);
1788#endif /* NOTYET */
1789
1790 return 0;
1791}
1792
1793
1794/* Opaque LSAs of type 9 on a specific interface can now be
1795 originated. Tell clients that registered type 9. */
1796int
1797ospf_apiserver_lsa9_originator (void *arg)
1798{
1799 struct ospf_interface *oi;
1800
1801 oi = (struct ospf_interface *) arg;
1802 if (listcount (apiserver_list) > 0) {
1803 ospf_apiserver_clients_notify_ready_type9 (oi);
1804 }
1805 return 0;
1806}
1807
1808int
1809ospf_apiserver_lsa10_originator (void *arg)
1810{
1811 struct ospf_area *area;
1812
1813 area = (struct ospf_area *) arg;
1814 if (listcount (apiserver_list) > 0) {
1815 ospf_apiserver_clients_notify_ready_type10 (area);
1816 }
1817 return 0;
1818}
1819
1820int
1821ospf_apiserver_lsa11_originator (void *arg)
1822{
1823 struct ospf *ospf;
1824
1825 ospf = (struct ospf *) arg;
1826 if (listcount (apiserver_list) > 0) {
1827 ospf_apiserver_clients_notify_ready_type11 (ospf);
1828 }
1829 return 0;
1830}
1831
1832
1833/* Periodically refresh opaque LSAs so that they do not expire in
1834 other routers. */
1835void
1836ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1837{
1838 struct ospf_apiserver *apiserv;
1839 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001840 struct ospf * ospf;
1841
1842 ospf = ospf_lookup();
1843 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001844
1845 apiserv = lookup_apiserver_by_lsa (lsa);
1846 if (!apiserv)
1847 {
1848 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1849 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1850 }
1851
1852 if (IS_LSA_MAXAGE (lsa))
1853 {
1854 ospf_opaque_lsa_flush_schedule (lsa);
1855 goto out;
1856 }
1857
1858 /* Check if updated version of LSA instance has already prepared. */
1859 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1860 if (!new)
1861 {
1862 /* This is a periodic refresh, driven by core OSPF mechanism. */
1863 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1864 if (!new)
1865 {
1866 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1867 goto out;
1868 }
1869 }
1870 else
1871 {
1872 /* This is a forcible refresh, requested by OSPF-API client. */
1873 ospf_lsdb_delete (&apiserv->reserve, new);
1874 new->lsdb = NULL;
1875 }
1876
1877 /* Increment sequence number */
1878 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1879
1880 /* New LSA is in same area. */
1881 new->area = lsa->area;
1882 SET_FLAG (new->flags, OSPF_LSA_SELF);
1883
1884 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001885 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001886 {
1887 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001888 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001889 goto out;
1890 }
1891
1892 /* Flood updated LSA through interface, area or AS */
1893
1894#ifdef NOTYET
1895 ospf_flood_through (NULL /*nbr */ , new);
1896#endif /* NOTYET */
1897 ospf_apiserver_flood_opaque_lsa (new);
1898
1899 /* Debug logging. */
1900 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1901 {
ajse84cc642004-12-08 17:28:56 +00001902 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
paul2d33f152003-03-17 01:10:58 +00001903 new->data->type, inet_ntoa (new->data->id));
1904 ospf_lsa_header_dump (new->data);
1905 }
1906
1907out:
1908 return;
1909}
1910
1911
1912/* -----------------------------------------------------------
1913 * Followings are functions to delete LSAs
1914 * -----------------------------------------------------------
1915 */
1916
1917int
1918ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1919 struct msg *msg)
1920{
1921 struct msg_delete_request *dmsg;
1922 struct ospf_lsa *old;
1923 struct ospf_area *area = NULL;
1924 struct in_addr id;
1925 int lsa_type, opaque_type;
1926 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001927 struct ospf * ospf;
1928
1929 ospf = ospf_lookup();
1930 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001931
1932 /* Extract opaque LSA from message */
1933 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1934
1935 /* Lookup area for link-local and area-local opaque LSAs */
1936 switch (dmsg->lsa_type)
1937 {
1938 case OSPF_OPAQUE_LINK_LSA:
1939 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001940 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001941 if (!area)
1942 {
1943 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1944 inet_ntoa (dmsg->area_id));
1945 rc = OSPF_API_NOSUCHAREA;
1946 goto out;
1947 }
1948 break;
1949 case OSPF_OPAQUE_AS_LSA:
1950 /* AS-external opaque LSAs have no designated area */
1951 area = NULL;
1952 break;
1953 default:
1954 zlog_warn
1955 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1956 dmsg->lsa_type);
1957 rc = OSPF_API_ILLEGALLSATYPE;
1958 goto out;
1959 }
1960
1961 /* Check if we registered this opaque type */
1962 lsa_type = dmsg->lsa_type;
1963 opaque_type = dmsg->opaque_type;
1964
1965 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1966 {
1967 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1968 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1969 goto out;
1970 }
1971
1972 /* opaque_id is in network byte order */
1973 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1974 ntohl (dmsg->opaque_id)));
1975
1976 /*
1977 * Even if the target LSA has once scheduled to flush, it remains in
1978 * the LSDB until it is finally handled by the maxage remover thread.
1979 * Therefore, the lookup function below may return non-NULL result.
1980 */
paul99b7c5d2003-04-06 01:19:28 +00001981 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001982 if (!old)
1983 {
1984 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1985 dmsg->lsa_type, inet_ntoa (id));
1986 rc = OSPF_API_NOSUCHLSA;
1987 goto out;
1988 }
1989
1990 /* Schedule flushing of LSA from LSDB */
1991 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1992 ospf_opaque_lsa_flush_schedule (old);
1993
1994out:
1995
1996 /* Send reply back to client including return code */
1997 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1998 return rc;
1999}
2000
2001/* Flush self-originated opaque LSA */
paul4dadc292005-05-06 21:37:42 +00002002static int
paul2d33f152003-03-17 01:10:58 +00002003apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2004 void *p_arg, int int_arg)
2005{
2006 struct param_t
2007 {
2008 struct ospf_apiserver *apiserv;
2009 u_char lsa_type;
2010 u_char opaque_type;
2011 }
2012 *param;
2013
2014 /* Sanity check */
2015 assert (lsa->data);
2016 assert (p_arg);
2017 param = (struct param_t *) p_arg;
2018
2019 /* If LSA matches type and opaque type then delete it */
2020 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2021 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2022 {
2023 ospf_opaque_lsa_flush_schedule (lsa);
2024 }
2025 return 0;
2026}
2027
2028/* Delete self-originated opaque LSAs of a given opaque type. This
2029 function is called when an application unregisters a given opaque
2030 type or a connection to an application closes and all those opaque
2031 LSAs need to be flushed the LSDB. */
2032void
2033ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2034 u_char lsa_type, u_char opaque_type)
2035{
2036 struct param_t
2037 {
2038 struct ospf_apiserver *apiserv;
2039 u_char lsa_type;
2040 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002041 } param;
paul1eb8ef22005-04-07 07:30:20 +00002042 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00002043 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002044 struct ospf_area *area;
2045
paul99b7c5d2003-04-06 01:19:28 +00002046 ospf = ospf_lookup();
2047 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002048
2049 /* Set parameter struct. */
2050 param.apiserv = apiserv;
2051 param.lsa_type = lsa_type;
2052 param.opaque_type = opaque_type;
2053
paul2d33f152003-03-17 01:10:58 +00002054 switch (lsa_type)
2055 {
paul99b7c5d2003-04-06 01:19:28 +00002056 struct route_node *rn;
2057 struct ospf_lsa *lsa;
2058
paul2d33f152003-03-17 01:10:58 +00002059 case OSPF_OPAQUE_LINK_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002060 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002061 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2062 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002063 break;
2064 case OSPF_OPAQUE_AREA_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002065 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002066 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2067 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002068 break;
2069 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002070 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2071 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002072 break;
2073 default:
2074 break;
2075 }
2076 return;
paul2d33f152003-03-17 01:10:58 +00002077}
2078
2079
2080/* -----------------------------------------------------------
2081 * Followings are callback functions to handle opaque types
2082 * -----------------------------------------------------------
2083 */
2084
2085int
2086ospf_apiserver_new_if (struct interface *ifp)
2087{
2088 struct ospf_interface *oi;
2089
2090 /* For some strange reason it seems possible that we are invoked
2091 with an interface that has no name. This seems to happen during
2092 initialization. Return if this happens */
2093
2094 if (ifp->name[0] == '\0') {
2095 /* interface has empty name */
2096 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2097 return 0;
2098 }
2099
2100 /* zlog_warn for debugging */
2101 zlog_warn ("ospf_apiserver_new_if");
2102 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2103 ifp->ifindex);
2104
2105 if (ifp->name[0] == '\0') {
2106 /* interface has empty name */
2107 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2108 return 0;
2109 }
2110
2111 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2112
2113 if (!oi) {
2114 /* This interface is known to Zebra but not to OSPF daemon yet. */
2115 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2116 ifp->name);
2117 return 0;
2118 }
2119
2120 assert (oi);
2121
2122 /* New interface added to OSPF, tell clients about it */
2123 if (listcount (apiserver_list) > 0) {
2124 ospf_apiserver_clients_notify_new_if (oi);
2125 }
2126 return 0;
2127}
2128
2129int
2130ospf_apiserver_del_if (struct interface *ifp)
2131{
2132 struct ospf_interface *oi;
2133
2134 /* zlog_warn for debugging */
2135 zlog_warn ("ospf_apiserver_del_if");
2136 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2137 ifp->ifindex);
2138
2139 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002140
2141 if (!oi) {
2142 /* This interface is known to Zebra but not to OSPF daemon
2143 anymore. No need to tell clients about it */
2144 return 0;
2145 }
paul2d33f152003-03-17 01:10:58 +00002146
2147 /* Interface deleted, tell clients about it */
2148 if (listcount (apiserver_list) > 0) {
2149 ospf_apiserver_clients_notify_del_if (oi);
2150 }
2151 return 0;
2152}
2153
2154void
2155ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2156{
2157 /* Tell clients about interface change */
2158
2159 /* zlog_warn for debugging */
2160 zlog_warn ("ospf_apiserver_ism_change");
2161 if (listcount (apiserver_list) > 0) {
2162 ospf_apiserver_clients_notify_ism_change (oi);
2163 }
2164
2165 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2166 zlog_warn ("old_state=%d", old_state);
2167 zlog_warn ("oi->state=%d", oi->state);
2168}
2169
2170void
2171ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2172{
2173 /* Neighbor status changed, tell clients about it */
2174 zlog_warn ("ospf_apiserver_nsm_change");
2175 if (listcount (apiserver_list) > 0) {
2176 ospf_apiserver_clients_notify_nsm_change (nbr);
2177 }
2178}
2179
2180void
2181ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2182{
2183 struct opaque_lsa
2184 {
2185 struct lsa_header header;
2186 u_char data[1]; /* opaque data have variable length. This is start
2187 address */
2188 };
2189 struct opaque_lsa *olsa;
2190 int opaquelen;
2191
2192 olsa = (struct opaque_lsa *) lsa->data;
2193
2194 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002195 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002196 else
paul87d6f872004-09-24 08:01:38 +00002197 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002198
2199 /* Output information about opaque LSAs */
2200 if (vty != NULL)
2201 {
2202 int i;
2203 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2204 opaquelen,
2205 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2206 VTY_NEWLINE);
2207 vty_out (vty, " Opaque data: ");
2208
2209 for (i = 0; i < opaquelen; i++)
2210 {
2211 vty_out (vty, "0x%x ", olsa->data[i]);
2212 }
2213 vty_out (vty, "%s", VTY_NEWLINE);
2214 }
2215 else
2216 {
2217 int i;
ajse84cc642004-12-08 17:28:56 +00002218 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
paul2d33f152003-03-17 01:10:58 +00002219 opaquelen,
2220 VALID_OPAQUE_INFO_LEN (lsa->
2221 data) ? "" : "(Invalid length?)");
ajse84cc642004-12-08 17:28:56 +00002222 zlog_debug (" Opaque data: ");
paul2d33f152003-03-17 01:10:58 +00002223
2224 for (i = 0; i < opaquelen; i++)
2225 {
ajse84cc642004-12-08 17:28:56 +00002226 zlog_debug ("0x%x ", olsa->data[i]);
paul2d33f152003-03-17 01:10:58 +00002227 }
ajse84cc642004-12-08 17:28:56 +00002228 zlog_debug ("\n");
paul2d33f152003-03-17 01:10:58 +00002229 }
2230 return;
2231}
2232
2233/* -----------------------------------------------------------
2234 * Followings are functions to notify clients about events
2235 * -----------------------------------------------------------
2236 */
2237
2238/* Send a message to all clients. This is useful for messages
2239 that need to be notified to all clients (such as interface
2240 changes) */
2241
2242void
2243ospf_apiserver_clients_notify_all (struct msg *msg)
2244{
paul1eb8ef22005-04-07 07:30:20 +00002245 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002246 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002247
2248 /* Send message to all clients */
paul1eb8ef22005-04-07 07:30:20 +00002249 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul87d6f872004-09-24 08:01:38 +00002250 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002251}
2252
2253/* An interface is now ready to accept opaque LSAs. Notify all
2254 clients that registered to use this opaque type */
2255void
2256ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2257{
paul1eb8ef22005-04-07 07:30:20 +00002258 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002259 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002260 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002261
2262 assert (oi);
2263 if (!oi->address)
2264 {
2265 zlog_warn ("Interface has no address?");
2266 return;
2267 }
2268
2269 if (!ospf_apiserver_is_ready_type9 (oi))
2270 {
2271 zlog_warn ("Interface not ready for type 9?");
2272 return;
2273 }
2274
paul1eb8ef22005-04-07 07:30:20 +00002275 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002276 {
paul1eb8ef22005-04-07 07:30:20 +00002277 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002278 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002279
paul1eb8ef22005-04-07 07:30:20 +00002280 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002281 {
paul2d33f152003-03-17 01:10:58 +00002282 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2283 {
2284 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2285 r->opaque_type,
2286 oi->address->u.prefix4);
2287 if (!msg)
2288 {
2289 zlog_warn
2290 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2291#ifdef NOTYET
2292 /* Cannot allocate new message. What should we do? */
2293 ospf_apiserver_free (apiserv);
2294#endif
2295 goto out;
2296 }
2297
2298 ospf_apiserver_send_msg (apiserv, msg);
2299 msg_free (msg);
2300 }
2301 }
2302 }
2303
2304out:
2305 return;
2306}
2307
2308void
2309ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2310{
paul1eb8ef22005-04-07 07:30:20 +00002311 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002312 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002313 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002314
2315 assert (area);
2316
2317 if (!ospf_apiserver_is_ready_type10 (area))
2318 {
2319 zlog_warn ("Area not ready for type 10?");
2320 return;
2321 }
2322
paul1eb8ef22005-04-07 07:30:20 +00002323 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002324 {
paul1eb8ef22005-04-07 07:30:20 +00002325 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002326 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002327
paul1eb8ef22005-04-07 07:30:20 +00002328 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002329 {
paul2d33f152003-03-17 01:10:58 +00002330 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2331 {
2332 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2333 r->opaque_type, area->area_id);
2334 if (!msg)
2335 {
2336 zlog_warn
2337 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2338#ifdef NOTYET
2339 /* Cannot allocate new message. What should we do? */
2340 ospf_apiserver_free (apiserv);
2341#endif
paul87d6f872004-09-24 08:01:38 +00002342 goto out;
paul2d33f152003-03-17 01:10:58 +00002343 }
2344
2345 ospf_apiserver_send_msg (apiserv, msg);
2346 msg_free (msg);
2347 }
2348 }
2349 }
2350
2351out:
2352 return;
2353}
2354
2355
2356void
2357ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2358{
paul1eb8ef22005-04-07 07:30:20 +00002359 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002360 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002361 struct in_addr id_null = { .s_addr = 0L };
paul87d6f872004-09-24 08:01:38 +00002362 struct ospf_apiserver *apiserv;
paul36238142005-10-11 04:12:54 +00002363
paul2d33f152003-03-17 01:10:58 +00002364 assert (top);
paul36238142005-10-11 04:12:54 +00002365
paul2d33f152003-03-17 01:10:58 +00002366 if (!ospf_apiserver_is_ready_type11 (top))
2367 {
2368 zlog_warn ("AS not ready for type 11?");
2369 return;
2370 }
2371
paul1eb8ef22005-04-07 07:30:20 +00002372 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002373 {
paul1eb8ef22005-04-07 07:30:20 +00002374 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002375 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002376
paul1eb8ef22005-04-07 07:30:20 +00002377 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002378 {
paul2d33f152003-03-17 01:10:58 +00002379 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2380 {
2381 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2382 r->opaque_type, id_null);
2383 if (!msg)
2384 {
2385 zlog_warn
2386 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2387#ifdef NOTYET
2388 /* Cannot allocate new message. What should we do? */
2389 ospf_apiserver_free (apiserv);
2390#endif
2391 goto out;
2392 }
2393
2394 ospf_apiserver_send_msg (apiserv, msg);
2395 msg_free (msg);
2396 }
2397 }
2398 }
2399
2400out:
2401 return;
2402}
2403
2404void
2405ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2406{
2407 struct msg *msg;
2408
2409 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2410 if (msg != NULL)
2411 {
2412 ospf_apiserver_clients_notify_all (msg);
2413 msg_free (msg);
2414 }
2415}
2416
2417void
2418ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2419{
2420 struct msg *msg;
2421
2422 msg = new_msg_del_if (0, oi->address->u.prefix4);
2423 if (msg != NULL)
2424 {
2425 ospf_apiserver_clients_notify_all (msg);
2426 msg_free (msg);
2427 }
2428}
2429
2430void
2431ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2432{
2433 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002434 struct in_addr ifaddr = { .s_addr = 0L };
2435 struct in_addr area_id = { .s_addr = 0L };
2436
paul2d33f152003-03-17 01:10:58 +00002437 assert (oi);
2438 assert (oi->ifp);
paul36238142005-10-11 04:12:54 +00002439
paul2d33f152003-03-17 01:10:58 +00002440 if (oi->address)
2441 {
2442 ifaddr = oi->address->u.prefix4;
2443 }
2444 if (oi->area)
2445 {
2446 area_id = oi->area->area_id;
2447 }
2448
hasso1ddd7292005-06-07 19:54:04 +00002449 msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
paul2d33f152003-03-17 01:10:58 +00002450 if (!msg)
2451 {
2452 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2453 return;
2454 }
2455
2456 ospf_apiserver_clients_notify_all (msg);
2457 msg_free (msg);
2458}
2459
2460void
2461ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2462{
2463 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002464 struct in_addr ifaddr = { .s_addr = 0L };
2465 struct in_addr nbraddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002466
2467 assert (nbr);
2468
2469 if (nbr->oi)
2470 {
2471 ifaddr = nbr->oi->address->u.prefix4;
2472 }
2473
2474 nbraddr = nbr->address.u.prefix4;
2475
2476 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2477 if (!msg)
2478 {
2479 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2480 return;
2481 }
2482
2483 ospf_apiserver_clients_notify_all (msg);
2484 msg_free (msg);
2485}
2486
paul4dadc292005-05-06 21:37:42 +00002487static void
paul2d33f152003-03-17 01:10:58 +00002488apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2489{
2490 struct msg *msg;
paul1eb8ef22005-04-07 07:30:20 +00002491 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002492 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002493
2494 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002495 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002496
2497 /* Default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002498 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002499
2500 if (lsa->area)
2501 {
2502 area_id = lsa->area->area_id;
2503 }
2504 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2505 {
2506 assert (lsa->oi);
2507 ifaddr = lsa->oi->address->u.prefix4;
2508 }
2509
2510 /* Prepare message that can be sent to clients that have a matching
2511 filter */
2512 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2513 ifaddr, area_id,
2514 lsa->flags & OSPF_LSA_SELF, lsa->data);
2515 if (!msg)
2516 {
2517 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2518 return;
2519 }
2520
2521 /* Now send message to all clients with a matching filter */
paul1eb8ef22005-04-07 07:30:20 +00002522 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002523 {
paul2d33f152003-03-17 01:10:58 +00002524 struct lsa_filter_type *filter;
2525 u_int16_t mask;
2526 u_int32_t *area;
2527 int i;
2528
2529 /* Check filter for this client. */
2530 filter = apiserv->filter;
2531
2532 /* Check area IDs in case of non AS-E LSAs.
2533 * If filter has areas (num_areas > 0),
2534 * then one of the areas must match the area ID of this LSA. */
2535
2536 i = filter->num_areas;
2537 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2538 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2539 {
2540 i = 0;
2541 }
2542
2543 if (i > 0)
2544 {
2545 area = (u_int32_t *) (filter + 1);
2546 while (i)
2547 {
2548 if (*area == area_id.s_addr)
2549 {
2550 break;
2551 }
2552 i--;
2553 area++;
2554 }
2555 }
2556 else
2557 {
2558 i = 1;
2559 }
2560
2561 if (i > 0)
2562 {
2563 /* Area match. Check LSA type. */
2564 mask = ntohs (filter->typemask);
2565
2566 if (mask & Power2[lsa->data->type])
2567 {
2568 /* Type also matches. Check origin. */
2569 if ((filter->origin == ANY_ORIGIN) ||
2570 (filter->origin == IS_LSA_SELF (lsa)))
2571 {
2572 ospf_apiserver_send_msg (apiserv, msg);
2573 }
2574 }
2575 }
2576 }
2577 /* Free message since it is not used anymore */
2578 msg_free (msg);
2579}
2580
2581
2582/* -------------------------------------------------------------
2583 * Followings are hooks invoked when LSAs are updated or deleted
2584 * -------------------------------------------------------------
2585 */
2586
2587
paul4dadc292005-05-06 21:37:42 +00002588static int
paul2d33f152003-03-17 01:10:58 +00002589apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2590{
2591 struct msg *msg;
2592 /* default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002593 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002594
2595 /* default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002596 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002597
2598 /* Only notify this update if the LSA's age is smaller than
2599 MAXAGE. Otherwise clients would see LSA updates with max age just
2600 before they are deleted from the LSDB. LSA delete messages have
2601 MAXAGE too but should not be filtered. */
2602 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2603 return 0;
2604 }
2605
2606 if (lsa->area)
2607 {
2608 area_id = lsa->area->area_id;
2609 }
2610 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2611 {
2612 ifaddr = lsa->oi->address->u.prefix4;
2613 }
2614 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2615 ifaddr, area_id,
2616 lsa->flags & OSPF_LSA_SELF, lsa->data);
2617 if (!msg)
2618 {
2619 zlog_warn ("notify_clients_lsa: msg_new failed");
2620 return -1;
2621 }
2622 /* Notify all clients that new LSA is added/updated */
2623 apiserver_clients_lsa_change_notify (msgtype, lsa);
2624
2625 /* Clients made their own copies of msg so we can free msg here */
2626 msg_free (msg);
2627
2628 return 0;
2629}
2630
2631int
2632ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2633{
2634 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2635}
2636
2637int
2638ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2639{
2640 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2641}
2642
2643#endif /* SUPPORT_OSPF_API */
2644