blob: 96fb917939449d530150ce75d247159c856be55e [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{
paul87d6f872004-09-24 08:01:38 +000086 struct listnode *node;
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
93 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul87d6f872004-09-24 08:01:38 +000094 LIST_LOOP (ospf->oiflist, oi, node)
95 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
96 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
97 return oi;
98
paul2d33f152003-03-17 01:10:58 +000099 return NULL;
100}
101
102struct ospf_interface *
103ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
104{
paul87d6f872004-09-24 08:01:38 +0000105 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000106 struct ospf_interface *oi;
paul99b7c5d2003-04-06 01:19:28 +0000107 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +0000108
paulafbacce2003-07-09 16:09:20 +0000109 if (!(ospf = ospf_lookup ()));
paul5549c6b2003-07-09 15:46:33 +0000110 return NULL;
paul99b7c5d2003-04-06 01:19:28 +0000111
paul87d6f872004-09-24 08:01:38 +0000112 LIST_LOOP (ospf->oiflist, oi, node)
113 if (oi->ifp == ifp)
114 return oi;
115
paul2d33f152003-03-17 01:10:58 +0000116 return NULL;
117}
118
119/* -----------------------------------------------------------
120 * Initialization
121 * -----------------------------------------------------------
122 */
123
124unsigned short
125ospf_apiserver_getport (void)
126{
127 struct servent *sp = getservbyname ("ospfapi", "tcp");
128
129 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
130}
131
132/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
133int
134ospf_apiserver_init (void)
135{
136 int fd;
137 int rc = -1;
138
139 /* Create new socket for synchronous messages. */
140 fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
141
142 if (fd < 0)
143 goto out;
144
145 /* Schedule new thread that handles accepted connections. */
146 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
147
148 /* Initialize list that keeps track of all connections. */
149 apiserver_list = list_new ();
150
151 /* Register opaque-independent call back functions. These functions
152 are invoked on ISM, NSM changes and LSA update and LSA deletes */
153 rc =
154 ospf_register_opaque_functab (0 /* all LSAs */,
155 0 /* all opaque types */,
156 ospf_apiserver_new_if,
157 ospf_apiserver_del_if,
158 ospf_apiserver_ism_change,
159 ospf_apiserver_nsm_change,
160 NULL,
161 NULL,
162 NULL,
163 NULL, /* ospf_apiserver_show_info */
164 NULL, /* originator_func */
165 NULL, /* ospf_apiserver_lsa_refresher */
166 ospf_apiserver_lsa_update,
167 ospf_apiserver_lsa_delete);
168 if (rc != 0)
169 {
170 zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
171 }
172
173 rc = 0;
174
175out:
176 return rc;
177}
178
179/* Terminate OSPF API module. */
180void
181ospf_apiserver_term (void)
182{
paul1603c062004-09-24 08:23:24 +0000183 struct listnode *node, *nnode;
paul87d6f872004-09-24 08:01:38 +0000184 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +0000185
186 /* Unregister wildcard [0/0] type */
187 ospf_delete_opaque_functab (0 /* all LSAs */,
188 0 /* all opaque types */);
189
190 /* Free all client instances */
paul1603c062004-09-24 08:23:24 +0000191 while ( (node = listhead (apiserver_list)) != NULL)
paul87d6f872004-09-24 08:01:38 +0000192 ospf_apiserver_free (apiserv);
paul2d33f152003-03-17 01:10:58 +0000193
194 /* Free client list itself */
195 list_delete (apiserver_list);
196
197 /* Free wildcard list */
198 /* XXX */
199}
200
201static struct ospf_apiserver *
202lookup_apiserver (u_char lsa_type, u_char opaque_type)
203{
paul87d6f872004-09-24 08:01:38 +0000204 struct listnode *n1, *n2;
paul2d33f152003-03-17 01:10:58 +0000205 struct registered_opaque_type *r;
206 struct ospf_apiserver *apiserv, *found = NULL;
207
paul87d6f872004-09-24 08:01:38 +0000208 /* XXX: this approaches O(n**2) */
paul2d33f152003-03-17 01:10:58 +0000209 for (n1 = listhead (apiserver_list); n1; nextnode (n1))
210 {
211 apiserv = (struct ospf_apiserver *) getdata (n1);
212
213 for (n2 = listhead (apiserv->opaque_types); n2; nextnode (n2))
214 {
215 r = (struct registered_opaque_type *) getdata (n2);
216
217 if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
218 {
219 found = apiserv;
220 goto out;
221 }
222 }
223 }
224out:
225 return found;
226}
227
228static struct ospf_apiserver *
229lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
230{
231 struct lsa_header *lsah = lsa->data;
232 struct ospf_apiserver *found = NULL;
233
234 if (IS_OPAQUE_LSA (lsah->type))
235 {
236 found = lookup_apiserver (lsah->type,
237 GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
238 }
239 return found;
240}
241
242/* -----------------------------------------------------------
243 * Followings are functions to manage client connections.
244 * -----------------------------------------------------------
245 */
246static int
247ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
248{
249 if (IS_DEBUG_OSPF_EVENT)
250 zlog_info ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
251 return 0;
252}
253
254static int
255ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
256{
257 if (IS_DEBUG_OSPF_EVENT)
258 zlog_info ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
259 return 0;
260}
261
262/* Allocate new connection structure. */
263struct ospf_apiserver *
264ospf_apiserver_new (int fd_sync, int fd_async)
265{
266 struct ospf_apiserver *new =
267 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
268
269 new->filter =
270 XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
271
272 new->fd_sync = fd_sync;
273 new->fd_async = fd_async;
274
275 /* list of registered opaque types that application uses */
276 new->opaque_types = list_new ();
277
278 /* Initialize temporary strage for LSA instances to be refreshed. */
279 memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
280 ospf_lsdb_init (&new->reserve);
281
282 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
283 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
284
285 new->out_sync_fifo = msg_fifo_new ();
286 new->out_async_fifo = msg_fifo_new ();
287 new->t_sync_read = NULL;
288#ifdef USE_ASYNC_READ
289 new->t_async_read = NULL;
290#endif /* USE_ASYNC_READ */
291 new->t_sync_write = NULL;
292 new->t_async_write = NULL;
293
294 new->filter->typemask = 0; /* filter all LSAs */
295 new->filter->origin = ANY_ORIGIN;
296 new->filter->num_areas = 0;
297
298 return new;
299}
300
301void
302ospf_apiserver_event (enum event event, int fd,
303 struct ospf_apiserver *apiserv)
304{
305 struct thread *apiserver_serv_thread;
306
307 switch (event)
308 {
309 case OSPF_APISERVER_ACCEPT:
310 apiserver_serv_thread =
311 thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
312 break;
313 case OSPF_APISERVER_SYNC_READ:
314 apiserv->t_sync_read =
315 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
316 break;
317#ifdef USE_ASYNC_READ
318 case OSPF_APISERVER_ASYNC_READ:
319 apiserv->t_async_read =
320 thread_add_read (master, ospf_apiserver_read, apiserv, fd);
321 break;
322#endif /* USE_ASYNC_READ */
323 case OSPF_APISERVER_SYNC_WRITE:
324 if (!apiserv->t_sync_write)
325 {
326 apiserv->t_sync_write =
327 thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
328 }
329 break;
330 case OSPF_APISERVER_ASYNC_WRITE:
331 if (!apiserv->t_async_write)
332 {
333 apiserv->t_async_write =
334 thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
335 }
336 break;
337 }
338}
339
340/* Free instance. First unregister all opaque types used by
341 application, flush opaque LSAs injected by application
342 from network and close connection. */
343void
344ospf_apiserver_free (struct ospf_apiserver *apiserv)
345{
paul87d6f872004-09-24 08:01:38 +0000346 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +0000347
348 /* Cancel read and write threads. */
349 if (apiserv->t_sync_read)
350 {
351 thread_cancel (apiserv->t_sync_read);
352 }
353#ifdef USE_ASYNC_READ
354 if (apiserv->t_async_read)
355 {
356 thread_cancel (apiserv->t_async_read);
357 }
358#endif /* USE_ASYNC_READ */
359 if (apiserv->t_sync_write)
360 {
361 thread_cancel (apiserv->t_sync_write);
362 }
363
364 if (apiserv->t_async_write)
365 {
366 thread_cancel (apiserv->t_async_write);
367 }
368
369 /* Unregister all opaque types that application registered
370 and flush opaque LSAs if still in LSDB. */
371
372 while ((node = listhead (apiserv->opaque_types)) != NULL)
373 {
374
375 struct registered_opaque_type *regtype = node->data;
376
377 ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
378 regtype->opaque_type);
379
380 }
381
382 /* Close connections to OSPFd. */
383 if (apiserv->fd_sync > 0)
384 {
385 close (apiserv->fd_sync);
386 }
387
388 if (apiserv->fd_async > 0)
389 {
390 close (apiserv->fd_async);
391 }
392
393 /* Free fifos */
394 msg_fifo_free (apiserv->out_sync_fifo);
395 msg_fifo_free (apiserv->out_async_fifo);
396
397 /* Clear temporary strage for LSA instances to be refreshed. */
398 ospf_lsdb_delete_all (&apiserv->reserve);
399 ospf_lsdb_cleanup (&apiserv->reserve);
400
401 /* Remove from the list of active clients. */
402 listnode_delete (apiserver_list, apiserv);
403
404 if (IS_DEBUG_OSPF_EVENT)
405 zlog_info ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
406
407 /* And free instance. */
408 XFREE (MTYPE_OSPF_APISERVER, apiserv);
409}
410
411int
412ospf_apiserver_read (struct thread *thread)
413{
414 struct ospf_apiserver *apiserv;
415 struct msg *msg;
416 int fd;
417 int rc = -1;
418 enum event event;
419
420 apiserv = THREAD_ARG (thread);
421 fd = THREAD_FD (thread);
422
423 if (fd == apiserv->fd_sync)
424 {
425 event = OSPF_APISERVER_SYNC_READ;
426 apiserv->t_sync_read = NULL;
427
428 if (IS_DEBUG_OSPF_EVENT)
429 zlog_info ("API: ospf_apiserver_read: Peer: %s/%u",
430 inet_ntoa (apiserv->peer_sync.sin_addr),
431 ntohs (apiserv->peer_sync.sin_port));
432 }
433#ifdef USE_ASYNC_READ
434 else if (fd == apiserv->fd_async)
435 {
436 event = OSPF_APISERVER_ASYNC_READ;
437 apiserv->t_async_read = NULL;
438
439 if (IS_DEBUG_OSPF_EVENT)
440 zlog_info ("API: ospf_apiserver_read: Peer: %s/%u",
441 inet_ntoa (apiserv->peer_async.sin_addr),
442 ntohs (apiserv->peer_async.sin_port));
443 }
444#endif /* USE_ASYNC_READ */
445 else
446 {
447 zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
448 ospf_apiserver_free (apiserv);
449 goto out;
450 }
451
452 /* Read message from fd. */
453 msg = msg_read (fd);
454 if (msg == NULL)
455 {
456 zlog_warn
457 ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
458
459 /* Perform cleanup. */
460 ospf_apiserver_free (apiserv);
461 goto out;
462 }
463
464 if (IS_DEBUG_OSPF_EVENT)
465 msg_print (msg);
466
467 /* Dispatch to corresponding message handler. */
468 rc = ospf_apiserver_handle_msg (apiserv, msg);
469
470 /* Prepare for next message, add read thread. */
471 ospf_apiserver_event (event, fd, apiserv);
472
473 msg_free (msg);
474
475out:
476 return rc;
477}
478
479int
480ospf_apiserver_sync_write (struct thread *thread)
481{
482 struct ospf_apiserver *apiserv;
483 struct msg *msg;
484 int fd;
485 int rc = -1;
486
487 apiserv = THREAD_ARG (thread);
488 assert (apiserv);
489 fd = THREAD_FD (thread);
490
491 apiserv->t_sync_write = NULL;
492
493 /* Sanity check */
494 if (fd != apiserv->fd_sync)
495 {
496 zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
497 goto out;
498 }
499
500 if (IS_DEBUG_OSPF_EVENT)
501 zlog_info ("API: ospf_apiserver_sync_write: Peer: %s/%u",
502 inet_ntoa (apiserv->peer_sync.sin_addr),
503 ntohs (apiserv->peer_sync.sin_port));
504
505 /* Check whether there is really a message in the fifo. */
506 msg = msg_fifo_pop (apiserv->out_sync_fifo);
507 if (!msg)
508 {
509 zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
510 return 0;
511 }
512
513 if (IS_DEBUG_OSPF_EVENT)
514 msg_print (msg);
515
516 rc = msg_write (fd, msg);
517
518 /* Once a message is dequeued, it should be freed anyway. */
519 msg_free (msg);
520
521 if (rc < 0)
522 {
523 zlog_warn
524 ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
525 goto out;
526 }
527
528
529 /* If more messages are in sync message fifo, schedule write thread. */
530 if (msg_fifo_head (apiserv->out_sync_fifo))
531 {
532 ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
533 apiserv);
534 }
535
536 out:
537
538 if (rc < 0)
539 {
540 /* Perform cleanup and disconnect with peer */
541 ospf_apiserver_free (apiserv);
542 }
543
544 return rc;
545}
546
547
548int
549ospf_apiserver_async_write (struct thread *thread)
550{
551 struct ospf_apiserver *apiserv;
552 struct msg *msg;
553 int fd;
554 int rc = -1;
555
556 apiserv = THREAD_ARG (thread);
557 assert (apiserv);
558 fd = THREAD_FD (thread);
559
560 apiserv->t_async_write = NULL;
561
562 /* Sanity check */
563 if (fd != apiserv->fd_async)
564 {
565 zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
566 goto out;
567 }
568
569 if (IS_DEBUG_OSPF_EVENT)
570 zlog_info ("API: ospf_apiserver_async_write: Peer: %s/%u",
571 inet_ntoa (apiserv->peer_async.sin_addr),
572 ntohs (apiserv->peer_async.sin_port));
573
574 /* Check whether there is really a message in the fifo. */
575 msg = msg_fifo_pop (apiserv->out_async_fifo);
576 if (!msg)
577 {
578 zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
579 return 0;
580 }
581
582 if (IS_DEBUG_OSPF_EVENT)
583 msg_print (msg);
584
585 rc = msg_write (fd, msg);
586
587 /* Once a message is dequeued, it should be freed anyway. */
588 msg_free (msg);
589
590 if (rc < 0)
591 {
592 zlog_warn
593 ("ospf_apiserver_async_write: write failed on fd=%d", fd);
594 goto out;
595 }
596
597
598 /* If more messages are in async message fifo, schedule write thread. */
599 if (msg_fifo_head (apiserv->out_async_fifo))
600 {
601 ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
602 apiserv);
603 }
604
605 out:
606
607 if (rc < 0)
608 {
609 /* Perform cleanup and disconnect with peer */
610 ospf_apiserver_free (apiserv);
611 }
612
613 return rc;
614}
615
616
617int
618ospf_apiserver_serv_sock_family (unsigned short port, int family)
619{
620 union sockunion su;
621 int accept_sock;
622 int rc;
623
624 memset (&su, 0, sizeof (union sockunion));
625 su.sa.sa_family = family;
626
627 /* Make new socket */
628 accept_sock = sockunion_stream_socket (&su);
629 if (accept_sock < 0)
630 return accept_sock;
631
632 /* This is a server, so reuse address and port */
633 sockopt_reuseaddr (accept_sock);
634 sockopt_reuseport (accept_sock);
635
636 /* Bind socket to address and given port. */
637 rc = sockunion_bind (accept_sock, &su, port, NULL);
638 if (rc < 0)
639 {
640 close (accept_sock); /* Close socket */
641 return rc;
642 }
643
644 /* Listen socket under queue length 3. */
645 rc = listen (accept_sock, 3);
646 if (rc < 0)
647 {
648 zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
649 strerror (errno));
650 close (accept_sock); /* Close socket */
651 return rc;
652 }
653 return accept_sock;
654}
655
656
657/* Accept connection request from external applications. For each
658 accepted connection allocate own connection instance. */
659int
660ospf_apiserver_accept (struct thread *thread)
661{
662 int accept_sock;
663 int new_sync_sock;
664 int new_async_sock;
665 union sockunion su;
666 struct ospf_apiserver *apiserv;
667 struct sockaddr_in peer_async;
668 struct sockaddr_in peer_sync;
669 int peerlen;
670 int ret;
671
672 /* THREAD_ARG (thread) is NULL */
673 accept_sock = THREAD_FD (thread);
674
675 /* Keep hearing on socket for further connections. */
676 ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
677
678 memset (&su, 0, sizeof (union sockunion));
679 /* Accept connection for synchronous messages */
680 new_sync_sock = sockunion_accept (accept_sock, &su);
681 if (new_sync_sock < 0)
682 {
683 zlog_warn ("ospf_apiserver_accept: accept: %s", strerror (errno));
684 return -1;
685 }
686
687 /* Get port address and port number of peer to make reverse connection.
688 The reverse channel uses the port number of the peer port+1. */
689
690 memset(&peer_sync, 0, sizeof(struct sockaddr_in));
691 peerlen = sizeof (struct sockaddr_in);
692
693 ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
694 if (ret < 0)
695 {
696 zlog_warn ("ospf_apiserver_accept: getpeername: %s", strerror (errno));
697 close (new_sync_sock);
698 return -1;
699 }
700
701 if (IS_DEBUG_OSPF_EVENT)
702 zlog_info ("API: ospf_apiserver_accept: New peer: %s/%u",
703 inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
704
705 /* Create new socket for asynchronous messages. */
706 peer_async = peer_sync;
707 peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
708
709 /* Check if remote port number to make reverse connection is valid one. */
710 if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
711 {
712 zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
713 inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
714 close (new_sync_sock);
715 return -1;
716 }
717
718 new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
719 if (new_async_sock < 0)
720 {
721 zlog_warn ("ospf_apiserver_accept: socket: %s", strerror (errno));
722 close (new_sync_sock);
723 return -1;
724 }
725
726 ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
727 sizeof (struct sockaddr_in));
728
729 if (ret < 0)
730 {
731 zlog_warn ("ospf_apiserver_accept: connect: %s", strerror (errno));
732 close (new_sync_sock);
733 close (new_async_sock);
734 return -1;
735 }
736
737#ifdef USE_ASYNC_READ
738#else /* USE_ASYNC_READ */
739 /* Make the asynchronous channel write-only. */
740 ret = shutdown (new_async_sock, SHUT_RD);
741 if (ret < 0)
742 {
743 zlog_warn ("ospf_apiserver_accept: shutdown: %s", strerror (errno));
744 close (new_sync_sock);
745 close (new_async_sock);
746 return -1;
747 }
748#endif /* USE_ASYNC_READ */
749
750 /* Allocate new server-side connection structure */
751 apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
752
753 /* Add to active connection list */
754 listnode_add (apiserver_list, apiserv);
755 apiserv->peer_sync = peer_sync;
756 apiserv->peer_async = peer_async;
757
758 /* And add read threads for new connection */
759 ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
760#ifdef USE_ASYNC_READ
761 ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
762#endif /* USE_ASYNC_READ */
763
764 if (IS_DEBUG_OSPF_EVENT)
765 zlog_warn ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
766
767 return 0;
768}
769
770
771/* -----------------------------------------------------------
772 * Send reply with return code to client application
773 * -----------------------------------------------------------
774 */
775
776int
777ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
778{
779 struct msg_fifo *fifo;
780 struct msg *msg2;
781 enum event event;
782 int fd;
783
784 switch (msg->hdr.msgtype)
785 {
786 case MSG_REPLY:
787 fifo = apiserv->out_sync_fifo;
788 fd = apiserv->fd_sync;
789 event = OSPF_APISERVER_SYNC_WRITE;
790 break;
791 case MSG_READY_NOTIFY:
792 case MSG_LSA_UPDATE_NOTIFY:
793 case MSG_LSA_DELETE_NOTIFY:
794 case MSG_NEW_IF:
795 case MSG_DEL_IF:
796 case MSG_ISM_CHANGE:
797 case MSG_NSM_CHANGE:
798 fifo = apiserv->out_async_fifo;
799 fd = apiserv->fd_async;
800 event = OSPF_APISERVER_ASYNC_WRITE;
801 break;
802 default:
803 zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
804 msg->hdr.msgtype);
805 return -1;
806 }
807
808 /* Make a copy of the message and put in the fifo. Once the fifo
809 gets drained by the write thread, the message will be freed. */
810 /* NB: Given "msg" is untouched in this function. */
811 msg2 = msg_dup (msg);
812
813 /* Enqueue message into corresponding fifo queue */
814 msg_fifo_push (fifo, msg2);
815
816 /* Schedule write thread */
817 ospf_apiserver_event (event, fd, apiserv);
818 return 0;
819}
820
821int
822ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
823 u_char rc)
824{
825 struct msg *msg = new_msg_reply (seqnr, rc);
826 int ret;
827
828 if (!msg)
829 {
830 zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
831#ifdef NOTYET
832 /* Cannot allocate new message. What should we do? */
833 ospf_apiserver_free (apiserv);
834#endif
835 return -1;
836 }
837
838 ret = ospf_apiserver_send_msg (apiserv, msg);
839 msg_free (msg);
840 return ret;
841}
842
843
844/* -----------------------------------------------------------
845 * Generic message dispatching handler function
846 * -----------------------------------------------------------
847 */
848
849int
850ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
851{
852 int rc;
853
854 /* Call corresponding message handler function. */
855 switch (msg->hdr.msgtype)
856 {
857 case MSG_REGISTER_OPAQUETYPE:
858 rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
859 break;
860 case MSG_UNREGISTER_OPAQUETYPE:
861 rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
862 break;
863 case MSG_REGISTER_EVENT:
864 rc = ospf_apiserver_handle_register_event (apiserv, msg);
865 break;
866 case MSG_SYNC_LSDB:
867 rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
868 break;
869 case MSG_ORIGINATE_REQUEST:
870 rc = ospf_apiserver_handle_originate_request (apiserv, msg);
871 break;
872 case MSG_DELETE_REQUEST:
873 rc = ospf_apiserver_handle_delete_request (apiserv, msg);
874 break;
875 default:
876 zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
877 msg->hdr.msgtype);
878 rc = -1;
879 }
880 return rc;
881}
882
883
884/* -----------------------------------------------------------
885 * Following are functions for opaque type registration
886 * -----------------------------------------------------------
887 */
888
889int
890ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
891 u_char lsa_type, u_char opaque_type)
892{
893 struct registered_opaque_type *regtype;
894 int (*originator_func) (void *arg);
895 int rc;
896
897 switch (lsa_type)
898 {
899 case OSPF_OPAQUE_LINK_LSA:
900 originator_func = ospf_apiserver_lsa9_originator;
901 break;
902 case OSPF_OPAQUE_AREA_LSA:
903 originator_func = ospf_apiserver_lsa10_originator;
904 break;
905 case OSPF_OPAQUE_AS_LSA:
906 originator_func = ospf_apiserver_lsa11_originator;
907 break;
908 default:
909 zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
910 lsa_type);
911 return OSPF_API_ILLEGALLSATYPE;
912 }
913
914
915 /* Register opaque function table */
916 /* NB: Duplicated registration will be detected inside the function. */
917 rc =
918 ospf_register_opaque_functab (lsa_type, opaque_type,
919 NULL, /* ospf_apiserver_new_if */
920 NULL, /* ospf_apiserver_del_if */
921 NULL, /* ospf_apiserver_ism_change */
922 NULL, /* ospf_apiserver_nsm_change */
923 NULL,
924 NULL,
925 NULL,
926 ospf_apiserver_show_info,
927 originator_func,
928 ospf_apiserver_lsa_refresher,
929 NULL, /* ospf_apiserver_lsa_update */
930 NULL /* ospf_apiserver_lsa_delete */);
931
932 if (rc != 0)
933 {
934 zlog_warn ("Failed to register opaque type [%d/%d]",
935 lsa_type, opaque_type);
936 return OSPF_API_OPAQUETYPEINUSE;
937 }
938
939 /* Remember the opaque type that application registers so when
940 connection shuts down, we can flush all LSAs of this opaque
941 type. */
942
943 regtype =
944 XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
945 memset (regtype, 0, sizeof (struct registered_opaque_type));
946 regtype->lsa_type = lsa_type;
947 regtype->opaque_type = opaque_type;
948
949 /* Add to list of registered opaque types */
950 listnode_add (apiserv->opaque_types, regtype);
951
952 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +0000953 zlog_info ("API: Add LSA-type(%d)/Opaque-type(%d) into"
954 " apiserv(%p), total#(%d)",
955 lsa_type, opaque_type, apiserv,
956 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000957
958 return 0;
959}
960
961int
962ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
963 u_char lsa_type, u_char opaque_type)
964{
gdt54ade992004-10-07 19:38:20 +0000965 struct listnode *n1, *n1_next;
966 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +0000967
gdt54ade992004-10-07 19:38:20 +0000968 for (n1 = listhead (apiserv->opaque_types); n1; n1 = n1_next)
paul2d33f152003-03-17 01:10:58 +0000969 {
gdt54ade992004-10-07 19:38:20 +0000970 n1_next = n1->next;
paul87d6f872004-09-24 08:01:38 +0000971
gdt54ade992004-10-07 19:38:20 +0000972 regtype = (struct registered_opaque_type *) getdata(n1);
paul2d33f152003-03-17 01:10:58 +0000973
974 /* Check if we really registered this opaque type */
975 if (regtype->lsa_type == lsa_type &&
976 regtype->opaque_type == opaque_type)
977 {
978
979 /* Yes, we registered this opaque type. Flush
980 all existing opaque LSAs of this type */
981
982 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
983 ospf_delete_opaque_functab (lsa_type, opaque_type);
984
985 /* Remove from list of registered opaque types */
986 listnode_delete (apiserv->opaque_types, regtype);
987
988 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +0000989 zlog_info ("API: Del LSA-type(%d)/Opaque-type(%d)"
990 " from apiserv(%p), total#(%d)",
991 lsa_type, opaque_type, apiserv,
992 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000993
994 return 0;
995 }
996 }
997
998 /* Opaque type is not registered */
999 zlog_warn ("Failed to unregister opaque type [%d/%d]",
1000 lsa_type, opaque_type);
1001 return OSPF_API_OPAQUETYPENOTREGISTERED;
1002}
1003
1004
1005int
1006apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
1007 u_char lsa_type, u_char opaque_type)
1008{
paul87d6f872004-09-24 08:01:38 +00001009 struct listnode *node;
1010 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001011
paul87d6f872004-09-24 08:01:38 +00001012 /* XXX: how many types are there? if few, why not just a bitmap? */
1013 LIST_LOOP (apiserv->opaque_types, regtype, node)
paul2d33f152003-03-17 01:10:58 +00001014 {
paul2d33f152003-03-17 01:10:58 +00001015 /* Check if we really registered this opaque type */
1016 if (regtype->lsa_type == lsa_type &&
1017 regtype->opaque_type == opaque_type)
1018 {
1019 /* Yes registered */
1020 return 1;
1021 }
1022 }
1023 /* Not registered */
1024 return 0;
1025}
1026
1027int
1028ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1029 struct msg *msg)
1030{
1031 struct msg_register_opaque_type *rmsg;
1032 u_char lsa_type;
1033 u_char opaque_type;
1034 int rc = 0;
1035
1036 /* Extract parameters from register opaque type message */
1037 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1038
1039 lsa_type = rmsg->lsatype;
1040 opaque_type = rmsg->opaquetype;
1041
1042 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1043
1044 /* Send a reply back to client including return code */
1045 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1046 if (rc < 0)
1047 goto out;
1048
1049 /* Now inform application about opaque types that are ready */
1050 switch (lsa_type)
1051 {
1052 case OSPF_OPAQUE_LINK_LSA:
1053 ospf_apiserver_notify_ready_type9 (apiserv);
1054 break;
1055 case OSPF_OPAQUE_AREA_LSA:
1056 ospf_apiserver_notify_ready_type10 (apiserv);
1057 break;
1058 case OSPF_OPAQUE_AS_LSA:
1059 ospf_apiserver_notify_ready_type11 (apiserv);
1060 break;
1061 }
1062out:
1063 return rc;
1064}
1065
1066
1067/* Notify specific client about all opaque types 9 that are ready. */
1068void
1069ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1070{
paul87d6f872004-09-24 08:01:38 +00001071 struct listnode *node;
1072 struct listnode *n2;
paul99b7c5d2003-04-06 01:19:28 +00001073 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001074 struct ospf_interface *oi;
1075 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001076
paul99b7c5d2003-04-06 01:19:28 +00001077 ospf = ospf_lookup ();
1078
paul87d6f872004-09-24 08:01:38 +00001079 LIST_LOOP (ospf->oiflist, oi, node)
paul2d33f152003-03-17 01:10:58 +00001080 {
paul2d33f152003-03-17 01:10:58 +00001081 /* Check if this interface is indeed ready for type 9 */
1082 if (!ospf_apiserver_is_ready_type9 (oi))
1083 continue;
1084
1085 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001086 /* XXX: loop-de-loop - optimise me */
1087 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00001088 {
paul2d33f152003-03-17 01:10:58 +00001089 struct msg *msg;
1090
1091 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1092 {
1093
1094 /* Yes, this opaque type is ready */
1095 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1096 r->opaque_type,
1097 oi->address->u.prefix4);
1098 if (!msg)
1099 {
1100 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1101#ifdef NOTYET
1102 /* Cannot allocate new message. What should we do? */
1103 ospf_apiserver_free (apiserv);
1104#endif
1105 goto out;
1106 }
1107 ospf_apiserver_send_msg (apiserv, msg);
1108 msg_free (msg);
1109 }
1110 }
1111 }
1112
1113out:
1114 return;
1115}
1116
1117
1118/* Notify specific client about all opaque types 10 that are ready. */
1119void
1120ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1121{
paul87d6f872004-09-24 08:01:38 +00001122 struct listnode *node;
1123 struct listnode *n2;
paul99b7c5d2003-04-06 01:19:28 +00001124 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001125 struct ospf_area *area;
1126
paul99b7c5d2003-04-06 01:19:28 +00001127 ospf = ospf_lookup ();
1128
paul87d6f872004-09-24 08:01:38 +00001129 LIST_LOOP (ospf->areas, area, node)
paul2d33f152003-03-17 01:10:58 +00001130 {
paul87d6f872004-09-24 08:01:38 +00001131 struct registered_opaque_type *r;
1132
paul2d33f152003-03-17 01:10:58 +00001133 if (!ospf_apiserver_is_ready_type10 (area))
1134 {
1135 continue;
1136 }
1137
1138 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001139 /* XXX: loop in loop - optimise me */
1140 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00001141 {
paul2d33f152003-03-17 01:10:58 +00001142 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001143
paul2d33f152003-03-17 01:10:58 +00001144 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1145 {
1146 /* Yes, this opaque type is ready */
1147 msg =
1148 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1149 r->opaque_type, area->area_id);
1150 if (!msg)
1151 {
1152 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1153#ifdef NOTYET
1154 /* Cannot allocate new message. What should we do? */
1155 ospf_apiserver_free (apiserv);
1156#endif
1157 goto out;
1158 }
1159 ospf_apiserver_send_msg (apiserv, msg);
1160 msg_free (msg);
1161 }
1162 }
1163 }
1164
1165out:
1166 return;
1167}
1168
1169/* Notify specific client about all opaque types 11 that are ready */
1170void
1171ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1172{
paul87d6f872004-09-24 08:01:38 +00001173 struct listnode *node;
paul99b7c5d2003-04-06 01:19:28 +00001174 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001175 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001176
1177 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001178
1179 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001180 if (!ospf_apiserver_is_ready_type11 (ospf))
paul1603c062004-09-24 08:23:24 +00001181 goto out;
paul2d33f152003-03-17 01:10:58 +00001182
1183 /* Check for registered opaque type 11 types */
paul87d6f872004-09-24 08:01:38 +00001184 LIST_LOOP (apiserv->opaque_types, r, node)
paul2d33f152003-03-17 01:10:58 +00001185 {
paul2d33f152003-03-17 01:10:58 +00001186 struct msg *msg;
1187 struct in_addr noarea_id = { 0L };
1188
1189 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1190 {
1191 /* Yes, this opaque type is ready */
1192 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1193 r->opaque_type, noarea_id);
1194
1195 if (!msg)
1196 {
1197 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1198#ifdef NOTYET
1199 /* Cannot allocate new message. What should we do? */
1200 ospf_apiserver_free (apiserv);
1201#endif
1202 goto out;
1203 }
1204 ospf_apiserver_send_msg (apiserv, msg);
1205 msg_free (msg);
1206 }
1207 }
1208
1209out:
1210 return;
1211}
1212
1213int
1214ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1215 struct msg *msg)
1216{
1217 struct msg_unregister_opaque_type *umsg;
1218 u_char ltype;
1219 u_char otype;
1220 int rc = 0;
1221
1222 /* Extract parameters from unregister opaque type message */
1223 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1224
1225 ltype = umsg->lsatype;
1226 otype = umsg->opaquetype;
1227
1228 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1229
1230 /* Send a reply back to client including return code */
1231 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1232
1233 return rc;
1234}
1235
1236
1237/* -----------------------------------------------------------
1238 * Following are functions for event (filter) registration.
1239 * -----------------------------------------------------------
1240 */
1241int
1242ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1243 struct msg *msg)
1244{
1245 struct msg_register_event *rmsg;
1246 int rc;
1247 u_int32_t seqnum;
1248
1249 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1250
1251 /* Get request sequence number */
1252 seqnum = msg_get_seq (msg);
1253
1254 /* Free existing filter in apiserv. */
1255 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1256 /* Alloc new space for filter. */
1257
1258 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1259 ntohs (msg->hdr.msglen));
1260 if (apiserv->filter)
1261 {
1262 /* copy it over. */
1263 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1264 rc = OSPF_API_OK;
1265 }
1266 else
1267 {
1268 rc = OSPF_API_NOMEMORY;
1269 }
1270 /* Send a reply back to client with return code */
1271 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1272 return rc;
1273}
1274
1275
1276/* -----------------------------------------------------------
1277 * Followings are functions for LSDB synchronization.
1278 * -----------------------------------------------------------
1279 */
1280
1281int
1282apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1283{
1284 struct ospf_apiserver *apiserv;
1285 int seqnum;
1286 struct msg *msg;
1287 struct param_t
1288 {
1289 struct ospf_apiserver *apiserv;
1290 struct lsa_filter_type *filter;
1291 }
1292 *param;
1293 int rc = -1;
1294
1295 /* Sanity check */
1296 assert (lsa->data);
1297 assert (p_arg);
1298
1299 param = (struct param_t *) p_arg;
1300 apiserv = param->apiserv;
1301 seqnum = (u_int32_t) int_arg;
1302
1303 /* Check origin in filter. */
1304 if ((param->filter->origin == ANY_ORIGIN) ||
1305 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1306 {
1307
1308 /* Default area for AS-External and Opaque11 LSAs */
1309 struct in_addr area_id = { 0L };
1310
1311 /* Default interface for non Opaque9 LSAs */
1312 struct in_addr ifaddr = { 0L };
1313
1314 if (lsa->area)
1315 {
1316 area_id = lsa->area->area_id;
1317 }
1318 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1319 {
1320 ifaddr = lsa->oi->address->u.prefix4;
1321 }
1322
1323 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1324 seqnum,
1325 ifaddr, area_id,
1326 lsa->flags & OSPF_LSA_SELF, lsa->data);
1327 if (!msg)
1328 {
1329 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1330#ifdef NOTYET
1331 /* Cannot allocate new message. What should we do? */
1332/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1333#endif
1334 goto out;
1335 }
1336
1337 /* Send LSA */
1338 ospf_apiserver_send_msg (apiserv, msg);
1339 msg_free (msg);
1340 }
1341 rc = 0;
1342
1343out:
1344 return rc;
1345}
1346
1347int
1348ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1349 struct msg *msg)
1350{
paul87d6f872004-09-24 08:01:38 +00001351 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00001352 u_int32_t seqnum;
1353 int rc = 0;
1354 struct msg_sync_lsdb *smsg;
1355 struct param_t
1356 {
1357 struct ospf_apiserver *apiserv;
1358 struct lsa_filter_type *filter;
1359 }
1360 param;
1361 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001362 struct route_node *rn;
1363 struct ospf_lsa *lsa;
1364 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001365 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001366
1367 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001368
1369 /* Get request sequence number */
1370 seqnum = msg_get_seq (msg);
1371 /* Set sync msg. */
1372 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1373
1374 /* Set parameter struct. */
1375 param.apiserv = apiserv;
1376 param.filter = &smsg->filter;
1377
1378 /* Remember mask. */
1379 mask = ntohs (smsg->filter.typemask);
1380
1381 /* Iterate over all areas. */
paul87d6f872004-09-24 08:01:38 +00001382 LIST_LOOP (ospf->areas, area, node)
paul2d33f152003-03-17 01:10:58 +00001383 {
paul2d33f152003-03-17 01:10:58 +00001384 int i;
1385 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001386
paul2d33f152003-03-17 01:10:58 +00001387 /* Compare area_id with area_ids in sync request. */
1388 if ((i = smsg->filter.num_areas) > 0)
1389 {
1390 /* Let area_id point to the list of area IDs,
1391 * which is at the end of smsg->filter. */
1392 area_id = (u_int32_t *) (&smsg->filter + 1);
1393 while (i)
1394 {
1395 if (*area_id == area->area_id.s_addr)
1396 {
1397 break;
1398 }
1399 i--;
1400 area_id++;
1401 }
1402 }
1403 else
1404 {
1405 i = 1;
1406 }
1407
1408 /* If area was found, then i>0 here. */
1409 if (i)
1410 {
1411 /* Check msg type. */
1412 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001413 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1414 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001415 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001416 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1417 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001418 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001419 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1420 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001421 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001422 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1423 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001424 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001425 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1426 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001427 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001428 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1429 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001430 }
1431 }
1432
1433 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001434 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001435 {
1436 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001437 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1438 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001439 }
1440
1441 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001442 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001443 {
1444 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001445 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1446 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001447 }
1448
1449 /* Send a reply back to client with return code */
1450 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1451 return rc;
1452}
1453
1454
1455/* -----------------------------------------------------------
1456 * Followings are functions to originate or update LSA
1457 * from an application.
1458 * -----------------------------------------------------------
1459 */
1460
1461/* Create a new internal opaque LSA by taking prototype and filling in
1462 missing fields such as age, sequence number, advertising router,
1463 checksum and so on. The interface parameter is used for type 9
1464 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1465 nor interface. */
1466
1467struct ospf_lsa *
1468ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1469 struct ospf_interface *oi,
1470 struct lsa_header *protolsa)
1471{
1472 struct stream *s;
1473 struct lsa_header *newlsa;
1474 struct ospf_lsa *new = NULL;
1475 u_char options = 0x0;
1476 u_int16_t length;
1477
paul99b7c5d2003-04-06 01:19:28 +00001478 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001479
paul99b7c5d2003-04-06 01:19:28 +00001480 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001481 assert(ospf);
1482
paul2d33f152003-03-17 01:10:58 +00001483 /* Create a stream for internal opaque LSA */
1484 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1485 {
1486 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1487 return NULL;
1488 }
1489
1490 newlsa = (struct lsa_header *) STREAM_DATA (s);
1491
1492 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1493 have to set options? */
1494
1495 if (area)
1496 {
1497 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001498 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001499 }
1500
1501 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1502
1503 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1504 {
1505 zlog_info ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1506 protolsa->type, inet_ntoa (protolsa->id));
1507 }
1508
1509 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001510 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001511 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001512
1513 /* Set opaque-LSA body fields. */
1514 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1515 ntohs (protolsa->length) - sizeof (struct lsa_header));
1516
1517 /* Determine length of LSA. */
1518 length = stream_get_endp (s);
1519 newlsa->length = htons (length);
1520
1521 /* Create OSPF LSA. */
1522 if ((new = ospf_lsa_new ()) == NULL)
1523 {
1524 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1525 stream_free (s);
1526 return NULL;
1527 }
1528
1529 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1530 {
1531 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1532 ospf_lsa_free (new);
1533 new = NULL;
1534 stream_free (s);
1535 return NULL;
1536 }
1537
1538 new->area = area;
1539 new->oi = oi;
1540
1541 SET_FLAG (new->flags, OSPF_LSA_SELF);
1542 memcpy (new->data, newlsa, length);
1543 stream_free (s);
1544
1545 return new;
1546}
1547
1548
1549int
1550ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1551{
1552 /* Type 9 opaque LSA can be originated if there is at least one
1553 active opaque-capable neighbor attached to the outgoing
1554 interface. */
1555
paula15f45d2003-03-28 01:50:03 +00001556 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001557}
1558
1559int
1560ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1561{
1562 /* Type 10 opaque LSA can be originated if there is at least one
1563 interface belonging to the area that has an active opaque-capable
1564 neighbor. */
paul87d6f872004-09-24 08:01:38 +00001565 struct listnode *node;
1566 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001567
paul87d6f872004-09-24 08:01:38 +00001568 LIST_LOOP (area->oiflist, oi, node)
1569 /* Is there an active neighbor attached to this interface? */
1570 if (ospf_apiserver_is_ready_type9 (oi))
1571 return 1;
paul2d33f152003-03-17 01:10:58 +00001572
paul2d33f152003-03-17 01:10:58 +00001573 /* No active neighbor in area */
1574 return 0;
1575}
1576
1577int
1578ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1579{
1580 /* Type 11 opaque LSA can be originated if there is at least one interface
1581 that has an active opaque-capable neighbor. */
paul87d6f872004-09-24 08:01:38 +00001582 struct listnode *node;
1583 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001584
paul87d6f872004-09-24 08:01:38 +00001585 LIST_LOOP (ospf->oiflist, oi, node)
1586 /* Is there an active neighbor attached to this interface? */
1587 if (ospf_apiserver_is_ready_type9 (oi))
1588 return 1;
paul2d33f152003-03-17 01:10:58 +00001589
paul2d33f152003-03-17 01:10:58 +00001590 /* No active neighbor at all */
1591 return 0;
1592}
1593
1594
1595int
1596ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1597 struct msg *msg)
1598{
1599 struct msg_originate_request *omsg;
1600 struct lsa_header *data;
1601 struct ospf_lsa *new;
1602 struct ospf_lsa *old;
1603 struct ospf_area *area = NULL;
1604 struct ospf_interface *oi = NULL;
1605 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001606 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001607 int lsa_type, opaque_type;
1608 int ready = 0;
1609 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001610
paul99b7c5d2003-04-06 01:19:28 +00001611 ospf = ospf_lookup();
1612
paul2d33f152003-03-17 01:10:58 +00001613 /* Extract opaque LSA data from message */
1614 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1615 data = &omsg->data;
1616
1617 /* Determine interface for type9 or area for type10 LSAs. */
1618 switch (data->type)
1619 {
1620 case OSPF_OPAQUE_LINK_LSA:
1621 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1622 if (!oi)
1623 {
1624 zlog_warn ("apiserver_originate: unknown interface %s",
1625 inet_ntoa (omsg->ifaddr));
1626 rc = OSPF_API_NOSUCHINTERFACE;
1627 goto out;
1628 }
1629 area = oi->area;
1630 lsdb = area->lsdb;
1631 break;
1632 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001633 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001634 if (!area)
1635 {
1636 zlog_warn ("apiserver_originate: unknown area %s",
1637 inet_ntoa (omsg->area_id));
1638 rc = OSPF_API_NOSUCHAREA;
1639 goto out;
1640 }
1641 lsdb = area->lsdb;
1642 break;
1643 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001644 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001645 break;
1646 default:
1647 /* We can only handle opaque types here */
1648 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1649 data->type);
1650 rc = OSPF_API_ILLEGALLSATYPE;
1651 goto out;
1652 }
1653
1654 /* Check if we registered this opaque type */
1655 lsa_type = data->type;
1656 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1657
1658 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1659 {
1660 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1661 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1662 goto out;
1663 }
1664
1665 /* Make sure that the neighbors are ready before we can originate */
1666 switch (data->type)
1667 {
1668 case OSPF_OPAQUE_LINK_LSA:
1669 ready = ospf_apiserver_is_ready_type9 (oi);
1670 break;
1671 case OSPF_OPAQUE_AREA_LSA:
1672 ready = ospf_apiserver_is_ready_type10 (area);
1673 break;
1674 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001675 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001676 break;
1677 default:
1678 break;
1679 }
1680
1681 if (!ready)
1682 {
1683 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1684 rc = OSPF_API_NOTREADY;
1685 goto out;
1686 }
1687
1688 /* Create OSPF's internal opaque LSA representation */
1689 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1690 if (!new)
1691 {
1692 rc = OSPF_API_NOMEMORY; /* XXX */
1693 goto out;
1694 }
1695
1696 /* Determine if LSA is new or an update for an existing one. */
1697 old = ospf_lsdb_lookup (lsdb, new);
1698
1699 if (!old)
1700 {
1701 /* New LSA install in LSDB. */
1702 rc = ospf_apiserver_originate1 (new);
1703 }
1704 else
1705 {
1706 /*
1707 * Keep the new LSA instance in the "waiting place" until the next
1708 * refresh timing. If several LSA update requests for the same LSID
1709 * have issued by peer, the last one takes effect.
1710 */
1711 new->lsdb = &apiserv->reserve;
1712 ospf_lsdb_add (&apiserv->reserve, new);
1713
1714 /* Kick the scheduler function. */
1715 ospf_opaque_lsa_refresh_schedule (old);
1716 }
1717
1718out:
1719
1720 /* Send a reply back to client with return code */
1721 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1722 return rc;
1723}
1724
1725
1726/* -----------------------------------------------------------
1727 * Flood an LSA within its flooding scope.
1728 * -----------------------------------------------------------
1729 */
1730
1731/* XXX We can probably use ospf_flood_through instead of this function
1732 but then we need the neighbor parameter. If we set nbr to
1733 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1734
1735void
1736ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1737{
1738 assert (lsa);
1739
1740 switch (lsa->data->type)
1741 {
1742 case OSPF_OPAQUE_LINK_LSA:
1743 /* Increment counters? XXX */
1744
1745 /* Flood LSA through local network. */
1746 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1747 break;
1748 case OSPF_OPAQUE_AREA_LSA:
1749 /* Update LSA origination count. */
1750 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001751 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001752
1753 /* Flood LSA through area. */
1754 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1755 break;
1756 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001757 {
paul99b7c5d2003-04-06 01:19:28 +00001758 struct ospf *ospf;
1759
1760 ospf = ospf_lookup();
1761 assert(ospf);
1762
paul7d5e2682003-04-05 19:41:07 +00001763 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001764
paul7d5e2682003-04-05 19:41:07 +00001765 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001766 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001767 break;
1768 }
paul2d33f152003-03-17 01:10:58 +00001769 }
1770}
1771
1772int
1773ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1774{
paul99b7c5d2003-04-06 01:19:28 +00001775 struct ospf *ospf;
1776
1777 ospf = ospf_lookup();
1778 assert(ospf);
1779
paul2d33f152003-03-17 01:10:58 +00001780 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001781 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001782 {
1783 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1784 return -1;
1785 }
1786
1787 /* Flood LSA within scope */
1788
1789#ifdef NOTYET
1790 /*
1791 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1792 * parameter, and thus it does not cause SIGSEGV error.
1793 */
1794 ospf_flood_through (NULL /*nbr */ , lsa);
1795#else /* NOTYET */
1796
1797 ospf_apiserver_flood_opaque_lsa (lsa);
1798#endif /* NOTYET */
1799
1800 return 0;
1801}
1802
1803
1804/* Opaque LSAs of type 9 on a specific interface can now be
1805 originated. Tell clients that registered type 9. */
1806int
1807ospf_apiserver_lsa9_originator (void *arg)
1808{
1809 struct ospf_interface *oi;
1810
1811 oi = (struct ospf_interface *) arg;
1812 if (listcount (apiserver_list) > 0) {
1813 ospf_apiserver_clients_notify_ready_type9 (oi);
1814 }
1815 return 0;
1816}
1817
1818int
1819ospf_apiserver_lsa10_originator (void *arg)
1820{
1821 struct ospf_area *area;
1822
1823 area = (struct ospf_area *) arg;
1824 if (listcount (apiserver_list) > 0) {
1825 ospf_apiserver_clients_notify_ready_type10 (area);
1826 }
1827 return 0;
1828}
1829
1830int
1831ospf_apiserver_lsa11_originator (void *arg)
1832{
1833 struct ospf *ospf;
1834
1835 ospf = (struct ospf *) arg;
1836 if (listcount (apiserver_list) > 0) {
1837 ospf_apiserver_clients_notify_ready_type11 (ospf);
1838 }
1839 return 0;
1840}
1841
1842
1843/* Periodically refresh opaque LSAs so that they do not expire in
1844 other routers. */
1845void
1846ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1847{
1848 struct ospf_apiserver *apiserv;
1849 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001850 struct ospf * ospf;
1851
1852 ospf = ospf_lookup();
1853 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001854
1855 apiserv = lookup_apiserver_by_lsa (lsa);
1856 if (!apiserv)
1857 {
1858 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1859 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1860 }
1861
1862 if (IS_LSA_MAXAGE (lsa))
1863 {
1864 ospf_opaque_lsa_flush_schedule (lsa);
1865 goto out;
1866 }
1867
1868 /* Check if updated version of LSA instance has already prepared. */
1869 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1870 if (!new)
1871 {
1872 /* This is a periodic refresh, driven by core OSPF mechanism. */
1873 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1874 if (!new)
1875 {
1876 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1877 goto out;
1878 }
1879 }
1880 else
1881 {
1882 /* This is a forcible refresh, requested by OSPF-API client. */
1883 ospf_lsdb_delete (&apiserv->reserve, new);
1884 new->lsdb = NULL;
1885 }
1886
1887 /* Increment sequence number */
1888 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1889
1890 /* New LSA is in same area. */
1891 new->area = lsa->area;
1892 SET_FLAG (new->flags, OSPF_LSA_SELF);
1893
1894 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001895 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001896 {
1897 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1898 ospf_lsa_free (new);
1899 goto out;
1900 }
1901
1902 /* Flood updated LSA through interface, area or AS */
1903
1904#ifdef NOTYET
1905 ospf_flood_through (NULL /*nbr */ , new);
1906#endif /* NOTYET */
1907 ospf_apiserver_flood_opaque_lsa (new);
1908
1909 /* Debug logging. */
1910 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1911 {
1912 zlog_info ("LSA[Type%d:%s]: Refresh Opaque LSA",
1913 new->data->type, inet_ntoa (new->data->id));
1914 ospf_lsa_header_dump (new->data);
1915 }
1916
1917out:
1918 return;
1919}
1920
1921
1922/* -----------------------------------------------------------
1923 * Followings are functions to delete LSAs
1924 * -----------------------------------------------------------
1925 */
1926
1927int
1928ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1929 struct msg *msg)
1930{
1931 struct msg_delete_request *dmsg;
1932 struct ospf_lsa *old;
1933 struct ospf_area *area = NULL;
1934 struct in_addr id;
1935 int lsa_type, opaque_type;
1936 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001937 struct ospf * ospf;
1938
1939 ospf = ospf_lookup();
1940 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001941
1942 /* Extract opaque LSA from message */
1943 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1944
1945 /* Lookup area for link-local and area-local opaque LSAs */
1946 switch (dmsg->lsa_type)
1947 {
1948 case OSPF_OPAQUE_LINK_LSA:
1949 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001950 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001951 if (!area)
1952 {
1953 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1954 inet_ntoa (dmsg->area_id));
1955 rc = OSPF_API_NOSUCHAREA;
1956 goto out;
1957 }
1958 break;
1959 case OSPF_OPAQUE_AS_LSA:
1960 /* AS-external opaque LSAs have no designated area */
1961 area = NULL;
1962 break;
1963 default:
1964 zlog_warn
1965 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1966 dmsg->lsa_type);
1967 rc = OSPF_API_ILLEGALLSATYPE;
1968 goto out;
1969 }
1970
1971 /* Check if we registered this opaque type */
1972 lsa_type = dmsg->lsa_type;
1973 opaque_type = dmsg->opaque_type;
1974
1975 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1976 {
1977 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1978 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1979 goto out;
1980 }
1981
1982 /* opaque_id is in network byte order */
1983 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1984 ntohl (dmsg->opaque_id)));
1985
1986 /*
1987 * Even if the target LSA has once scheduled to flush, it remains in
1988 * the LSDB until it is finally handled by the maxage remover thread.
1989 * Therefore, the lookup function below may return non-NULL result.
1990 */
paul99b7c5d2003-04-06 01:19:28 +00001991 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001992 if (!old)
1993 {
1994 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1995 dmsg->lsa_type, inet_ntoa (id));
1996 rc = OSPF_API_NOSUCHLSA;
1997 goto out;
1998 }
1999
2000 /* Schedule flushing of LSA from LSDB */
2001 /* NB: Multiple scheduling will produce a warning message, but harmless. */
2002 ospf_opaque_lsa_flush_schedule (old);
2003
2004out:
2005
2006 /* Send reply back to client including return code */
2007 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
2008 return rc;
2009}
2010
2011/* Flush self-originated opaque LSA */
2012int
2013apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2014 void *p_arg, int int_arg)
2015{
2016 struct param_t
2017 {
2018 struct ospf_apiserver *apiserv;
2019 u_char lsa_type;
2020 u_char opaque_type;
2021 }
2022 *param;
2023
2024 /* Sanity check */
2025 assert (lsa->data);
2026 assert (p_arg);
2027 param = (struct param_t *) p_arg;
2028
2029 /* If LSA matches type and opaque type then delete it */
2030 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2031 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2032 {
2033 ospf_opaque_lsa_flush_schedule (lsa);
2034 }
2035 return 0;
2036}
2037
2038/* Delete self-originated opaque LSAs of a given opaque type. This
2039 function is called when an application unregisters a given opaque
2040 type or a connection to an application closes and all those opaque
2041 LSAs need to be flushed the LSDB. */
2042void
2043ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2044 u_char lsa_type, u_char opaque_type)
2045{
2046 struct param_t
2047 {
2048 struct ospf_apiserver *apiserv;
2049 u_char lsa_type;
2050 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002051 } param;
2052 struct listnode *node;
paul99b7c5d2003-04-06 01:19:28 +00002053 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002054 struct ospf_area *area;
2055
paul99b7c5d2003-04-06 01:19:28 +00002056 ospf = ospf_lookup();
2057 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002058
2059 /* Set parameter struct. */
2060 param.apiserv = apiserv;
2061 param.lsa_type = lsa_type;
2062 param.opaque_type = opaque_type;
2063
paul2d33f152003-03-17 01:10:58 +00002064 switch (lsa_type)
2065 {
paul99b7c5d2003-04-06 01:19:28 +00002066 struct route_node *rn;
2067 struct ospf_lsa *lsa;
2068
paul2d33f152003-03-17 01:10:58 +00002069 case OSPF_OPAQUE_LINK_LSA:
paul87d6f872004-09-24 08:01:38 +00002070 LIST_LOOP (ospf->areas, area, node)
2071 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2072 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002073 break;
2074 case OSPF_OPAQUE_AREA_LSA:
paul87d6f872004-09-24 08:01:38 +00002075 LIST_LOOP (ospf->areas, area, node)
2076 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2077 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002078 break;
2079 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002080 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2081 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002082 break;
2083 default:
2084 break;
2085 }
2086 return;
paul2d33f152003-03-17 01:10:58 +00002087}
2088
2089
2090/* -----------------------------------------------------------
2091 * Followings are callback functions to handle opaque types
2092 * -----------------------------------------------------------
2093 */
2094
2095int
2096ospf_apiserver_new_if (struct interface *ifp)
2097{
2098 struct ospf_interface *oi;
2099
2100 /* For some strange reason it seems possible that we are invoked
2101 with an interface that has no name. This seems to happen during
2102 initialization. Return if this happens */
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 /* zlog_warn for debugging */
2111 zlog_warn ("ospf_apiserver_new_if");
2112 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2113 ifp->ifindex);
2114
2115 if (ifp->name[0] == '\0') {
2116 /* interface has empty name */
2117 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2118 return 0;
2119 }
2120
2121 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2122
2123 if (!oi) {
2124 /* This interface is known to Zebra but not to OSPF daemon yet. */
2125 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2126 ifp->name);
2127 return 0;
2128 }
2129
2130 assert (oi);
2131
2132 /* New interface added to OSPF, tell clients about it */
2133 if (listcount (apiserver_list) > 0) {
2134 ospf_apiserver_clients_notify_new_if (oi);
2135 }
2136 return 0;
2137}
2138
2139int
2140ospf_apiserver_del_if (struct interface *ifp)
2141{
2142 struct ospf_interface *oi;
2143
2144 /* zlog_warn for debugging */
2145 zlog_warn ("ospf_apiserver_del_if");
2146 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2147 ifp->ifindex);
2148
2149 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002150
2151 if (!oi) {
2152 /* This interface is known to Zebra but not to OSPF daemon
2153 anymore. No need to tell clients about it */
2154 return 0;
2155 }
paul2d33f152003-03-17 01:10:58 +00002156
2157 /* Interface deleted, tell clients about it */
2158 if (listcount (apiserver_list) > 0) {
2159 ospf_apiserver_clients_notify_del_if (oi);
2160 }
2161 return 0;
2162}
2163
2164void
2165ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2166{
2167 /* Tell clients about interface change */
2168
2169 /* zlog_warn for debugging */
2170 zlog_warn ("ospf_apiserver_ism_change");
2171 if (listcount (apiserver_list) > 0) {
2172 ospf_apiserver_clients_notify_ism_change (oi);
2173 }
2174
2175 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2176 zlog_warn ("old_state=%d", old_state);
2177 zlog_warn ("oi->state=%d", oi->state);
2178}
2179
2180void
2181ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2182{
2183 /* Neighbor status changed, tell clients about it */
2184 zlog_warn ("ospf_apiserver_nsm_change");
2185 if (listcount (apiserver_list) > 0) {
2186 ospf_apiserver_clients_notify_nsm_change (nbr);
2187 }
2188}
2189
2190void
2191ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2192{
2193 struct opaque_lsa
2194 {
2195 struct lsa_header header;
2196 u_char data[1]; /* opaque data have variable length. This is start
2197 address */
2198 };
2199 struct opaque_lsa *olsa;
2200 int opaquelen;
2201
2202 olsa = (struct opaque_lsa *) lsa->data;
2203
2204 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002205 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002206 else
paul87d6f872004-09-24 08:01:38 +00002207 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002208
2209 /* Output information about opaque LSAs */
2210 if (vty != NULL)
2211 {
2212 int i;
2213 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2214 opaquelen,
2215 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2216 VTY_NEWLINE);
2217 vty_out (vty, " Opaque data: ");
2218
2219 for (i = 0; i < opaquelen; i++)
2220 {
2221 vty_out (vty, "0x%x ", olsa->data[i]);
2222 }
2223 vty_out (vty, "%s", VTY_NEWLINE);
2224 }
2225 else
2226 {
2227 int i;
2228 zlog_info (" Added using OSPF API: %u octets of opaque data %s",
2229 opaquelen,
2230 VALID_OPAQUE_INFO_LEN (lsa->
2231 data) ? "" : "(Invalid length?)");
2232 zlog_info (" Opaque data: ");
2233
2234 for (i = 0; i < opaquelen; i++)
2235 {
2236 zlog_info ("0x%x ", olsa->data[i]);
2237 }
2238 zlog_info ("\n");
2239 }
2240 return;
2241}
2242
2243/* -----------------------------------------------------------
2244 * Followings are functions to notify clients about events
2245 * -----------------------------------------------------------
2246 */
2247
2248/* Send a message to all clients. This is useful for messages
2249 that need to be notified to all clients (such as interface
2250 changes) */
2251
2252void
2253ospf_apiserver_clients_notify_all (struct msg *msg)
2254{
paul87d6f872004-09-24 08:01:38 +00002255 struct listnode *node;
2256 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002257
2258 /* Send message to all clients */
paul87d6f872004-09-24 08:01:38 +00002259 LIST_LOOP (apiserver_list, apiserv, node)
2260 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002261}
2262
2263/* An interface is now ready to accept opaque LSAs. Notify all
2264 clients that registered to use this opaque type */
2265void
2266ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2267{
paul87d6f872004-09-24 08:01:38 +00002268 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002269 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002270 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002271
2272 assert (oi);
2273 if (!oi->address)
2274 {
2275 zlog_warn ("Interface has no address?");
2276 return;
2277 }
2278
2279 if (!ospf_apiserver_is_ready_type9 (oi))
2280 {
2281 zlog_warn ("Interface not ready for type 9?");
2282 return;
2283 }
2284
paul87d6f872004-09-24 08:01:38 +00002285 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002286 {
paul87d6f872004-09-24 08:01:38 +00002287 struct listnode *n2;
2288 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002289
paul87d6f872004-09-24 08:01:38 +00002290 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002291 {
paul2d33f152003-03-17 01:10:58 +00002292 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2293 {
2294 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2295 r->opaque_type,
2296 oi->address->u.prefix4);
2297 if (!msg)
2298 {
2299 zlog_warn
2300 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2301#ifdef NOTYET
2302 /* Cannot allocate new message. What should we do? */
2303 ospf_apiserver_free (apiserv);
2304#endif
2305 goto out;
2306 }
2307
2308 ospf_apiserver_send_msg (apiserv, msg);
2309 msg_free (msg);
2310 }
2311 }
2312 }
2313
2314out:
2315 return;
2316}
2317
2318void
2319ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2320{
paul87d6f872004-09-24 08:01:38 +00002321 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002322 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002323 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002324
2325 assert (area);
2326
2327 if (!ospf_apiserver_is_ready_type10 (area))
2328 {
2329 zlog_warn ("Area not ready for type 10?");
2330 return;
2331 }
2332
paul87d6f872004-09-24 08:01:38 +00002333 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002334 {
paul87d6f872004-09-24 08:01:38 +00002335 struct listnode *n2;
2336 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002337
paul87d6f872004-09-24 08:01:38 +00002338 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002339 {
paul2d33f152003-03-17 01:10:58 +00002340 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2341 {
2342 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2343 r->opaque_type, area->area_id);
2344 if (!msg)
2345 {
2346 zlog_warn
2347 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2348#ifdef NOTYET
2349 /* Cannot allocate new message. What should we do? */
2350 ospf_apiserver_free (apiserv);
2351#endif
paul87d6f872004-09-24 08:01:38 +00002352 goto out;
paul2d33f152003-03-17 01:10:58 +00002353 }
2354
2355 ospf_apiserver_send_msg (apiserv, msg);
2356 msg_free (msg);
2357 }
2358 }
2359 }
2360
2361out:
2362 return;
2363}
2364
2365
2366void
2367ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2368{
paul87d6f872004-09-24 08:01:38 +00002369 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002370 struct msg *msg;
2371 struct in_addr id_null = { 0L };
paul87d6f872004-09-24 08:01:38 +00002372 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002373
2374 assert (top);
2375
2376 if (!ospf_apiserver_is_ready_type11 (top))
2377 {
2378 zlog_warn ("AS not ready for type 11?");
2379 return;
2380 }
2381
paul87d6f872004-09-24 08:01:38 +00002382 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002383 {
paul87d6f872004-09-24 08:01:38 +00002384 struct listnode *n2;
2385 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002386
paul87d6f872004-09-24 08:01:38 +00002387 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002388 {
paul2d33f152003-03-17 01:10:58 +00002389 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2390 {
2391 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2392 r->opaque_type, id_null);
2393 if (!msg)
2394 {
2395 zlog_warn
2396 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2397#ifdef NOTYET
2398 /* Cannot allocate new message. What should we do? */
2399 ospf_apiserver_free (apiserv);
2400#endif
2401 goto out;
2402 }
2403
2404 ospf_apiserver_send_msg (apiserv, msg);
2405 msg_free (msg);
2406 }
2407 }
2408 }
2409
2410out:
2411 return;
2412}
2413
2414void
2415ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2416{
2417 struct msg *msg;
2418
2419 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2420 if (msg != NULL)
2421 {
2422 ospf_apiserver_clients_notify_all (msg);
2423 msg_free (msg);
2424 }
2425}
2426
2427void
2428ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2429{
2430 struct msg *msg;
2431
2432 msg = new_msg_del_if (0, oi->address->u.prefix4);
2433 if (msg != NULL)
2434 {
2435 ospf_apiserver_clients_notify_all (msg);
2436 msg_free (msg);
2437 }
2438}
2439
2440void
2441ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2442{
2443 struct msg *msg;
2444 struct in_addr ifaddr = { 0L };
2445 struct in_addr area_id = { 0L };
2446
2447 assert (oi);
2448 assert (oi->ifp);
2449
2450 if (oi->address)
2451 {
2452 ifaddr = oi->address->u.prefix4;
2453 }
2454 if (oi->area)
2455 {
2456 area_id = oi->area->area_id;
2457 }
2458
2459 msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status);
2460 if (!msg)
2461 {
2462 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2463 return;
2464 }
2465
2466 ospf_apiserver_clients_notify_all (msg);
2467 msg_free (msg);
2468}
2469
2470void
2471ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2472{
2473 struct msg *msg;
2474 struct in_addr ifaddr = { 0L };
2475 struct in_addr nbraddr = { 0L };
2476
2477 assert (nbr);
2478
2479 if (nbr->oi)
2480 {
2481 ifaddr = nbr->oi->address->u.prefix4;
2482 }
2483
2484 nbraddr = nbr->address.u.prefix4;
2485
2486 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2487 if (!msg)
2488 {
2489 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2490 return;
2491 }
2492
2493 ospf_apiserver_clients_notify_all (msg);
2494 msg_free (msg);
2495}
2496
2497void
2498apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2499{
2500 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002501 struct listnode *node;
2502 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002503
2504 /* Default area for AS-External and Opaque11 LSAs */
2505 struct in_addr area_id = { 0L };
2506
2507 /* Default interface for non Opaque9 LSAs */
2508 struct in_addr ifaddr = { 0L };
2509
2510 if (lsa->area)
2511 {
2512 area_id = lsa->area->area_id;
2513 }
2514 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2515 {
2516 assert (lsa->oi);
2517 ifaddr = lsa->oi->address->u.prefix4;
2518 }
2519
2520 /* Prepare message that can be sent to clients that have a matching
2521 filter */
2522 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2523 ifaddr, area_id,
2524 lsa->flags & OSPF_LSA_SELF, lsa->data);
2525 if (!msg)
2526 {
2527 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2528 return;
2529 }
2530
2531 /* Now send message to all clients with a matching filter */
paul87d6f872004-09-24 08:01:38 +00002532 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002533 {
paul2d33f152003-03-17 01:10:58 +00002534 struct lsa_filter_type *filter;
2535 u_int16_t mask;
2536 u_int32_t *area;
2537 int i;
2538
2539 /* Check filter for this client. */
2540 filter = apiserv->filter;
2541
2542 /* Check area IDs in case of non AS-E LSAs.
2543 * If filter has areas (num_areas > 0),
2544 * then one of the areas must match the area ID of this LSA. */
2545
2546 i = filter->num_areas;
2547 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2548 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2549 {
2550 i = 0;
2551 }
2552
2553 if (i > 0)
2554 {
2555 area = (u_int32_t *) (filter + 1);
2556 while (i)
2557 {
2558 if (*area == area_id.s_addr)
2559 {
2560 break;
2561 }
2562 i--;
2563 area++;
2564 }
2565 }
2566 else
2567 {
2568 i = 1;
2569 }
2570
2571 if (i > 0)
2572 {
2573 /* Area match. Check LSA type. */
2574 mask = ntohs (filter->typemask);
2575
2576 if (mask & Power2[lsa->data->type])
2577 {
2578 /* Type also matches. Check origin. */
2579 if ((filter->origin == ANY_ORIGIN) ||
2580 (filter->origin == IS_LSA_SELF (lsa)))
2581 {
2582 ospf_apiserver_send_msg (apiserv, msg);
2583 }
2584 }
2585 }
2586 }
2587 /* Free message since it is not used anymore */
2588 msg_free (msg);
2589}
2590
2591
2592/* -------------------------------------------------------------
2593 * Followings are hooks invoked when LSAs are updated or deleted
2594 * -------------------------------------------------------------
2595 */
2596
2597
2598int
2599apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2600{
2601 struct msg *msg;
2602 /* default area for AS-External and Opaque11 LSAs */
2603 struct in_addr area_id = { 0L };
2604
2605 /* default interface for non Opaque9 LSAs */
2606 struct in_addr ifaddr = { 0L };
2607
2608 /* Only notify this update if the LSA's age is smaller than
2609 MAXAGE. Otherwise clients would see LSA updates with max age just
2610 before they are deleted from the LSDB. LSA delete messages have
2611 MAXAGE too but should not be filtered. */
2612 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2613 return 0;
2614 }
2615
2616 if (lsa->area)
2617 {
2618 area_id = lsa->area->area_id;
2619 }
2620 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2621 {
2622 ifaddr = lsa->oi->address->u.prefix4;
2623 }
2624 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2625 ifaddr, area_id,
2626 lsa->flags & OSPF_LSA_SELF, lsa->data);
2627 if (!msg)
2628 {
2629 zlog_warn ("notify_clients_lsa: msg_new failed");
2630 return -1;
2631 }
2632 /* Notify all clients that new LSA is added/updated */
2633 apiserver_clients_lsa_change_notify (msgtype, lsa);
2634
2635 /* Clients made their own copies of msg so we can free msg here */
2636 msg_free (msg);
2637
2638 return 0;
2639}
2640
2641int
2642ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2643{
2644 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2645}
2646
2647int
2648ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2649{
2650 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2651}
2652
2653#endif /* SUPPORT_OSPF_API */
2654