blob: 84d70ccc1bb9ca680d67313b0c5998b5c2a62309 [file] [log] [blame]
paul2d33f152003-03-17 01:10:58 +00001/*
2 * Server side of OSPF API.
3 * Copyright (C) 2001, 2002 Ralph Keller
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#ifdef SUPPORT_OSPF_API
26#ifndef HAVE_OPAQUE_LSA
27#error "Core Opaque-LSA module must be configured."
28#endif /* HAVE_OPAQUE_LSA */
29
30#include "linklist.h"
31#include "prefix.h"
32#include "if.h"
33#include "table.h"
34#include "memory.h"
35#include "command.h"
36#include "vty.h"
37#include "stream.h"
38#include "log.h"
39#include "thread.h"
40#include "hash.h"
41#include "sockunion.h" /* for inet_aton() */
42#include "buffer.h"
43
44#include <sys/types.h>
45
46#include "ospfd/ospfd.h" /* for "struct thread_master" */
47#include "ospfd/ospf_interface.h"
48#include "ospfd/ospf_ism.h"
49#include "ospfd/ospf_asbr.h"
50#include "ospfd/ospf_lsa.h"
51#include "ospfd/ospf_lsdb.h"
52#include "ospfd/ospf_neighbor.h"
53#include "ospfd/ospf_nsm.h"
54#include "ospfd/ospf_flood.h"
55#include "ospfd/ospf_packet.h"
56#include "ospfd/ospf_spf.h"
57#include "ospfd/ospf_dump.h"
58#include "ospfd/ospf_route.h"
59#include "ospfd/ospf_ase.h"
60#include "ospfd/ospf_zebra.h"
61
62#include "ospfd/ospf_api.h"
63#include "ospfd/ospf_apiserver.h"
64
65/* This is an implementation of an API to the OSPF daemon that allows
66 * external applications to access the OSPF daemon through socket
67 * connections. The application can use this API to inject its own
68 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
69 * daemons then receive these LSAs and inform applications through the
70 * API by sending a corresponding message. The application can also
71 * register to receive all LSA types (in addition to opaque types) and
72 * use this information to reconstruct the OSPF's LSDB. The OSPF
73 * daemon supports multiple applications concurrently. */
74
75/* List of all active connections. */
paul87d6f872004-09-24 08:01:38 +000076struct list *apiserver_list;
paul2d33f152003-03-17 01:10:58 +000077
78/* -----------------------------------------------------------
79 * Functions to lookup interfaces
80 * -----------------------------------------------------------
81 */
82
83struct ospf_interface *
84ospf_apiserver_if_lookup_by_addr (struct in_addr address)
85{
paul1eb8ef22005-04-07 07:30:20 +000086 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +000087 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +000088 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +000089
paulafbacce2003-07-09 16:09:20 +000090 if (!(ospf = ospf_lookup ()))
paul5549c6b2003-07-09 15:46:33 +000091 return NULL;
paul99b7c5d2003-04-06 01:19:28 +000092
paul1eb8ef22005-04-07 07:30:20 +000093 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +000094 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
95 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
96 return oi;
97
paul2d33f152003-03-17 01:10:58 +000098 return NULL;
99}
100
101struct ospf_interface *
102ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
103{
paul1eb8ef22005-04-07 07:30:20 +0000104 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +0000105 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +0000106 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000107
Hasso Tepper8c9ed272012-10-11 11:15:18 +0000108 if (!(ospf = ospf_lookup ()))
paul5549c6b2003-07-09 15:46:33 +0000109 return NULL;
paul99b7c5d2003-04-06 01:19:28 +0000110
paul1eb8ef22005-04-07 07:30:20 +0000111 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +0000112 if (oi->ifp == ifp)
113 return oi;
114
paul2d33f152003-03-17 01:10:58 +0000115 return NULL;
116}
117
118/* -----------------------------------------------------------
119 * Initialization
120 * -----------------------------------------------------------
121 */
122
123unsigned short
124ospf_apiserver_getport (void)
125{
126 struct servent *sp = getservbyname ("ospfapi", "tcp");
127
128 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
129}
130
131/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
132int
133ospf_apiserver_init (void)
134{
135 int fd;
136 int rc = -1;
137
138 /* Create new socket for synchronous messages. */
139 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
140
141 if (fd < 0)
142 goto out;
143
144 /* Schedule new thread that handles accepted connections. */
145 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
146
147 /* Initialize list that keeps track of all connections. */
148 apiserver_list = list_new ();
149
150 /* Register opaque-independent call back functions. These functions
151 are invoked on ISM, NSM changes and LSA update and LSA deletes */
152 rc =
153 ospf_register_opaque_functab (0 /* all LSAs */,
154 0 /* all opaque types */,
155 ospf_apiserver_new_if,
156 ospf_apiserver_del_if,
157 ospf_apiserver_ism_change,
158 ospf_apiserver_nsm_change,
159 NULL,
160 NULL,
161 NULL,
162 NULL, /* ospf_apiserver_show_info */
163 NULL, /* originator_func */
164 NULL, /* ospf_apiserver_lsa_refresher */
165 ospf_apiserver_lsa_update,
166 ospf_apiserver_lsa_delete);
167 if (rc != 0)
168 {
169 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
170 }
171
172 rc = 0;
173
174out:
175 return rc;
176}
177
178/* Terminate OSPF API module. */
179void
180ospf_apiserver_term (void)
181{
paul87d6f872004-09-24 08:01:38 +0000182 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +0000183
184 /* Unregister wildcard [0/0] type */
185 ospf_delete_opaque_functab (0 /* all LSAs */,
186 0 /* all opaque types */);
187
gdt3fb9de72004-12-09 16:30:04 +0000188 /*
189 * Free all client instances. ospf_apiserver_free removes the node
190 * from the list, so we examine the head of the list anew each time.
191 */
paule029d442005-10-23 15:26:24 +0000192 while ( apiserver_list &&
193 (apiserv = listgetdata (listhead (apiserver_list))) != NULL)
paul87d6f872004-09-24 08:01:38 +0000194 ospf_apiserver_free (apiserv);
paul2d33f152003-03-17 01:10:58 +0000195
196 /* Free client list itself */
paule029d442005-10-23 15:26:24 +0000197 if (apiserver_list)
198 list_delete (apiserver_list);
paul2d33f152003-03-17 01:10:58 +0000199
200 /* Free wildcard list */
201 /* XXX */
202}
203
204static struct ospf_apiserver *
205lookup_apiserver (u_char lsa_type, u_char opaque_type)
206{
paul87d6f872004-09-24 08:01:38 +0000207 struct listnode *n1, *n2;
paul2d33f152003-03-17 01:10:58 +0000208 struct registered_opaque_type *r;
209 struct ospf_apiserver *apiserv, *found = NULL;
210
paul87d6f872004-09-24 08:01:38 +0000211 /* XXX: this approaches O(n**2) */
paul1eb8ef22005-04-07 07:30:20 +0000212 for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv))
paul2d33f152003-03-17 01:10:58 +0000213 {
paul1eb8ef22005-04-07 07:30:20 +0000214 for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r))
215 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
216 {
217 found = apiserv;
218 goto out;
219 }
paul2d33f152003-03-17 01:10:58 +0000220 }
221out:
222 return found;
223}
224
225static struct ospf_apiserver *
226lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
227{
228 struct lsa_header *lsah = lsa->data;
229 struct ospf_apiserver *found = NULL;
230
231 if (IS_OPAQUE_LSA (lsah->type))
232 {
233 found = lookup_apiserver (lsah->type,
234 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
235 }
236 return found;
237}
238
239/* -----------------------------------------------------------
240 * Followings are functions to manage client connections.
241 * -----------------------------------------------------------
242 */
243static int
244ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
245{
246 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000247 zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
paul2d33f152003-03-17 01:10:58 +0000248 return 0;
249}
250
251static int
252ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
253{
254 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000255 zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
paul2d33f152003-03-17 01:10:58 +0000256 return 0;
257}
258
259/* Allocate new connection structure. */
260struct ospf_apiserver *
261ospf_apiserver_new (int fd_sync, int fd_async)
262{
263 struct ospf_apiserver *new =
264 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
265
266 new->filter =
267 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
268
269 new->fd_sync = fd_sync;
270 new->fd_async = fd_async;
271
272 /* list of registered opaque types that application uses */
273 new->opaque_types = list_new ();
274
275 /* Initialize temporary strage for LSA instances to be refreshed. */
276 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
277 ospf_lsdb_init (&new->reserve);
278
279 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
280 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
281
282 new->out_sync_fifo = msg_fifo_new ();
283 new->out_async_fifo = msg_fifo_new ();
284 new->t_sync_read = NULL;
285#ifdef USE_ASYNC_READ
286 new->t_async_read = NULL;
287#endif /* USE_ASYNC_READ */
288 new->t_sync_write = NULL;
289 new->t_async_write = NULL;
290
291 new->filter->typemask = 0; /* filter all LSAs */
292 new->filter->origin = ANY_ORIGIN;
293 new->filter->num_areas = 0;
294
295 return new;
296}
297
298void
299ospf_apiserver_event (enum event event, int fd,
300 struct ospf_apiserver *apiserv)
301{
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 =
Stephen Hemminger393deb92008-08-18 14:13:29 -0700940 XCALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
paul2d33f152003-03-17 01:10:58 +0000941 regtype->lsa_type = lsa_type;
942 regtype->opaque_type = opaque_type;
943
944 /* Add to list of registered opaque types */
945 listnode_add (apiserv->opaque_types, regtype);
946
947 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000948 zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
paul87d6f872004-09-24 08:01:38 +0000949 " apiserv(%p), total#(%d)",
950 lsa_type, opaque_type, apiserv,
951 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000952
953 return 0;
954}
955
956int
957ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
958 u_char lsa_type, u_char opaque_type)
959{
paul1eb8ef22005-04-07 07:30:20 +0000960 struct listnode *node, *nnode;
gdt54ade992004-10-07 19:38:20 +0000961 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000962
paul1eb8ef22005-04-07 07:30:20 +0000963 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +0000964 {
paul2d33f152003-03-17 01:10:58 +0000965 /* Check if we really registered this opaque type */
966 if (regtype->lsa_type == lsa_type &&
967 regtype->opaque_type == opaque_type)
968 {
969
970 /* Yes, we registered this opaque type. Flush
971 all existing opaque LSAs of this type */
972
973 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
974 ospf_delete_opaque_functab (lsa_type, opaque_type);
975
976 /* Remove from list of registered opaque types */
977 listnode_delete (apiserv->opaque_types, regtype);
978
979 if (IS_DEBUG_OSPF_EVENT)
ajse84cc642004-12-08 17:28:56 +0000980 zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
paul87d6f872004-09-24 08:01:38 +0000981 " from apiserv(%p), total#(%d)",
982 lsa_type, opaque_type, apiserv,
983 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000984
985 return 0;
986 }
987 }
988
989 /* Opaque type is not registered */
990 zlog_warn ("Failed to unregister opaque type [%d/%d]",
991 lsa_type, opaque_type);
992 return OSPF_API_OPAQUETYPENOTREGISTERED;
993}
994
995
paul4dadc292005-05-06 21:37:42 +0000996static int
paul2d33f152003-03-17 01:10:58 +0000997apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
998 u_char lsa_type, u_char opaque_type)
999{
paul1eb8ef22005-04-07 07:30:20 +00001000 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001001 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001002
paul87d6f872004-09-24 08:01:38 +00001003 /* XXX: how many types are there? if few, why not just a bitmap? */
paul1eb8ef22005-04-07 07:30:20 +00001004 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
paul2d33f152003-03-17 01:10:58 +00001005 {
paul2d33f152003-03-17 01:10:58 +00001006 /* Check if we really registered this opaque type */
1007 if (regtype->lsa_type == lsa_type &&
1008 regtype->opaque_type == opaque_type)
1009 {
1010 /* Yes registered */
1011 return 1;
1012 }
1013 }
1014 /* Not registered */
1015 return 0;
1016}
1017
1018int
1019ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1020 struct msg *msg)
1021{
1022 struct msg_register_opaque_type *rmsg;
1023 u_char lsa_type;
1024 u_char opaque_type;
1025 int rc = 0;
1026
1027 /* Extract parameters from register opaque type message */
1028 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1029
1030 lsa_type = rmsg->lsatype;
1031 opaque_type = rmsg->opaquetype;
1032
1033 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1034
1035 /* Send a reply back to client including return code */
1036 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1037 if (rc < 0)
1038 goto out;
1039
1040 /* Now inform application about opaque types that are ready */
1041 switch (lsa_type)
1042 {
1043 case OSPF_OPAQUE_LINK_LSA:
1044 ospf_apiserver_notify_ready_type9 (apiserv);
1045 break;
1046 case OSPF_OPAQUE_AREA_LSA:
1047 ospf_apiserver_notify_ready_type10 (apiserv);
1048 break;
1049 case OSPF_OPAQUE_AS_LSA:
1050 ospf_apiserver_notify_ready_type11 (apiserv);
1051 break;
1052 }
1053out:
1054 return rc;
1055}
1056
1057
1058/* Notify specific client about all opaque types 9 that are ready. */
1059void
1060ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1061{
paul1eb8ef22005-04-07 07:30:20 +00001062 struct listnode *node, *nnode;
1063 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001064 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001065 struct ospf_interface *oi;
1066 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001067
paul99b7c5d2003-04-06 01:19:28 +00001068 ospf = ospf_lookup ();
1069
paul1eb8ef22005-04-07 07:30:20 +00001070 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul2d33f152003-03-17 01:10:58 +00001071 {
paul2d33f152003-03-17 01:10:58 +00001072 /* Check if this interface is indeed ready for type 9 */
1073 if (!ospf_apiserver_is_ready_type9 (oi))
1074 continue;
1075
1076 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001077 /* XXX: loop-de-loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001078 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001079 {
paul2d33f152003-03-17 01:10:58 +00001080 struct msg *msg;
1081
1082 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1083 {
1084
1085 /* Yes, this opaque type is ready */
1086 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1087 r->opaque_type,
1088 oi->address->u.prefix4);
1089 if (!msg)
1090 {
1091 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1092#ifdef NOTYET
1093 /* Cannot allocate new message. What should we do? */
1094 ospf_apiserver_free (apiserv);
1095#endif
1096 goto out;
1097 }
1098 ospf_apiserver_send_msg (apiserv, msg);
1099 msg_free (msg);
1100 }
1101 }
1102 }
1103
1104out:
1105 return;
1106}
1107
1108
1109/* Notify specific client about all opaque types 10 that are ready. */
1110void
1111ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1112{
paul1eb8ef22005-04-07 07:30:20 +00001113 struct listnode *node, *nnode;
1114 struct listnode *node2, *nnode2;
paul99b7c5d2003-04-06 01:19:28 +00001115 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001116 struct ospf_area *area;
1117
paul99b7c5d2003-04-06 01:19:28 +00001118 ospf = ospf_lookup ();
1119
paul1eb8ef22005-04-07 07:30:20 +00001120 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001121 {
paul87d6f872004-09-24 08:01:38 +00001122 struct registered_opaque_type *r;
1123
paul2d33f152003-03-17 01:10:58 +00001124 if (!ospf_apiserver_is_ready_type10 (area))
1125 {
1126 continue;
1127 }
1128
1129 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001130 /* XXX: loop in loop - optimise me */
paul1eb8ef22005-04-07 07:30:20 +00001131 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00001132 {
paul2d33f152003-03-17 01:10:58 +00001133 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001134
paul2d33f152003-03-17 01:10:58 +00001135 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1136 {
1137 /* Yes, this opaque type is ready */
1138 msg =
1139 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1140 r->opaque_type, area->area_id);
1141 if (!msg)
1142 {
1143 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1144#ifdef NOTYET
1145 /* Cannot allocate new message. What should we do? */
1146 ospf_apiserver_free (apiserv);
1147#endif
1148 goto out;
1149 }
1150 ospf_apiserver_send_msg (apiserv, msg);
1151 msg_free (msg);
1152 }
1153 }
1154 }
1155
1156out:
1157 return;
1158}
1159
1160/* Notify specific client about all opaque types 11 that are ready */
1161void
1162ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1163{
paul1eb8ef22005-04-07 07:30:20 +00001164 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00001165 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001166 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001167
1168 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001169
1170 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001171 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001172 goto out;
paul2d33f152003-03-17 01:10:58 +00001173
1174 /* Check for registered opaque type 11 types */
paul1eb8ef22005-04-07 07:30:20 +00001175 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
paul2d33f152003-03-17 01:10:58 +00001176 {
paul2d33f152003-03-17 01:10:58 +00001177 struct msg *msg;
paul36238142005-10-11 04:12:54 +00001178 struct in_addr noarea_id = { .s_addr = 0L };
1179
paul2d33f152003-03-17 01:10:58 +00001180 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1181 {
1182 /* Yes, this opaque type is ready */
1183 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1184 r->opaque_type, noarea_id);
1185
1186 if (!msg)
1187 {
1188 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1189#ifdef NOTYET
1190 /* Cannot allocate new message. What should we do? */
1191 ospf_apiserver_free (apiserv);
1192#endif
1193 goto out;
1194 }
1195 ospf_apiserver_send_msg (apiserv, msg);
1196 msg_free (msg);
1197 }
1198 }
1199
1200out:
1201 return;
1202}
1203
1204int
1205ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1206 struct msg *msg)
1207{
1208 struct msg_unregister_opaque_type *umsg;
1209 u_char ltype;
1210 u_char otype;
1211 int rc = 0;
1212
1213 /* Extract parameters from unregister opaque type message */
1214 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1215
1216 ltype = umsg->lsatype;
1217 otype = umsg->opaquetype;
1218
1219 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1220
1221 /* Send a reply back to client including return code */
1222 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1223
1224 return rc;
1225}
1226
1227
1228/* -----------------------------------------------------------
1229 * Following are functions for event (filter) registration.
1230 * -----------------------------------------------------------
1231 */
1232int
1233ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1234 struct msg *msg)
1235{
1236 struct msg_register_event *rmsg;
1237 int rc;
1238 u_int32_t seqnum;
1239
1240 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1241
1242 /* Get request sequence number */
1243 seqnum = msg_get_seq (msg);
1244
1245 /* Free existing filter in apiserv. */
1246 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1247 /* Alloc new space for filter. */
1248
1249 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1250 ntohs (msg->hdr.msglen));
1251 if (apiserv->filter)
1252 {
1253 /* copy it over. */
1254 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1255 rc = OSPF_API_OK;
1256 }
1257 else
1258 {
1259 rc = OSPF_API_NOMEMORY;
1260 }
1261 /* Send a reply back to client with return code */
1262 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1263 return rc;
1264}
1265
1266
1267/* -----------------------------------------------------------
1268 * Followings are functions for LSDB synchronization.
1269 * -----------------------------------------------------------
1270 */
1271
paul4dadc292005-05-06 21:37:42 +00001272static int
paul2d33f152003-03-17 01:10:58 +00001273apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1274{
1275 struct ospf_apiserver *apiserv;
1276 int seqnum;
1277 struct msg *msg;
1278 struct param_t
1279 {
1280 struct ospf_apiserver *apiserv;
1281 struct lsa_filter_type *filter;
1282 }
1283 *param;
1284 int rc = -1;
1285
1286 /* Sanity check */
1287 assert (lsa->data);
1288 assert (p_arg);
1289
1290 param = (struct param_t *) p_arg;
1291 apiserv = param->apiserv;
1292 seqnum = (u_int32_t) int_arg;
1293
1294 /* Check origin in filter. */
1295 if ((param->filter->origin == ANY_ORIGIN) ||
1296 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1297 {
1298
1299 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00001300 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00001301
1302 /* Default interface for non Opaque9 LSAs */
paul484315f2005-11-03 09:08:29 +00001303 struct in_addr ifaddr = { .s_addr = 0L };
paul36238142005-10-11 04:12:54 +00001304
paul2d33f152003-03-17 01:10:58 +00001305 if (lsa->area)
1306 {
1307 area_id = lsa->area->area_id;
1308 }
1309 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1310 {
1311 ifaddr = lsa->oi->address->u.prefix4;
1312 }
1313
1314 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1315 seqnum,
1316 ifaddr, area_id,
1317 lsa->flags & OSPF_LSA_SELF, lsa->data);
1318 if (!msg)
1319 {
1320 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1321#ifdef NOTYET
1322 /* Cannot allocate new message. What should we do? */
1323/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1324#endif
1325 goto out;
1326 }
1327
1328 /* Send LSA */
1329 ospf_apiserver_send_msg (apiserv, msg);
1330 msg_free (msg);
1331 }
1332 rc = 0;
1333
1334out:
1335 return rc;
1336}
1337
1338int
1339ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1340 struct msg *msg)
1341{
paul1eb8ef22005-04-07 07:30:20 +00001342 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00001343 u_int32_t seqnum;
1344 int rc = 0;
1345 struct msg_sync_lsdb *smsg;
paul1eb8ef22005-04-07 07:30:20 +00001346 struct ospf_apiserver_param_t
paul2d33f152003-03-17 01:10:58 +00001347 {
1348 struct ospf_apiserver *apiserv;
1349 struct lsa_filter_type *filter;
paul1eb8ef22005-04-07 07:30:20 +00001350 } param;
paul2d33f152003-03-17 01:10:58 +00001351 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001352 struct route_node *rn;
1353 struct ospf_lsa *lsa;
1354 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001355 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001356
1357 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001358
1359 /* Get request sequence number */
1360 seqnum = msg_get_seq (msg);
1361 /* Set sync msg. */
1362 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1363
1364 /* Set parameter struct. */
1365 param.apiserv = apiserv;
1366 param.filter = &smsg->filter;
1367
1368 /* Remember mask. */
1369 mask = ntohs (smsg->filter.typemask);
1370
1371 /* Iterate over all areas. */
paul1eb8ef22005-04-07 07:30:20 +00001372 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul2d33f152003-03-17 01:10:58 +00001373 {
paul2d33f152003-03-17 01:10:58 +00001374 int i;
1375 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001376
paul2d33f152003-03-17 01:10:58 +00001377 /* Compare area_id with area_ids in sync request. */
1378 if ((i = smsg->filter.num_areas) > 0)
1379 {
1380 /* Let area_id point to the list of area IDs,
1381 * which is at the end of smsg->filter. */
1382 area_id = (u_int32_t *) (&smsg->filter + 1);
1383 while (i)
1384 {
1385 if (*area_id == area->area_id.s_addr)
1386 {
1387 break;
1388 }
1389 i--;
1390 area_id++;
1391 }
1392 }
1393 else
1394 {
1395 i = 1;
1396 }
1397
1398 /* If area was found, then i>0 here. */
1399 if (i)
1400 {
1401 /* Check msg type. */
1402 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001403 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1404 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001405 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001406 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1407 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001408 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001409 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1410 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001411 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001412 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1413 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001414 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001415 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1416 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001417 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001418 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1419 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001420 }
1421 }
1422
1423 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001424 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001425 {
1426 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001427 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1428 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001429 }
1430
1431 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001432 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001433 {
1434 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001435 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1436 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001437 }
1438
1439 /* Send a reply back to client with return code */
1440 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1441 return rc;
1442}
1443
1444
1445/* -----------------------------------------------------------
1446 * Followings are functions to originate or update LSA
1447 * from an application.
1448 * -----------------------------------------------------------
1449 */
1450
1451/* Create a new internal opaque LSA by taking prototype and filling in
1452 missing fields such as age, sequence number, advertising router,
1453 checksum and so on. The interface parameter is used for type 9
1454 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1455 nor interface. */
1456
1457struct ospf_lsa *
1458ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1459 struct ospf_interface *oi,
1460 struct lsa_header *protolsa)
1461{
1462 struct stream *s;
1463 struct lsa_header *newlsa;
1464 struct ospf_lsa *new = NULL;
1465 u_char options = 0x0;
1466 u_int16_t length;
1467
paul99b7c5d2003-04-06 01:19:28 +00001468 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001469
paul99b7c5d2003-04-06 01:19:28 +00001470 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001471 assert(ospf);
1472
paul2d33f152003-03-17 01:10:58 +00001473 /* Create a stream for internal opaque LSA */
1474 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1475 {
1476 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1477 return NULL;
1478 }
1479
1480 newlsa = (struct lsa_header *) STREAM_DATA (s);
1481
1482 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1483 have to set options? */
1484
1485 if (area)
1486 {
1487 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001488 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001489 }
1490
1491 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1492
1493 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1494 {
ajse84cc642004-12-08 17:28:56 +00001495 zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
paul2d33f152003-03-17 01:10:58 +00001496 protolsa->type, inet_ntoa (protolsa->id));
1497 }
1498
1499 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001500 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001501 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001502
1503 /* Set opaque-LSA body fields. */
1504 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1505 ntohs (protolsa->length) - sizeof (struct lsa_header));
1506
1507 /* Determine length of LSA. */
1508 length = stream_get_endp (s);
1509 newlsa->length = htons (length);
1510
1511 /* Create OSPF LSA. */
1512 if ((new = ospf_lsa_new ()) == NULL)
1513 {
1514 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1515 stream_free (s);
1516 return NULL;
1517 }
1518
1519 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1520 {
1521 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001522 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001523 stream_free (s);
1524 return NULL;
1525 }
1526
1527 new->area = area;
1528 new->oi = oi;
1529
1530 SET_FLAG (new->flags, OSPF_LSA_SELF);
1531 memcpy (new->data, newlsa, length);
1532 stream_free (s);
1533
1534 return new;
1535}
1536
1537
1538int
1539ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1540{
1541 /* Type 9 opaque LSA can be originated if there is at least one
1542 active opaque-capable neighbor attached to the outgoing
1543 interface. */
1544
paula15f45d2003-03-28 01:50:03 +00001545 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001546}
1547
1548int
1549ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1550{
1551 /* Type 10 opaque LSA can be originated if there is at least one
1552 interface belonging to the area that has an active opaque-capable
1553 neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001554 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001555 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001556
paul1eb8ef22005-04-07 07:30:20 +00001557 for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001558 /* Is there an active neighbor attached to this interface? */
1559 if (ospf_apiserver_is_ready_type9 (oi))
1560 return 1;
paul2d33f152003-03-17 01:10:58 +00001561
paul2d33f152003-03-17 01:10:58 +00001562 /* No active neighbor in area */
1563 return 0;
1564}
1565
1566int
1567ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1568{
1569 /* Type 11 opaque LSA can be originated if there is at least one interface
1570 that has an active opaque-capable neighbor. */
paul1eb8ef22005-04-07 07:30:20 +00001571 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00001572 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001573
paul1eb8ef22005-04-07 07:30:20 +00001574 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul87d6f872004-09-24 08:01:38 +00001575 /* Is there an active neighbor attached to this interface? */
1576 if (ospf_apiserver_is_ready_type9 (oi))
1577 return 1;
paul2d33f152003-03-17 01:10:58 +00001578
paul2d33f152003-03-17 01:10:58 +00001579 /* No active neighbor at all */
1580 return 0;
1581}
1582
1583
1584int
1585ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1586 struct msg *msg)
1587{
1588 struct msg_originate_request *omsg;
1589 struct lsa_header *data;
1590 struct ospf_lsa *new;
1591 struct ospf_lsa *old;
1592 struct ospf_area *area = NULL;
1593 struct ospf_interface *oi = NULL;
1594 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001595 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001596 int lsa_type, opaque_type;
1597 int ready = 0;
1598 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001599
paul99b7c5d2003-04-06 01:19:28 +00001600 ospf = ospf_lookup();
1601
paul2d33f152003-03-17 01:10:58 +00001602 /* Extract opaque LSA data from message */
1603 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1604 data = &omsg->data;
1605
1606 /* Determine interface for type9 or area for type10 LSAs. */
1607 switch (data->type)
1608 {
1609 case OSPF_OPAQUE_LINK_LSA:
1610 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1611 if (!oi)
1612 {
1613 zlog_warn ("apiserver_originate: unknown interface %s",
1614 inet_ntoa (omsg->ifaddr));
1615 rc = OSPF_API_NOSUCHINTERFACE;
1616 goto out;
1617 }
1618 area = oi->area;
1619 lsdb = area->lsdb;
1620 break;
1621 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001622 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001623 if (!area)
1624 {
1625 zlog_warn ("apiserver_originate: unknown area %s",
1626 inet_ntoa (omsg->area_id));
1627 rc = OSPF_API_NOSUCHAREA;
1628 goto out;
1629 }
1630 lsdb = area->lsdb;
1631 break;
1632 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001633 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001634 break;
1635 default:
1636 /* We can only handle opaque types here */
1637 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1638 data->type);
1639 rc = OSPF_API_ILLEGALLSATYPE;
1640 goto out;
1641 }
1642
1643 /* Check if we registered this opaque type */
1644 lsa_type = data->type;
1645 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1646
1647 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1648 {
1649 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1650 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1651 goto out;
1652 }
1653
1654 /* Make sure that the neighbors are ready before we can originate */
1655 switch (data->type)
1656 {
1657 case OSPF_OPAQUE_LINK_LSA:
1658 ready = ospf_apiserver_is_ready_type9 (oi);
1659 break;
1660 case OSPF_OPAQUE_AREA_LSA:
1661 ready = ospf_apiserver_is_ready_type10 (area);
1662 break;
1663 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001664 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001665 break;
1666 default:
1667 break;
1668 }
1669
1670 if (!ready)
1671 {
1672 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1673 rc = OSPF_API_NOTREADY;
1674 goto out;
1675 }
1676
1677 /* Create OSPF's internal opaque LSA representation */
1678 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1679 if (!new)
1680 {
1681 rc = OSPF_API_NOMEMORY; /* XXX */
1682 goto out;
1683 }
1684
1685 /* Determine if LSA is new or an update for an existing one. */
1686 old = ospf_lsdb_lookup (lsdb, new);
1687
1688 if (!old)
1689 {
1690 /* New LSA install in LSDB. */
1691 rc = ospf_apiserver_originate1 (new);
1692 }
1693 else
1694 {
1695 /*
1696 * Keep the new LSA instance in the "waiting place" until the next
1697 * refresh timing. If several LSA update requests for the same LSID
1698 * have issued by peer, the last one takes effect.
1699 */
1700 new->lsdb = &apiserv->reserve;
1701 ospf_lsdb_add (&apiserv->reserve, new);
1702
1703 /* Kick the scheduler function. */
1704 ospf_opaque_lsa_refresh_schedule (old);
1705 }
1706
1707out:
1708
1709 /* Send a reply back to client with return code */
1710 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1711 return rc;
1712}
1713
1714
1715/* -----------------------------------------------------------
1716 * Flood an LSA within its flooding scope.
1717 * -----------------------------------------------------------
1718 */
1719
1720/* XXX We can probably use ospf_flood_through instead of this function
1721 but then we need the neighbor parameter. If we set nbr to
1722 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1723
1724void
1725ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1726{
1727 assert (lsa);
1728
1729 switch (lsa->data->type)
1730 {
1731 case OSPF_OPAQUE_LINK_LSA:
1732 /* Increment counters? XXX */
1733
1734 /* Flood LSA through local network. */
1735 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1736 break;
1737 case OSPF_OPAQUE_AREA_LSA:
1738 /* Update LSA origination count. */
1739 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001740 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001741
1742 /* Flood LSA through area. */
1743 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1744 break;
1745 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001746 {
paul99b7c5d2003-04-06 01:19:28 +00001747 struct ospf *ospf;
1748
1749 ospf = ospf_lookup();
1750 assert(ospf);
1751
paul7d5e2682003-04-05 19:41:07 +00001752 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001753
paul7d5e2682003-04-05 19:41:07 +00001754 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001755 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001756 break;
1757 }
paul2d33f152003-03-17 01:10:58 +00001758 }
1759}
1760
1761int
1762ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1763{
paul99b7c5d2003-04-06 01:19:28 +00001764 struct ospf *ospf;
1765
1766 ospf = ospf_lookup();
1767 assert(ospf);
1768
paul2d33f152003-03-17 01:10:58 +00001769 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001770 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001771 {
1772 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1773 return -1;
1774 }
1775
1776 /* Flood LSA within scope */
1777
1778#ifdef NOTYET
1779 /*
1780 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1781 * parameter, and thus it does not cause SIGSEGV error.
1782 */
1783 ospf_flood_through (NULL /*nbr */ , lsa);
1784#else /* NOTYET */
1785
1786 ospf_apiserver_flood_opaque_lsa (lsa);
1787#endif /* NOTYET */
1788
1789 return 0;
1790}
1791
1792
1793/* Opaque LSAs of type 9 on a specific interface can now be
1794 originated. Tell clients that registered type 9. */
1795int
1796ospf_apiserver_lsa9_originator (void *arg)
1797{
1798 struct ospf_interface *oi;
1799
1800 oi = (struct ospf_interface *) arg;
1801 if (listcount (apiserver_list) > 0) {
1802 ospf_apiserver_clients_notify_ready_type9 (oi);
1803 }
1804 return 0;
1805}
1806
1807int
1808ospf_apiserver_lsa10_originator (void *arg)
1809{
1810 struct ospf_area *area;
1811
1812 area = (struct ospf_area *) arg;
1813 if (listcount (apiserver_list) > 0) {
1814 ospf_apiserver_clients_notify_ready_type10 (area);
1815 }
1816 return 0;
1817}
1818
1819int
1820ospf_apiserver_lsa11_originator (void *arg)
1821{
1822 struct ospf *ospf;
1823
1824 ospf = (struct ospf *) arg;
1825 if (listcount (apiserver_list) > 0) {
1826 ospf_apiserver_clients_notify_ready_type11 (ospf);
1827 }
1828 return 0;
1829}
1830
1831
1832/* Periodically refresh opaque LSAs so that they do not expire in
1833 other routers. */
Paul Jakma072990e2011-04-11 16:28:16 +01001834struct ospf_lsa *
paul2d33f152003-03-17 01:10:58 +00001835ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1836{
1837 struct ospf_apiserver *apiserv;
1838 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001839 struct ospf * ospf;
1840
1841 ospf = ospf_lookup();
1842 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001843
1844 apiserv = lookup_apiserver_by_lsa (lsa);
1845 if (!apiserv)
1846 {
1847 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1848 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1849 }
1850
1851 if (IS_LSA_MAXAGE (lsa))
1852 {
1853 ospf_opaque_lsa_flush_schedule (lsa);
1854 goto out;
1855 }
1856
1857 /* Check if updated version of LSA instance has already prepared. */
1858 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1859 if (!new)
1860 {
1861 /* This is a periodic refresh, driven by core OSPF mechanism. */
1862 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1863 if (!new)
1864 {
1865 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1866 goto out;
1867 }
1868 }
1869 else
1870 {
1871 /* This is a forcible refresh, requested by OSPF-API client. */
1872 ospf_lsdb_delete (&apiserv->reserve, new);
1873 new->lsdb = NULL;
1874 }
1875
1876 /* Increment sequence number */
1877 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1878
1879 /* New LSA is in same area. */
1880 new->area = lsa->area;
1881 SET_FLAG (new->flags, OSPF_LSA_SELF);
1882
1883 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001884 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001885 {
1886 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001887 ospf_lsa_unlock (&new);
paul2d33f152003-03-17 01:10:58 +00001888 goto out;
1889 }
1890
1891 /* Flood updated LSA through interface, area or AS */
1892
1893#ifdef NOTYET
1894 ospf_flood_through (NULL /*nbr */ , new);
1895#endif /* NOTYET */
1896 ospf_apiserver_flood_opaque_lsa (new);
1897
1898 /* Debug logging. */
1899 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1900 {
ajse84cc642004-12-08 17:28:56 +00001901 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
paul2d33f152003-03-17 01:10:58 +00001902 new->data->type, inet_ntoa (new->data->id));
1903 ospf_lsa_header_dump (new->data);
1904 }
1905
1906out:
Paul Jakma072990e2011-04-11 16:28:16 +01001907 return new;
paul2d33f152003-03-17 01:10:58 +00001908}
1909
1910
1911/* -----------------------------------------------------------
1912 * Followings are functions to delete LSAs
1913 * -----------------------------------------------------------
1914 */
1915
1916int
1917ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1918 struct msg *msg)
1919{
1920 struct msg_delete_request *dmsg;
1921 struct ospf_lsa *old;
1922 struct ospf_area *area = NULL;
1923 struct in_addr id;
1924 int lsa_type, opaque_type;
1925 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001926 struct ospf * ospf;
1927
1928 ospf = ospf_lookup();
1929 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001930
1931 /* Extract opaque LSA from message */
1932 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1933
1934 /* Lookup area for link-local and area-local opaque LSAs */
1935 switch (dmsg->lsa_type)
1936 {
1937 case OSPF_OPAQUE_LINK_LSA:
1938 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001939 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001940 if (!area)
1941 {
1942 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1943 inet_ntoa (dmsg->area_id));
1944 rc = OSPF_API_NOSUCHAREA;
1945 goto out;
1946 }
1947 break;
1948 case OSPF_OPAQUE_AS_LSA:
1949 /* AS-external opaque LSAs have no designated area */
1950 area = NULL;
1951 break;
1952 default:
1953 zlog_warn
1954 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1955 dmsg->lsa_type);
1956 rc = OSPF_API_ILLEGALLSATYPE;
1957 goto out;
1958 }
1959
1960 /* Check if we registered this opaque type */
1961 lsa_type = dmsg->lsa_type;
1962 opaque_type = dmsg->opaque_type;
1963
1964 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1965 {
1966 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1967 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1968 goto out;
1969 }
1970
1971 /* opaque_id is in network byte order */
1972 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1973 ntohl (dmsg->opaque_id)));
1974
1975 /*
1976 * Even if the target LSA has once scheduled to flush, it remains in
1977 * the LSDB until it is finally handled by the maxage remover thread.
1978 * Therefore, the lookup function below may return non-NULL result.
1979 */
paul99b7c5d2003-04-06 01:19:28 +00001980 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001981 if (!old)
1982 {
1983 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1984 dmsg->lsa_type, inet_ntoa (id));
1985 rc = OSPF_API_NOSUCHLSA;
1986 goto out;
1987 }
1988
1989 /* Schedule flushing of LSA from LSDB */
1990 /* NB: Multiple scheduling will produce a warning message, but harmless. */
1991 ospf_opaque_lsa_flush_schedule (old);
1992
1993out:
1994
1995 /* Send reply back to client including return code */
1996 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1997 return rc;
1998}
1999
2000/* Flush self-originated opaque LSA */
paul4dadc292005-05-06 21:37:42 +00002001static int
paul2d33f152003-03-17 01:10:58 +00002002apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2003 void *p_arg, int int_arg)
2004{
2005 struct param_t
2006 {
2007 struct ospf_apiserver *apiserv;
2008 u_char lsa_type;
2009 u_char opaque_type;
2010 }
2011 *param;
2012
2013 /* Sanity check */
2014 assert (lsa->data);
2015 assert (p_arg);
2016 param = (struct param_t *) p_arg;
2017
2018 /* If LSA matches type and opaque type then delete it */
2019 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2020 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2021 {
2022 ospf_opaque_lsa_flush_schedule (lsa);
2023 }
2024 return 0;
2025}
2026
2027/* Delete self-originated opaque LSAs of a given opaque type. This
2028 function is called when an application unregisters a given opaque
2029 type or a connection to an application closes and all those opaque
2030 LSAs need to be flushed the LSDB. */
2031void
2032ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2033 u_char lsa_type, u_char opaque_type)
2034{
2035 struct param_t
2036 {
2037 struct ospf_apiserver *apiserv;
2038 u_char lsa_type;
2039 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002040 } param;
paul1eb8ef22005-04-07 07:30:20 +00002041 struct listnode *node, *nnode;
paul99b7c5d2003-04-06 01:19:28 +00002042 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002043 struct ospf_area *area;
2044
paul99b7c5d2003-04-06 01:19:28 +00002045 ospf = ospf_lookup();
2046 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002047
2048 /* Set parameter struct. */
2049 param.apiserv = apiserv;
2050 param.lsa_type = lsa_type;
2051 param.opaque_type = opaque_type;
2052
paul2d33f152003-03-17 01:10:58 +00002053 switch (lsa_type)
2054 {
paul99b7c5d2003-04-06 01:19:28 +00002055 struct route_node *rn;
2056 struct ospf_lsa *lsa;
2057
paul2d33f152003-03-17 01:10:58 +00002058 case OSPF_OPAQUE_LINK_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002059 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002060 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2061 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002062 break;
2063 case OSPF_OPAQUE_AREA_LSA:
paul1eb8ef22005-04-07 07:30:20 +00002064 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul87d6f872004-09-24 08:01:38 +00002065 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2066 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002067 break;
2068 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002069 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2070 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002071 break;
2072 default:
2073 break;
2074 }
2075 return;
paul2d33f152003-03-17 01:10:58 +00002076}
2077
2078
2079/* -----------------------------------------------------------
2080 * Followings are callback functions to handle opaque types
2081 * -----------------------------------------------------------
2082 */
2083
2084int
2085ospf_apiserver_new_if (struct interface *ifp)
2086{
2087 struct ospf_interface *oi;
2088
2089 /* For some strange reason it seems possible that we are invoked
2090 with an interface that has no name. This seems to happen during
2091 initialization. Return if this happens */
2092
2093 if (ifp->name[0] == '\0') {
2094 /* interface has empty name */
2095 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2096 return 0;
2097 }
2098
2099 /* zlog_warn for debugging */
2100 zlog_warn ("ospf_apiserver_new_if");
2101 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2102 ifp->ifindex);
2103
2104 if (ifp->name[0] == '\0') {
2105 /* interface has empty name */
2106 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2107 return 0;
2108 }
2109
2110 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2111
2112 if (!oi) {
2113 /* This interface is known to Zebra but not to OSPF daemon yet. */
2114 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2115 ifp->name);
2116 return 0;
2117 }
2118
2119 assert (oi);
2120
2121 /* New interface added to OSPF, tell clients about it */
2122 if (listcount (apiserver_list) > 0) {
2123 ospf_apiserver_clients_notify_new_if (oi);
2124 }
2125 return 0;
2126}
2127
2128int
2129ospf_apiserver_del_if (struct interface *ifp)
2130{
2131 struct ospf_interface *oi;
2132
2133 /* zlog_warn for debugging */
2134 zlog_warn ("ospf_apiserver_del_if");
2135 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2136 ifp->ifindex);
2137
2138 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002139
2140 if (!oi) {
2141 /* This interface is known to Zebra but not to OSPF daemon
2142 anymore. No need to tell clients about it */
2143 return 0;
2144 }
paul2d33f152003-03-17 01:10:58 +00002145
2146 /* Interface deleted, tell clients about it */
2147 if (listcount (apiserver_list) > 0) {
2148 ospf_apiserver_clients_notify_del_if (oi);
2149 }
2150 return 0;
2151}
2152
2153void
2154ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2155{
2156 /* Tell clients about interface change */
2157
2158 /* zlog_warn for debugging */
2159 zlog_warn ("ospf_apiserver_ism_change");
2160 if (listcount (apiserver_list) > 0) {
2161 ospf_apiserver_clients_notify_ism_change (oi);
2162 }
2163
2164 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2165 zlog_warn ("old_state=%d", old_state);
2166 zlog_warn ("oi->state=%d", oi->state);
2167}
2168
2169void
2170ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2171{
2172 /* Neighbor status changed, tell clients about it */
2173 zlog_warn ("ospf_apiserver_nsm_change");
2174 if (listcount (apiserver_list) > 0) {
2175 ospf_apiserver_clients_notify_nsm_change (nbr);
2176 }
2177}
2178
2179void
2180ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2181{
2182 struct opaque_lsa
2183 {
2184 struct lsa_header header;
2185 u_char data[1]; /* opaque data have variable length. This is start
2186 address */
2187 };
2188 struct opaque_lsa *olsa;
2189 int opaquelen;
2190
2191 olsa = (struct opaque_lsa *) lsa->data;
2192
2193 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002194 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002195 else
paul87d6f872004-09-24 08:01:38 +00002196 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002197
2198 /* Output information about opaque LSAs */
2199 if (vty != NULL)
2200 {
2201 int i;
2202 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2203 opaquelen,
2204 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2205 VTY_NEWLINE);
2206 vty_out (vty, " Opaque data: ");
2207
2208 for (i = 0; i < opaquelen; i++)
2209 {
2210 vty_out (vty, "0x%x ", olsa->data[i]);
2211 }
2212 vty_out (vty, "%s", VTY_NEWLINE);
2213 }
2214 else
2215 {
2216 int i;
ajse84cc642004-12-08 17:28:56 +00002217 zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
paul2d33f152003-03-17 01:10:58 +00002218 opaquelen,
2219 VALID_OPAQUE_INFO_LEN (lsa->
2220 data) ? "" : "(Invalid length?)");
ajse84cc642004-12-08 17:28:56 +00002221 zlog_debug (" Opaque data: ");
paul2d33f152003-03-17 01:10:58 +00002222
2223 for (i = 0; i < opaquelen; i++)
2224 {
ajse84cc642004-12-08 17:28:56 +00002225 zlog_debug ("0x%x ", olsa->data[i]);
paul2d33f152003-03-17 01:10:58 +00002226 }
ajse84cc642004-12-08 17:28:56 +00002227 zlog_debug ("\n");
paul2d33f152003-03-17 01:10:58 +00002228 }
2229 return;
2230}
2231
2232/* -----------------------------------------------------------
2233 * Followings are functions to notify clients about events
2234 * -----------------------------------------------------------
2235 */
2236
2237/* Send a message to all clients. This is useful for messages
2238 that need to be notified to all clients (such as interface
2239 changes) */
2240
2241void
2242ospf_apiserver_clients_notify_all (struct msg *msg)
2243{
paul1eb8ef22005-04-07 07:30:20 +00002244 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002245 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002246
2247 /* Send message to all clients */
paul1eb8ef22005-04-07 07:30:20 +00002248 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul87d6f872004-09-24 08:01:38 +00002249 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002250}
2251
2252/* An interface is now ready to accept opaque LSAs. Notify all
2253 clients that registered to use this opaque type */
2254void
2255ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2256{
paul1eb8ef22005-04-07 07:30:20 +00002257 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002258 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002259 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002260
2261 assert (oi);
2262 if (!oi->address)
2263 {
2264 zlog_warn ("Interface has no address?");
2265 return;
2266 }
2267
2268 if (!ospf_apiserver_is_ready_type9 (oi))
2269 {
2270 zlog_warn ("Interface not ready for type 9?");
2271 return;
2272 }
2273
paul1eb8ef22005-04-07 07:30:20 +00002274 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002275 {
paul1eb8ef22005-04-07 07:30:20 +00002276 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002277 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002278
paul1eb8ef22005-04-07 07:30:20 +00002279 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002280 {
paul2d33f152003-03-17 01:10:58 +00002281 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2282 {
2283 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2284 r->opaque_type,
2285 oi->address->u.prefix4);
2286 if (!msg)
2287 {
2288 zlog_warn
2289 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2290#ifdef NOTYET
2291 /* Cannot allocate new message. What should we do? */
2292 ospf_apiserver_free (apiserv);
2293#endif
2294 goto out;
2295 }
2296
2297 ospf_apiserver_send_msg (apiserv, msg);
2298 msg_free (msg);
2299 }
2300 }
2301 }
2302
2303out:
2304 return;
2305}
2306
2307void
2308ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2309{
paul1eb8ef22005-04-07 07:30:20 +00002310 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002311 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002312 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002313
2314 assert (area);
2315
2316 if (!ospf_apiserver_is_ready_type10 (area))
2317 {
2318 zlog_warn ("Area not ready for type 10?");
2319 return;
2320 }
2321
paul1eb8ef22005-04-07 07:30:20 +00002322 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002323 {
paul1eb8ef22005-04-07 07:30:20 +00002324 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002325 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002326
paul1eb8ef22005-04-07 07:30:20 +00002327 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002328 {
paul2d33f152003-03-17 01:10:58 +00002329 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2330 {
2331 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2332 r->opaque_type, area->area_id);
2333 if (!msg)
2334 {
2335 zlog_warn
2336 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2337#ifdef NOTYET
2338 /* Cannot allocate new message. What should we do? */
2339 ospf_apiserver_free (apiserv);
2340#endif
paul87d6f872004-09-24 08:01:38 +00002341 goto out;
paul2d33f152003-03-17 01:10:58 +00002342 }
2343
2344 ospf_apiserver_send_msg (apiserv, msg);
2345 msg_free (msg);
2346 }
2347 }
2348 }
2349
2350out:
2351 return;
2352}
2353
2354
2355void
2356ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2357{
paul1eb8ef22005-04-07 07:30:20 +00002358 struct listnode *node, *nnode;
paul2d33f152003-03-17 01:10:58 +00002359 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002360 struct in_addr id_null = { .s_addr = 0L };
paul87d6f872004-09-24 08:01:38 +00002361 struct ospf_apiserver *apiserv;
paul36238142005-10-11 04:12:54 +00002362
paul2d33f152003-03-17 01:10:58 +00002363 assert (top);
paul36238142005-10-11 04:12:54 +00002364
paul2d33f152003-03-17 01:10:58 +00002365 if (!ospf_apiserver_is_ready_type11 (top))
2366 {
2367 zlog_warn ("AS not ready for type 11?");
2368 return;
2369 }
2370
paul1eb8ef22005-04-07 07:30:20 +00002371 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002372 {
paul1eb8ef22005-04-07 07:30:20 +00002373 struct listnode *node2, *nnode2;
paul87d6f872004-09-24 08:01:38 +00002374 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002375
paul1eb8ef22005-04-07 07:30:20 +00002376 for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
paul2d33f152003-03-17 01:10:58 +00002377 {
paul2d33f152003-03-17 01:10:58 +00002378 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2379 {
2380 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2381 r->opaque_type, id_null);
2382 if (!msg)
2383 {
2384 zlog_warn
2385 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2386#ifdef NOTYET
2387 /* Cannot allocate new message. What should we do? */
2388 ospf_apiserver_free (apiserv);
2389#endif
2390 goto out;
2391 }
2392
2393 ospf_apiserver_send_msg (apiserv, msg);
2394 msg_free (msg);
2395 }
2396 }
2397 }
2398
2399out:
2400 return;
2401}
2402
2403void
2404ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2405{
2406 struct msg *msg;
2407
2408 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2409 if (msg != NULL)
2410 {
2411 ospf_apiserver_clients_notify_all (msg);
2412 msg_free (msg);
2413 }
2414}
2415
2416void
2417ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2418{
2419 struct msg *msg;
2420
2421 msg = new_msg_del_if (0, oi->address->u.prefix4);
2422 if (msg != NULL)
2423 {
2424 ospf_apiserver_clients_notify_all (msg);
2425 msg_free (msg);
2426 }
2427}
2428
2429void
2430ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2431{
2432 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002433 struct in_addr ifaddr = { .s_addr = 0L };
2434 struct in_addr area_id = { .s_addr = 0L };
2435
paul2d33f152003-03-17 01:10:58 +00002436 assert (oi);
2437 assert (oi->ifp);
paul36238142005-10-11 04:12:54 +00002438
paul2d33f152003-03-17 01:10:58 +00002439 if (oi->address)
2440 {
2441 ifaddr = oi->address->u.prefix4;
2442 }
2443 if (oi->area)
2444 {
2445 area_id = oi->area->area_id;
2446 }
2447
hasso1ddd7292005-06-07 19:54:04 +00002448 msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
paul2d33f152003-03-17 01:10:58 +00002449 if (!msg)
2450 {
2451 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2452 return;
2453 }
2454
2455 ospf_apiserver_clients_notify_all (msg);
2456 msg_free (msg);
2457}
2458
2459void
2460ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2461{
2462 struct msg *msg;
paul36238142005-10-11 04:12:54 +00002463 struct in_addr ifaddr = { .s_addr = 0L };
2464 struct in_addr nbraddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002465
2466 assert (nbr);
2467
2468 if (nbr->oi)
2469 {
2470 ifaddr = nbr->oi->address->u.prefix4;
2471 }
2472
2473 nbraddr = nbr->address.u.prefix4;
2474
2475 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2476 if (!msg)
2477 {
2478 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2479 return;
2480 }
2481
2482 ospf_apiserver_clients_notify_all (msg);
2483 msg_free (msg);
2484}
2485
paul4dadc292005-05-06 21:37:42 +00002486static void
paul2d33f152003-03-17 01:10:58 +00002487apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2488{
2489 struct msg *msg;
paul1eb8ef22005-04-07 07:30:20 +00002490 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +00002491 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002492
2493 /* Default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002494 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002495
2496 /* Default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002497 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002498
2499 if (lsa->area)
2500 {
2501 area_id = lsa->area->area_id;
2502 }
2503 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2504 {
2505 assert (lsa->oi);
2506 ifaddr = lsa->oi->address->u.prefix4;
2507 }
2508
2509 /* Prepare message that can be sent to clients that have a matching
2510 filter */
2511 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2512 ifaddr, area_id,
2513 lsa->flags & OSPF_LSA_SELF, lsa->data);
2514 if (!msg)
2515 {
2516 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2517 return;
2518 }
2519
2520 /* Now send message to all clients with a matching filter */
paul1eb8ef22005-04-07 07:30:20 +00002521 for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
paul2d33f152003-03-17 01:10:58 +00002522 {
paul2d33f152003-03-17 01:10:58 +00002523 struct lsa_filter_type *filter;
2524 u_int16_t mask;
2525 u_int32_t *area;
2526 int i;
2527
2528 /* Check filter for this client. */
2529 filter = apiserv->filter;
2530
2531 /* Check area IDs in case of non AS-E LSAs.
2532 * If filter has areas (num_areas > 0),
2533 * then one of the areas must match the area ID of this LSA. */
2534
2535 i = filter->num_areas;
2536 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2537 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2538 {
2539 i = 0;
2540 }
2541
2542 if (i > 0)
2543 {
2544 area = (u_int32_t *) (filter + 1);
2545 while (i)
2546 {
2547 if (*area == area_id.s_addr)
2548 {
2549 break;
2550 }
2551 i--;
2552 area++;
2553 }
2554 }
2555 else
2556 {
2557 i = 1;
2558 }
2559
2560 if (i > 0)
2561 {
2562 /* Area match. Check LSA type. */
2563 mask = ntohs (filter->typemask);
2564
2565 if (mask & Power2[lsa->data->type])
2566 {
2567 /* Type also matches. Check origin. */
2568 if ((filter->origin == ANY_ORIGIN) ||
2569 (filter->origin == IS_LSA_SELF (lsa)))
2570 {
2571 ospf_apiserver_send_msg (apiserv, msg);
2572 }
2573 }
2574 }
2575 }
2576 /* Free message since it is not used anymore */
2577 msg_free (msg);
2578}
2579
2580
2581/* -------------------------------------------------------------
2582 * Followings are hooks invoked when LSAs are updated or deleted
2583 * -------------------------------------------------------------
2584 */
2585
2586
paul4dadc292005-05-06 21:37:42 +00002587static int
paul2d33f152003-03-17 01:10:58 +00002588apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2589{
2590 struct msg *msg;
2591 /* default area for AS-External and Opaque11 LSAs */
paul36238142005-10-11 04:12:54 +00002592 struct in_addr area_id = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002593
2594 /* default interface for non Opaque9 LSAs */
paul36238142005-10-11 04:12:54 +00002595 struct in_addr ifaddr = { .s_addr = 0L };
paul2d33f152003-03-17 01:10:58 +00002596
2597 /* Only notify this update if the LSA's age is smaller than
2598 MAXAGE. Otherwise clients would see LSA updates with max age just
2599 before they are deleted from the LSDB. LSA delete messages have
2600 MAXAGE too but should not be filtered. */
2601 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2602 return 0;
2603 }
2604
2605 if (lsa->area)
2606 {
2607 area_id = lsa->area->area_id;
2608 }
2609 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2610 {
2611 ifaddr = lsa->oi->address->u.prefix4;
2612 }
2613 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2614 ifaddr, area_id,
2615 lsa->flags & OSPF_LSA_SELF, lsa->data);
2616 if (!msg)
2617 {
2618 zlog_warn ("notify_clients_lsa: msg_new failed");
2619 return -1;
2620 }
2621 /* Notify all clients that new LSA is added/updated */
2622 apiserver_clients_lsa_change_notify (msgtype, lsa);
2623
2624 /* Clients made their own copies of msg so we can free msg here */
2625 msg_free (msg);
2626
2627 return 0;
2628}
2629
2630int
2631ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2632{
2633 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2634}
2635
2636int
2637ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2638{
2639 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2640}
2641
2642#endif /* SUPPORT_OSPF_API */
2643