blob: fa2d99305f62221c6fc7b2be439585d02fff1cda [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{
paul87d6f872004-09-24 08:01:38 +0000183 struct listnode *node;
184 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 */
paul87d6f872004-09-24 08:01:38 +0000191 LIST_LOOP (apiserver_list, apiserv, node)
192 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{
paul87d6f872004-09-24 08:01:38 +0000965 struct listnode *node, *nextnode;
paul2d33f152003-03-17 01:10:58 +0000966
paul87d6f872004-09-24 08:01:38 +0000967 for (node = listhead (apiserv->opaque_types); node; node = nextnode)
paul2d33f152003-03-17 01:10:58 +0000968 {
paul87d6f872004-09-24 08:01:38 +0000969 nextnode = node->next;
970
paul2d33f152003-03-17 01:10:58 +0000971 struct registered_opaque_type *regtype = node->data;
972
973 /* Check if we really registered this opaque type */
974 if (regtype->lsa_type == lsa_type &&
975 regtype->opaque_type == opaque_type)
976 {
977
978 /* Yes, we registered this opaque type. Flush
979 all existing opaque LSAs of this type */
980
981 ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
982 ospf_delete_opaque_functab (lsa_type, opaque_type);
983
984 /* Remove from list of registered opaque types */
985 listnode_delete (apiserv->opaque_types, regtype);
986
987 if (IS_DEBUG_OSPF_EVENT)
paul87d6f872004-09-24 08:01:38 +0000988 zlog_info ("API: Del LSA-type(%d)/Opaque-type(%d)"
989 " from apiserv(%p), total#(%d)",
990 lsa_type, opaque_type, apiserv,
991 listcount (apiserv->opaque_types));
paul2d33f152003-03-17 01:10:58 +0000992
993 return 0;
994 }
995 }
996
997 /* Opaque type is not registered */
998 zlog_warn ("Failed to unregister opaque type [%d/%d]",
999 lsa_type, opaque_type);
1000 return OSPF_API_OPAQUETYPENOTREGISTERED;
1001}
1002
1003
1004int
1005apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
1006 u_char lsa_type, u_char opaque_type)
1007{
paul87d6f872004-09-24 08:01:38 +00001008 struct listnode *node;
1009 struct registered_opaque_type *regtype;
paul2d33f152003-03-17 01:10:58 +00001010
paul87d6f872004-09-24 08:01:38 +00001011 /* XXX: how many types are there? if few, why not just a bitmap? */
1012 LIST_LOOP (apiserv->opaque_types, regtype, node)
paul2d33f152003-03-17 01:10:58 +00001013 {
paul2d33f152003-03-17 01:10:58 +00001014 /* Check if we really registered this opaque type */
1015 if (regtype->lsa_type == lsa_type &&
1016 regtype->opaque_type == opaque_type)
1017 {
1018 /* Yes registered */
1019 return 1;
1020 }
1021 }
1022 /* Not registered */
1023 return 0;
1024}
1025
1026int
1027ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
1028 struct msg *msg)
1029{
1030 struct msg_register_opaque_type *rmsg;
1031 u_char lsa_type;
1032 u_char opaque_type;
1033 int rc = 0;
1034
1035 /* Extract parameters from register opaque type message */
1036 rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
1037
1038 lsa_type = rmsg->lsatype;
1039 opaque_type = rmsg->opaquetype;
1040
1041 rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
1042
1043 /* Send a reply back to client including return code */
1044 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1045 if (rc < 0)
1046 goto out;
1047
1048 /* Now inform application about opaque types that are ready */
1049 switch (lsa_type)
1050 {
1051 case OSPF_OPAQUE_LINK_LSA:
1052 ospf_apiserver_notify_ready_type9 (apiserv);
1053 break;
1054 case OSPF_OPAQUE_AREA_LSA:
1055 ospf_apiserver_notify_ready_type10 (apiserv);
1056 break;
1057 case OSPF_OPAQUE_AS_LSA:
1058 ospf_apiserver_notify_ready_type11 (apiserv);
1059 break;
1060 }
1061out:
1062 return rc;
1063}
1064
1065
1066/* Notify specific client about all opaque types 9 that are ready. */
1067void
1068ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
1069{
paul87d6f872004-09-24 08:01:38 +00001070 struct listnode *node;
1071 struct listnode *n2;
paul99b7c5d2003-04-06 01:19:28 +00001072 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001073 struct ospf_interface *oi;
1074 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00001075
paul99b7c5d2003-04-06 01:19:28 +00001076 ospf = ospf_lookup ();
1077
paul87d6f872004-09-24 08:01:38 +00001078 LIST_LOOP (ospf->oiflist, oi, node)
paul2d33f152003-03-17 01:10:58 +00001079 {
paul2d33f152003-03-17 01:10:58 +00001080 /* Check if this interface is indeed ready for type 9 */
1081 if (!ospf_apiserver_is_ready_type9 (oi))
1082 continue;
1083
1084 /* Check for registered opaque type 9 types */
paul87d6f872004-09-24 08:01:38 +00001085 /* XXX: loop-de-loop - optimise me */
1086 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00001087 {
paul2d33f152003-03-17 01:10:58 +00001088 struct msg *msg;
1089
1090 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
1091 {
1092
1093 /* Yes, this opaque type is ready */
1094 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
1095 r->opaque_type,
1096 oi->address->u.prefix4);
1097 if (!msg)
1098 {
1099 zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
1100#ifdef NOTYET
1101 /* Cannot allocate new message. What should we do? */
1102 ospf_apiserver_free (apiserv);
1103#endif
1104 goto out;
1105 }
1106 ospf_apiserver_send_msg (apiserv, msg);
1107 msg_free (msg);
1108 }
1109 }
1110 }
1111
1112out:
1113 return;
1114}
1115
1116
1117/* Notify specific client about all opaque types 10 that are ready. */
1118void
1119ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
1120{
paul87d6f872004-09-24 08:01:38 +00001121 struct listnode *node;
1122 struct listnode *n2;
paul99b7c5d2003-04-06 01:19:28 +00001123 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001124 struct ospf_area *area;
1125
paul99b7c5d2003-04-06 01:19:28 +00001126 ospf = ospf_lookup ();
1127
paul87d6f872004-09-24 08:01:38 +00001128 LIST_LOOP (ospf->areas, area, node)
paul2d33f152003-03-17 01:10:58 +00001129 {
paul87d6f872004-09-24 08:01:38 +00001130 struct registered_opaque_type *r;
1131
paul2d33f152003-03-17 01:10:58 +00001132 if (!ospf_apiserver_is_ready_type10 (area))
1133 {
1134 continue;
1135 }
1136
1137 /* Check for registered opaque type 10 types */
paul87d6f872004-09-24 08:01:38 +00001138 /* XXX: loop in loop - optimise me */
1139 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00001140 {
paul2d33f152003-03-17 01:10:58 +00001141 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00001142
paul2d33f152003-03-17 01:10:58 +00001143 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
1144 {
1145 /* Yes, this opaque type is ready */
1146 msg =
1147 new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
1148 r->opaque_type, area->area_id);
1149 if (!msg)
1150 {
1151 zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
1152#ifdef NOTYET
1153 /* Cannot allocate new message. What should we do? */
1154 ospf_apiserver_free (apiserv);
1155#endif
1156 goto out;
1157 }
1158 ospf_apiserver_send_msg (apiserv, msg);
1159 msg_free (msg);
1160 }
1161 }
1162 }
1163
1164out:
1165 return;
1166}
1167
1168/* Notify specific client about all opaque types 11 that are ready */
1169void
1170ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
1171{
paul87d6f872004-09-24 08:01:38 +00001172 struct listnode *node;
paul99b7c5d2003-04-06 01:19:28 +00001173 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001174 struct registered_opaque_type *r;
paul99b7c5d2003-04-06 01:19:28 +00001175
1176 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001177
1178 /* Can type 11 be originated? */
paul99b7c5d2003-04-06 01:19:28 +00001179 if (!ospf_apiserver_is_ready_type11 (ospf))
paul2d33f152003-03-17 01:10:58 +00001180 goto out;;
1181
1182 /* Check for registered opaque type 11 types */
paul87d6f872004-09-24 08:01:38 +00001183 LIST_LOOP (apiserv->opaque_types, r, node)
paul2d33f152003-03-17 01:10:58 +00001184 {
paul2d33f152003-03-17 01:10:58 +00001185 struct msg *msg;
1186 struct in_addr noarea_id = { 0L };
1187
1188 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
1189 {
1190 /* Yes, this opaque type is ready */
1191 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
1192 r->opaque_type, noarea_id);
1193
1194 if (!msg)
1195 {
1196 zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
1197#ifdef NOTYET
1198 /* Cannot allocate new message. What should we do? */
1199 ospf_apiserver_free (apiserv);
1200#endif
1201 goto out;
1202 }
1203 ospf_apiserver_send_msg (apiserv, msg);
1204 msg_free (msg);
1205 }
1206 }
1207
1208out:
1209 return;
1210}
1211
1212int
1213ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
1214 struct msg *msg)
1215{
1216 struct msg_unregister_opaque_type *umsg;
1217 u_char ltype;
1218 u_char otype;
1219 int rc = 0;
1220
1221 /* Extract parameters from unregister opaque type message */
1222 umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
1223
1224 ltype = umsg->lsatype;
1225 otype = umsg->opaquetype;
1226
1227 rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
1228
1229 /* Send a reply back to client including return code */
1230 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1231
1232 return rc;
1233}
1234
1235
1236/* -----------------------------------------------------------
1237 * Following are functions for event (filter) registration.
1238 * -----------------------------------------------------------
1239 */
1240int
1241ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
1242 struct msg *msg)
1243{
1244 struct msg_register_event *rmsg;
1245 int rc;
1246 u_int32_t seqnum;
1247
1248 rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
1249
1250 /* Get request sequence number */
1251 seqnum = msg_get_seq (msg);
1252
1253 /* Free existing filter in apiserv. */
1254 XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1255 /* Alloc new space for filter. */
1256
1257 apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
1258 ntohs (msg->hdr.msglen));
1259 if (apiserv->filter)
1260 {
1261 /* copy it over. */
1262 memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
1263 rc = OSPF_API_OK;
1264 }
1265 else
1266 {
1267 rc = OSPF_API_NOMEMORY;
1268 }
1269 /* Send a reply back to client with return code */
1270 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1271 return rc;
1272}
1273
1274
1275/* -----------------------------------------------------------
1276 * Followings are functions for LSDB synchronization.
1277 * -----------------------------------------------------------
1278 */
1279
1280int
1281apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
1282{
1283 struct ospf_apiserver *apiserv;
1284 int seqnum;
1285 struct msg *msg;
1286 struct param_t
1287 {
1288 struct ospf_apiserver *apiserv;
1289 struct lsa_filter_type *filter;
1290 }
1291 *param;
1292 int rc = -1;
1293
1294 /* Sanity check */
1295 assert (lsa->data);
1296 assert (p_arg);
1297
1298 param = (struct param_t *) p_arg;
1299 apiserv = param->apiserv;
1300 seqnum = (u_int32_t) int_arg;
1301
1302 /* Check origin in filter. */
1303 if ((param->filter->origin == ANY_ORIGIN) ||
1304 (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
1305 {
1306
1307 /* Default area for AS-External and Opaque11 LSAs */
1308 struct in_addr area_id = { 0L };
1309
1310 /* Default interface for non Opaque9 LSAs */
1311 struct in_addr ifaddr = { 0L };
1312
1313 if (lsa->area)
1314 {
1315 area_id = lsa->area->area_id;
1316 }
1317 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
1318 {
1319 ifaddr = lsa->oi->address->u.prefix4;
1320 }
1321
1322 msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
1323 seqnum,
1324 ifaddr, area_id,
1325 lsa->flags & OSPF_LSA_SELF, lsa->data);
1326 if (!msg)
1327 {
1328 zlog_warn ("apiserver_sync_callback: new_msg_update failed");
1329#ifdef NOTYET
1330 /* Cannot allocate new message. What should we do? */
1331/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
1332#endif
1333 goto out;
1334 }
1335
1336 /* Send LSA */
1337 ospf_apiserver_send_msg (apiserv, msg);
1338 msg_free (msg);
1339 }
1340 rc = 0;
1341
1342out:
1343 return rc;
1344}
1345
1346int
1347ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
1348 struct msg *msg)
1349{
paul87d6f872004-09-24 08:01:38 +00001350 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00001351 u_int32_t seqnum;
1352 int rc = 0;
1353 struct msg_sync_lsdb *smsg;
1354 struct param_t
1355 {
1356 struct ospf_apiserver *apiserv;
1357 struct lsa_filter_type *filter;
1358 }
1359 param;
1360 u_int16_t mask;
paul99b7c5d2003-04-06 01:19:28 +00001361 struct route_node *rn;
1362 struct ospf_lsa *lsa;
1363 struct ospf *ospf;
paul87d6f872004-09-24 08:01:38 +00001364 struct ospf_area *area;
paul99b7c5d2003-04-06 01:19:28 +00001365
1366 ospf = ospf_lookup ();
paul2d33f152003-03-17 01:10:58 +00001367
1368 /* Get request sequence number */
1369 seqnum = msg_get_seq (msg);
1370 /* Set sync msg. */
1371 smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
1372
1373 /* Set parameter struct. */
1374 param.apiserv = apiserv;
1375 param.filter = &smsg->filter;
1376
1377 /* Remember mask. */
1378 mask = ntohs (smsg->filter.typemask);
1379
1380 /* Iterate over all areas. */
paul87d6f872004-09-24 08:01:38 +00001381 LIST_LOOP (ospf->areas, area, node)
paul2d33f152003-03-17 01:10:58 +00001382 {
paul2d33f152003-03-17 01:10:58 +00001383 int i;
1384 u_int32_t *area_id = NULL;
paul87d6f872004-09-24 08:01:38 +00001385
paul2d33f152003-03-17 01:10:58 +00001386 /* Compare area_id with area_ids in sync request. */
1387 if ((i = smsg->filter.num_areas) > 0)
1388 {
1389 /* Let area_id point to the list of area IDs,
1390 * which is at the end of smsg->filter. */
1391 area_id = (u_int32_t *) (&smsg->filter + 1);
1392 while (i)
1393 {
1394 if (*area_id == area->area_id.s_addr)
1395 {
1396 break;
1397 }
1398 i--;
1399 area_id++;
1400 }
1401 }
1402 else
1403 {
1404 i = 1;
1405 }
1406
1407 /* If area was found, then i>0 here. */
1408 if (i)
1409 {
1410 /* Check msg type. */
1411 if (mask & Power2[OSPF_ROUTER_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001412 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
1413 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001414 if (mask & Power2[OSPF_NETWORK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001415 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
1416 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001417 if (mask & Power2[OSPF_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001418 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
1419 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001420 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001421 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
1422 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001423 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001424 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
1425 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001426 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001427 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
1428 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001429 }
1430 }
1431
1432 /* For AS-external LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001433 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001434 {
1435 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001436 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
1437 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001438 }
1439
1440 /* For AS-external opaque LSAs */
paul99b7c5d2003-04-06 01:19:28 +00001441 if (ospf->lsdb)
paul2d33f152003-03-17 01:10:58 +00001442 {
1443 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
paul99b7c5d2003-04-06 01:19:28 +00001444 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
1445 apiserver_sync_callback(lsa, (void *) &param, seqnum);
paul2d33f152003-03-17 01:10:58 +00001446 }
1447
1448 /* Send a reply back to client with return code */
1449 rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
1450 return rc;
1451}
1452
1453
1454/* -----------------------------------------------------------
1455 * Followings are functions to originate or update LSA
1456 * from an application.
1457 * -----------------------------------------------------------
1458 */
1459
1460/* Create a new internal opaque LSA by taking prototype and filling in
1461 missing fields such as age, sequence number, advertising router,
1462 checksum and so on. The interface parameter is used for type 9
1463 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1464 nor interface. */
1465
1466struct ospf_lsa *
1467ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
1468 struct ospf_interface *oi,
1469 struct lsa_header *protolsa)
1470{
1471 struct stream *s;
1472 struct lsa_header *newlsa;
1473 struct ospf_lsa *new = NULL;
1474 u_char options = 0x0;
1475 u_int16_t length;
1476
paul99b7c5d2003-04-06 01:19:28 +00001477 struct ospf *ospf;
paul7d5e2682003-04-05 19:41:07 +00001478
paul99b7c5d2003-04-06 01:19:28 +00001479 ospf = ospf_lookup();
paul7d5e2682003-04-05 19:41:07 +00001480 assert(ospf);
1481
paul2d33f152003-03-17 01:10:58 +00001482 /* Create a stream for internal opaque LSA */
1483 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1484 {
1485 zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
1486 return NULL;
1487 }
1488
1489 newlsa = (struct lsa_header *) STREAM_DATA (s);
1490
1491 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1492 have to set options? */
1493
1494 if (area)
1495 {
1496 options = LSA_OPTIONS_GET (area);
paul5549c6b2003-07-09 15:46:33 +00001497 options |= LSA_OPTIONS_NSSA_GET (area);
paul2d33f152003-03-17 01:10:58 +00001498 }
1499
1500 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1501
1502 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1503 {
1504 zlog_info ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1505 protolsa->type, inet_ntoa (protolsa->id));
1506 }
1507
1508 /* Set opaque-LSA header fields. */
paul68980082003-03-25 05:07:42 +00001509 lsa_header_set (s, options, protolsa->type, protolsa->id,
paul7d5e2682003-04-05 19:41:07 +00001510 ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001511
1512 /* Set opaque-LSA body fields. */
1513 stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
1514 ntohs (protolsa->length) - sizeof (struct lsa_header));
1515
1516 /* Determine length of LSA. */
1517 length = stream_get_endp (s);
1518 newlsa->length = htons (length);
1519
1520 /* Create OSPF LSA. */
1521 if ((new = ospf_lsa_new ()) == NULL)
1522 {
1523 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
1524 stream_free (s);
1525 return NULL;
1526 }
1527
1528 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1529 {
1530 zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
1531 ospf_lsa_free (new);
1532 new = NULL;
1533 stream_free (s);
1534 return NULL;
1535 }
1536
1537 new->area = area;
1538 new->oi = oi;
1539
1540 SET_FLAG (new->flags, OSPF_LSA_SELF);
1541 memcpy (new->data, newlsa, length);
1542 stream_free (s);
1543
1544 return new;
1545}
1546
1547
1548int
1549ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
1550{
1551 /* Type 9 opaque LSA can be originated if there is at least one
1552 active opaque-capable neighbor attached to the outgoing
1553 interface. */
1554
paula15f45d2003-03-28 01:50:03 +00001555 return (ospf_nbr_count_opaque_capable (oi) > 0);
paul2d33f152003-03-17 01:10:58 +00001556}
1557
1558int
1559ospf_apiserver_is_ready_type10 (struct ospf_area *area)
1560{
1561 /* Type 10 opaque LSA can be originated if there is at least one
1562 interface belonging to the area that has an active opaque-capable
1563 neighbor. */
paul87d6f872004-09-24 08:01:38 +00001564 struct listnode *node;
1565 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001566
paul87d6f872004-09-24 08:01:38 +00001567 LIST_LOOP (area->oiflist, oi, node)
1568 /* Is there an active neighbor attached to this interface? */
1569 if (ospf_apiserver_is_ready_type9 (oi))
1570 return 1;
paul2d33f152003-03-17 01:10:58 +00001571
paul2d33f152003-03-17 01:10:58 +00001572 /* No active neighbor in area */
1573 return 0;
1574}
1575
1576int
1577ospf_apiserver_is_ready_type11 (struct ospf *ospf)
1578{
1579 /* Type 11 opaque LSA can be originated if there is at least one interface
1580 that has an active opaque-capable neighbor. */
paul87d6f872004-09-24 08:01:38 +00001581 struct listnode *node;
1582 struct ospf_interface *oi;
paul2d33f152003-03-17 01:10:58 +00001583
paul87d6f872004-09-24 08:01:38 +00001584 LIST_LOOP (ospf->oiflist, oi, node)
1585 /* Is there an active neighbor attached to this interface? */
1586 if (ospf_apiserver_is_ready_type9 (oi))
1587 return 1;
paul2d33f152003-03-17 01:10:58 +00001588
paul2d33f152003-03-17 01:10:58 +00001589 /* No active neighbor at all */
1590 return 0;
1591}
1592
1593
1594int
1595ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
1596 struct msg *msg)
1597{
1598 struct msg_originate_request *omsg;
1599 struct lsa_header *data;
1600 struct ospf_lsa *new;
1601 struct ospf_lsa *old;
1602 struct ospf_area *area = NULL;
1603 struct ospf_interface *oi = NULL;
1604 struct ospf_lsdb *lsdb = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001605 struct ospf *ospf;
paul2d33f152003-03-17 01:10:58 +00001606 int lsa_type, opaque_type;
1607 int ready = 0;
1608 int rc = 0;
paula15f45d2003-03-28 01:50:03 +00001609
paul99b7c5d2003-04-06 01:19:28 +00001610 ospf = ospf_lookup();
1611
paul2d33f152003-03-17 01:10:58 +00001612 /* Extract opaque LSA data from message */
1613 omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
1614 data = &omsg->data;
1615
1616 /* Determine interface for type9 or area for type10 LSAs. */
1617 switch (data->type)
1618 {
1619 case OSPF_OPAQUE_LINK_LSA:
1620 oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
1621 if (!oi)
1622 {
1623 zlog_warn ("apiserver_originate: unknown interface %s",
1624 inet_ntoa (omsg->ifaddr));
1625 rc = OSPF_API_NOSUCHINTERFACE;
1626 goto out;
1627 }
1628 area = oi->area;
1629 lsdb = area->lsdb;
1630 break;
1631 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001632 area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001633 if (!area)
1634 {
1635 zlog_warn ("apiserver_originate: unknown area %s",
1636 inet_ntoa (omsg->area_id));
1637 rc = OSPF_API_NOSUCHAREA;
1638 goto out;
1639 }
1640 lsdb = area->lsdb;
1641 break;
1642 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001643 lsdb = ospf->lsdb;
paul2d33f152003-03-17 01:10:58 +00001644 break;
1645 default:
1646 /* We can only handle opaque types here */
1647 zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
1648 data->type);
1649 rc = OSPF_API_ILLEGALLSATYPE;
1650 goto out;
1651 }
1652
1653 /* Check if we registered this opaque type */
1654 lsa_type = data->type;
1655 opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
1656
1657 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1658 {
1659 zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1660 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1661 goto out;
1662 }
1663
1664 /* Make sure that the neighbors are ready before we can originate */
1665 switch (data->type)
1666 {
1667 case OSPF_OPAQUE_LINK_LSA:
1668 ready = ospf_apiserver_is_ready_type9 (oi);
1669 break;
1670 case OSPF_OPAQUE_AREA_LSA:
1671 ready = ospf_apiserver_is_ready_type10 (area);
1672 break;
1673 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001674 ready = ospf_apiserver_is_ready_type11 (ospf);
paul2d33f152003-03-17 01:10:58 +00001675 break;
1676 default:
1677 break;
1678 }
1679
1680 if (!ready)
1681 {
1682 zlog_warn ("Neighbors not ready to originate type %d", data->type);
1683 rc = OSPF_API_NOTREADY;
1684 goto out;
1685 }
1686
1687 /* Create OSPF's internal opaque LSA representation */
1688 new = ospf_apiserver_opaque_lsa_new (area, oi, data);
1689 if (!new)
1690 {
1691 rc = OSPF_API_NOMEMORY; /* XXX */
1692 goto out;
1693 }
1694
1695 /* Determine if LSA is new or an update for an existing one. */
1696 old = ospf_lsdb_lookup (lsdb, new);
1697
1698 if (!old)
1699 {
1700 /* New LSA install in LSDB. */
1701 rc = ospf_apiserver_originate1 (new);
1702 }
1703 else
1704 {
1705 /*
1706 * Keep the new LSA instance in the "waiting place" until the next
1707 * refresh timing. If several LSA update requests for the same LSID
1708 * have issued by peer, the last one takes effect.
1709 */
1710 new->lsdb = &apiserv->reserve;
1711 ospf_lsdb_add (&apiserv->reserve, new);
1712
1713 /* Kick the scheduler function. */
1714 ospf_opaque_lsa_refresh_schedule (old);
1715 }
1716
1717out:
1718
1719 /* Send a reply back to client with return code */
1720 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
1721 return rc;
1722}
1723
1724
1725/* -----------------------------------------------------------
1726 * Flood an LSA within its flooding scope.
1727 * -----------------------------------------------------------
1728 */
1729
1730/* XXX We can probably use ospf_flood_through instead of this function
1731 but then we need the neighbor parameter. If we set nbr to
1732 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1733
1734void
1735ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
1736{
1737 assert (lsa);
1738
1739 switch (lsa->data->type)
1740 {
1741 case OSPF_OPAQUE_LINK_LSA:
1742 /* Increment counters? XXX */
1743
1744 /* Flood LSA through local network. */
1745 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1746 break;
1747 case OSPF_OPAQUE_AREA_LSA:
1748 /* Update LSA origination count. */
1749 assert (lsa->area);
paula15f45d2003-03-28 01:50:03 +00001750 lsa->area->ospf->lsa_originate_count++;
paul2d33f152003-03-17 01:10:58 +00001751
1752 /* Flood LSA through area. */
1753 ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
1754 break;
1755 case OSPF_OPAQUE_AS_LSA:
paul7d5e2682003-04-05 19:41:07 +00001756 {
paul99b7c5d2003-04-06 01:19:28 +00001757 struct ospf *ospf;
1758
1759 ospf = ospf_lookup();
1760 assert(ospf);
1761
paul7d5e2682003-04-05 19:41:07 +00001762 /* Increment counters? XXX */
paul2d33f152003-03-17 01:10:58 +00001763
paul7d5e2682003-04-05 19:41:07 +00001764 /* Flood LSA through AS. */
paul99b7c5d2003-04-06 01:19:28 +00001765 ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
paul7d5e2682003-04-05 19:41:07 +00001766 break;
1767 }
paul2d33f152003-03-17 01:10:58 +00001768 }
1769}
1770
1771int
1772ospf_apiserver_originate1 (struct ospf_lsa *lsa)
1773{
paul99b7c5d2003-04-06 01:19:28 +00001774 struct ospf *ospf;
1775
1776 ospf = ospf_lookup();
1777 assert(ospf);
1778
paul2d33f152003-03-17 01:10:58 +00001779 /* Install this LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001780 if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
paul2d33f152003-03-17 01:10:58 +00001781 {
1782 zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
1783 return -1;
1784 }
1785
1786 /* Flood LSA within scope */
1787
1788#ifdef NOTYET
1789 /*
1790 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1791 * parameter, and thus it does not cause SIGSEGV error.
1792 */
1793 ospf_flood_through (NULL /*nbr */ , lsa);
1794#else /* NOTYET */
1795
1796 ospf_apiserver_flood_opaque_lsa (lsa);
1797#endif /* NOTYET */
1798
1799 return 0;
1800}
1801
1802
1803/* Opaque LSAs of type 9 on a specific interface can now be
1804 originated. Tell clients that registered type 9. */
1805int
1806ospf_apiserver_lsa9_originator (void *arg)
1807{
1808 struct ospf_interface *oi;
1809
1810 oi = (struct ospf_interface *) arg;
1811 if (listcount (apiserver_list) > 0) {
1812 ospf_apiserver_clients_notify_ready_type9 (oi);
1813 }
1814 return 0;
1815}
1816
1817int
1818ospf_apiserver_lsa10_originator (void *arg)
1819{
1820 struct ospf_area *area;
1821
1822 area = (struct ospf_area *) arg;
1823 if (listcount (apiserver_list) > 0) {
1824 ospf_apiserver_clients_notify_ready_type10 (area);
1825 }
1826 return 0;
1827}
1828
1829int
1830ospf_apiserver_lsa11_originator (void *arg)
1831{
1832 struct ospf *ospf;
1833
1834 ospf = (struct ospf *) arg;
1835 if (listcount (apiserver_list) > 0) {
1836 ospf_apiserver_clients_notify_ready_type11 (ospf);
1837 }
1838 return 0;
1839}
1840
1841
1842/* Periodically refresh opaque LSAs so that they do not expire in
1843 other routers. */
1844void
1845ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
1846{
1847 struct ospf_apiserver *apiserv;
1848 struct ospf_lsa *new = NULL;
paul99b7c5d2003-04-06 01:19:28 +00001849 struct ospf * ospf;
1850
1851 ospf = ospf_lookup();
1852 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001853
1854 apiserv = lookup_apiserver_by_lsa (lsa);
1855 if (!apiserv)
1856 {
1857 zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
1858 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1859 }
1860
1861 if (IS_LSA_MAXAGE (lsa))
1862 {
1863 ospf_opaque_lsa_flush_schedule (lsa);
1864 goto out;
1865 }
1866
1867 /* Check if updated version of LSA instance has already prepared. */
1868 new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
1869 if (!new)
1870 {
1871 /* This is a periodic refresh, driven by core OSPF mechanism. */
1872 new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
1873 if (!new)
1874 {
1875 zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1876 goto out;
1877 }
1878 }
1879 else
1880 {
1881 /* This is a forcible refresh, requested by OSPF-API client. */
1882 ospf_lsdb_delete (&apiserv->reserve, new);
1883 new->lsdb = NULL;
1884 }
1885
1886 /* Increment sequence number */
1887 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1888
1889 /* New LSA is in same area. */
1890 new->area = lsa->area;
1891 SET_FLAG (new->flags, OSPF_LSA_SELF);
1892
1893 /* Install LSA into LSDB. */
paul99b7c5d2003-04-06 01:19:28 +00001894 if (ospf_lsa_install (ospf, new->oi, new) == NULL)
paul2d33f152003-03-17 01:10:58 +00001895 {
1896 zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1897 ospf_lsa_free (new);
1898 goto out;
1899 }
1900
1901 /* Flood updated LSA through interface, area or AS */
1902
1903#ifdef NOTYET
1904 ospf_flood_through (NULL /*nbr */ , new);
1905#endif /* NOTYET */
1906 ospf_apiserver_flood_opaque_lsa (new);
1907
1908 /* Debug logging. */
1909 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1910 {
1911 zlog_info ("LSA[Type%d:%s]: Refresh Opaque LSA",
1912 new->data->type, inet_ntoa (new->data->id));
1913 ospf_lsa_header_dump (new->data);
1914 }
1915
1916out:
1917 return;
1918}
1919
1920
1921/* -----------------------------------------------------------
1922 * Followings are functions to delete LSAs
1923 * -----------------------------------------------------------
1924 */
1925
1926int
1927ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
1928 struct msg *msg)
1929{
1930 struct msg_delete_request *dmsg;
1931 struct ospf_lsa *old;
1932 struct ospf_area *area = NULL;
1933 struct in_addr id;
1934 int lsa_type, opaque_type;
1935 int rc = 0;
paul99b7c5d2003-04-06 01:19:28 +00001936 struct ospf * ospf;
1937
1938 ospf = ospf_lookup();
1939 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00001940
1941 /* Extract opaque LSA from message */
1942 dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
1943
1944 /* Lookup area for link-local and area-local opaque LSAs */
1945 switch (dmsg->lsa_type)
1946 {
1947 case OSPF_OPAQUE_LINK_LSA:
1948 case OSPF_OPAQUE_AREA_LSA:
paul99b7c5d2003-04-06 01:19:28 +00001949 area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
paul2d33f152003-03-17 01:10:58 +00001950 if (!area)
1951 {
1952 zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
1953 inet_ntoa (dmsg->area_id));
1954 rc = OSPF_API_NOSUCHAREA;
1955 goto out;
1956 }
1957 break;
1958 case OSPF_OPAQUE_AS_LSA:
1959 /* AS-external opaque LSAs have no designated area */
1960 area = NULL;
1961 break;
1962 default:
1963 zlog_warn
1964 ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1965 dmsg->lsa_type);
1966 rc = OSPF_API_ILLEGALLSATYPE;
1967 goto out;
1968 }
1969
1970 /* Check if we registered this opaque type */
1971 lsa_type = dmsg->lsa_type;
1972 opaque_type = dmsg->opaque_type;
1973
1974 if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
1975 {
1976 zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
1977 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1978 goto out;
1979 }
1980
1981 /* opaque_id is in network byte order */
1982 id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
1983 ntohl (dmsg->opaque_id)));
1984
1985 /*
1986 * Even if the target LSA has once scheduled to flush, it remains in
1987 * the LSDB until it is finally handled by the maxage remover thread.
1988 * Therefore, the lookup function below may return non-NULL result.
1989 */
paul99b7c5d2003-04-06 01:19:28 +00001990 old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
paul2d33f152003-03-17 01:10:58 +00001991 if (!old)
1992 {
1993 zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1994 dmsg->lsa_type, inet_ntoa (id));
1995 rc = OSPF_API_NOSUCHLSA;
1996 goto out;
1997 }
1998
1999 /* Schedule flushing of LSA from LSDB */
2000 /* NB: Multiple scheduling will produce a warning message, but harmless. */
2001 ospf_opaque_lsa_flush_schedule (old);
2002
2003out:
2004
2005 /* Send reply back to client including return code */
2006 rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
2007 return rc;
2008}
2009
2010/* Flush self-originated opaque LSA */
2011int
2012apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
2013 void *p_arg, int int_arg)
2014{
2015 struct param_t
2016 {
2017 struct ospf_apiserver *apiserv;
2018 u_char lsa_type;
2019 u_char opaque_type;
2020 }
2021 *param;
2022
2023 /* Sanity check */
2024 assert (lsa->data);
2025 assert (p_arg);
2026 param = (struct param_t *) p_arg;
2027
2028 /* If LSA matches type and opaque type then delete it */
2029 if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
2030 && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
2031 {
2032 ospf_opaque_lsa_flush_schedule (lsa);
2033 }
2034 return 0;
2035}
2036
2037/* Delete self-originated opaque LSAs of a given opaque type. This
2038 function is called when an application unregisters a given opaque
2039 type or a connection to an application closes and all those opaque
2040 LSAs need to be flushed the LSDB. */
2041void
2042ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
2043 u_char lsa_type, u_char opaque_type)
2044{
2045 struct param_t
2046 {
2047 struct ospf_apiserver *apiserv;
2048 u_char lsa_type;
2049 u_char opaque_type;
paul87d6f872004-09-24 08:01:38 +00002050 } param;
2051 struct listnode *node;
paul99b7c5d2003-04-06 01:19:28 +00002052 struct ospf * ospf;
paul87d6f872004-09-24 08:01:38 +00002053 struct ospf_area *area;
2054
paul99b7c5d2003-04-06 01:19:28 +00002055 ospf = ospf_lookup();
2056 assert(ospf);
paul2d33f152003-03-17 01:10:58 +00002057
2058 /* Set parameter struct. */
2059 param.apiserv = apiserv;
2060 param.lsa_type = lsa_type;
2061 param.opaque_type = opaque_type;
2062
paul2d33f152003-03-17 01:10:58 +00002063 switch (lsa_type)
2064 {
paul99b7c5d2003-04-06 01:19:28 +00002065 struct route_node *rn;
2066 struct ospf_lsa *lsa;
2067
paul2d33f152003-03-17 01:10:58 +00002068 case OSPF_OPAQUE_LINK_LSA:
paul87d6f872004-09-24 08:01:38 +00002069 LIST_LOOP (ospf->areas, area, node)
2070 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2071 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002072 break;
2073 case OSPF_OPAQUE_AREA_LSA:
paul87d6f872004-09-24 08:01:38 +00002074 LIST_LOOP (ospf->areas, area, node)
2075 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2076 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002077 break;
2078 case OSPF_OPAQUE_AS_LSA:
paul99b7c5d2003-04-06 01:19:28 +00002079 LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
2080 apiserver_flush_opaque_type_callback(lsa, (void *) &param, 0);
paul2d33f152003-03-17 01:10:58 +00002081 break;
2082 default:
2083 break;
2084 }
2085 return;
paul2d33f152003-03-17 01:10:58 +00002086}
2087
2088
2089/* -----------------------------------------------------------
2090 * Followings are callback functions to handle opaque types
2091 * -----------------------------------------------------------
2092 */
2093
2094int
2095ospf_apiserver_new_if (struct interface *ifp)
2096{
2097 struct ospf_interface *oi;
2098
2099 /* For some strange reason it seems possible that we are invoked
2100 with an interface that has no name. This seems to happen during
2101 initialization. Return if this happens */
2102
2103 if (ifp->name[0] == '\0') {
2104 /* interface has empty name */
2105 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2106 return 0;
2107 }
2108
2109 /* zlog_warn for debugging */
2110 zlog_warn ("ospf_apiserver_new_if");
2111 zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2112 ifp->ifindex);
2113
2114 if (ifp->name[0] == '\0') {
2115 /* interface has empty name */
2116 zlog_warn ("ospf_apiserver_new_if: interface has no name?");
2117 return 0;
2118 }
2119
2120 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
2121
2122 if (!oi) {
2123 /* This interface is known to Zebra but not to OSPF daemon yet. */
2124 zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
2125 ifp->name);
2126 return 0;
2127 }
2128
2129 assert (oi);
2130
2131 /* New interface added to OSPF, tell clients about it */
2132 if (listcount (apiserver_list) > 0) {
2133 ospf_apiserver_clients_notify_new_if (oi);
2134 }
2135 return 0;
2136}
2137
2138int
2139ospf_apiserver_del_if (struct interface *ifp)
2140{
2141 struct ospf_interface *oi;
2142
2143 /* zlog_warn for debugging */
2144 zlog_warn ("ospf_apiserver_del_if");
2145 zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2146 ifp->ifindex);
2147
2148 oi = ospf_apiserver_if_lookup_by_ifp (ifp);
paul2be32b72003-03-21 15:11:58 +00002149
2150 if (!oi) {
2151 /* This interface is known to Zebra but not to OSPF daemon
2152 anymore. No need to tell clients about it */
2153 return 0;
2154 }
paul2d33f152003-03-17 01:10:58 +00002155
2156 /* Interface deleted, tell clients about it */
2157 if (listcount (apiserver_list) > 0) {
2158 ospf_apiserver_clients_notify_del_if (oi);
2159 }
2160 return 0;
2161}
2162
2163void
2164ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
2165{
2166 /* Tell clients about interface change */
2167
2168 /* zlog_warn for debugging */
2169 zlog_warn ("ospf_apiserver_ism_change");
2170 if (listcount (apiserver_list) > 0) {
2171 ospf_apiserver_clients_notify_ism_change (oi);
2172 }
2173
2174 zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
2175 zlog_warn ("old_state=%d", old_state);
2176 zlog_warn ("oi->state=%d", oi->state);
2177}
2178
2179void
2180ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
2181{
2182 /* Neighbor status changed, tell clients about it */
2183 zlog_warn ("ospf_apiserver_nsm_change");
2184 if (listcount (apiserver_list) > 0) {
2185 ospf_apiserver_clients_notify_nsm_change (nbr);
2186 }
2187}
2188
2189void
2190ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
2191{
2192 struct opaque_lsa
2193 {
2194 struct lsa_header header;
2195 u_char data[1]; /* opaque data have variable length. This is start
2196 address */
2197 };
2198 struct opaque_lsa *olsa;
2199 int opaquelen;
2200
2201 olsa = (struct opaque_lsa *) lsa->data;
2202
2203 if (VALID_OPAQUE_INFO_LEN (lsa->data))
paul87d6f872004-09-24 08:01:38 +00002204 opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
paul2d33f152003-03-17 01:10:58 +00002205 else
paul87d6f872004-09-24 08:01:38 +00002206 opaquelen = 0;
paul2d33f152003-03-17 01:10:58 +00002207
2208 /* Output information about opaque LSAs */
2209 if (vty != NULL)
2210 {
2211 int i;
2212 vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
2213 opaquelen,
2214 VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
2215 VTY_NEWLINE);
2216 vty_out (vty, " Opaque data: ");
2217
2218 for (i = 0; i < opaquelen; i++)
2219 {
2220 vty_out (vty, "0x%x ", olsa->data[i]);
2221 }
2222 vty_out (vty, "%s", VTY_NEWLINE);
2223 }
2224 else
2225 {
2226 int i;
2227 zlog_info (" Added using OSPF API: %u octets of opaque data %s",
2228 opaquelen,
2229 VALID_OPAQUE_INFO_LEN (lsa->
2230 data) ? "" : "(Invalid length?)");
2231 zlog_info (" Opaque data: ");
2232
2233 for (i = 0; i < opaquelen; i++)
2234 {
2235 zlog_info ("0x%x ", olsa->data[i]);
2236 }
2237 zlog_info ("\n");
2238 }
2239 return;
2240}
2241
2242/* -----------------------------------------------------------
2243 * Followings are functions to notify clients about events
2244 * -----------------------------------------------------------
2245 */
2246
2247/* Send a message to all clients. This is useful for messages
2248 that need to be notified to all clients (such as interface
2249 changes) */
2250
2251void
2252ospf_apiserver_clients_notify_all (struct msg *msg)
2253{
paul87d6f872004-09-24 08:01:38 +00002254 struct listnode *node;
2255 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002256
2257 /* Send message to all clients */
paul87d6f872004-09-24 08:01:38 +00002258 LIST_LOOP (apiserver_list, apiserv, node)
2259 ospf_apiserver_send_msg (apiserv, msg);
paul2d33f152003-03-17 01:10:58 +00002260}
2261
2262/* An interface is now ready to accept opaque LSAs. Notify all
2263 clients that registered to use this opaque type */
2264void
2265ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
2266{
paul87d6f872004-09-24 08:01:38 +00002267 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002268 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002269 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002270
2271 assert (oi);
2272 if (!oi->address)
2273 {
2274 zlog_warn ("Interface has no address?");
2275 return;
2276 }
2277
2278 if (!ospf_apiserver_is_ready_type9 (oi))
2279 {
2280 zlog_warn ("Interface not ready for type 9?");
2281 return;
2282 }
2283
paul87d6f872004-09-24 08:01:38 +00002284 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002285 {
paul87d6f872004-09-24 08:01:38 +00002286 struct listnode *n2;
2287 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002288
paul87d6f872004-09-24 08:01:38 +00002289 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002290 {
paul2d33f152003-03-17 01:10:58 +00002291 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
2292 {
2293 msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
2294 r->opaque_type,
2295 oi->address->u.prefix4);
2296 if (!msg)
2297 {
2298 zlog_warn
2299 ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2300#ifdef NOTYET
2301 /* Cannot allocate new message. What should we do? */
2302 ospf_apiserver_free (apiserv);
2303#endif
2304 goto out;
2305 }
2306
2307 ospf_apiserver_send_msg (apiserv, msg);
2308 msg_free (msg);
2309 }
2310 }
2311 }
2312
2313out:
2314 return;
2315}
2316
2317void
2318ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
2319{
paul87d6f872004-09-24 08:01:38 +00002320 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002321 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002322 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002323
2324 assert (area);
2325
2326 if (!ospf_apiserver_is_ready_type10 (area))
2327 {
2328 zlog_warn ("Area not ready for type 10?");
2329 return;
2330 }
2331
paul87d6f872004-09-24 08:01:38 +00002332 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002333 {
paul87d6f872004-09-24 08:01:38 +00002334 struct listnode *n2;
2335 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002336
paul87d6f872004-09-24 08:01:38 +00002337 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002338 {
paul2d33f152003-03-17 01:10:58 +00002339 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
2340 {
2341 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
2342 r->opaque_type, area->area_id);
2343 if (!msg)
2344 {
2345 zlog_warn
2346 ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2347#ifdef NOTYET
2348 /* Cannot allocate new message. What should we do? */
2349 ospf_apiserver_free (apiserv);
2350#endif
paul87d6f872004-09-24 08:01:38 +00002351 goto out;
paul2d33f152003-03-17 01:10:58 +00002352 }
2353
2354 ospf_apiserver_send_msg (apiserv, msg);
2355 msg_free (msg);
2356 }
2357 }
2358 }
2359
2360out:
2361 return;
2362}
2363
2364
2365void
2366ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
2367{
paul87d6f872004-09-24 08:01:38 +00002368 struct listnode *node;
paul2d33f152003-03-17 01:10:58 +00002369 struct msg *msg;
2370 struct in_addr id_null = { 0L };
paul87d6f872004-09-24 08:01:38 +00002371 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002372
2373 assert (top);
2374
2375 if (!ospf_apiserver_is_ready_type11 (top))
2376 {
2377 zlog_warn ("AS not ready for type 11?");
2378 return;
2379 }
2380
paul87d6f872004-09-24 08:01:38 +00002381 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002382 {
paul87d6f872004-09-24 08:01:38 +00002383 struct listnode *n2;
2384 struct registered_opaque_type *r;
paul2d33f152003-03-17 01:10:58 +00002385
paul87d6f872004-09-24 08:01:38 +00002386 LIST_LOOP (apiserv->opaque_types, r, n2)
paul2d33f152003-03-17 01:10:58 +00002387 {
paul2d33f152003-03-17 01:10:58 +00002388 if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
2389 {
2390 msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
2391 r->opaque_type, id_null);
2392 if (!msg)
2393 {
2394 zlog_warn
2395 ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2396#ifdef NOTYET
2397 /* Cannot allocate new message. What should we do? */
2398 ospf_apiserver_free (apiserv);
2399#endif
2400 goto out;
2401 }
2402
2403 ospf_apiserver_send_msg (apiserv, msg);
2404 msg_free (msg);
2405 }
2406 }
2407 }
2408
2409out:
2410 return;
2411}
2412
2413void
2414ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
2415{
2416 struct msg *msg;
2417
2418 msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
2419 if (msg != NULL)
2420 {
2421 ospf_apiserver_clients_notify_all (msg);
2422 msg_free (msg);
2423 }
2424}
2425
2426void
2427ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
2428{
2429 struct msg *msg;
2430
2431 msg = new_msg_del_if (0, oi->address->u.prefix4);
2432 if (msg != NULL)
2433 {
2434 ospf_apiserver_clients_notify_all (msg);
2435 msg_free (msg);
2436 }
2437}
2438
2439void
2440ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
2441{
2442 struct msg *msg;
2443 struct in_addr ifaddr = { 0L };
2444 struct in_addr area_id = { 0L };
2445
2446 assert (oi);
2447 assert (oi->ifp);
2448
2449 if (oi->address)
2450 {
2451 ifaddr = oi->address->u.prefix4;
2452 }
2453 if (oi->area)
2454 {
2455 area_id = oi->area->area_id;
2456 }
2457
2458 msg = new_msg_ism_change (0, ifaddr, area_id, oi->ifp->status);
2459 if (!msg)
2460 {
2461 zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
2462 return;
2463 }
2464
2465 ospf_apiserver_clients_notify_all (msg);
2466 msg_free (msg);
2467}
2468
2469void
2470ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
2471{
2472 struct msg *msg;
2473 struct in_addr ifaddr = { 0L };
2474 struct in_addr nbraddr = { 0L };
2475
2476 assert (nbr);
2477
2478 if (nbr->oi)
2479 {
2480 ifaddr = nbr->oi->address->u.prefix4;
2481 }
2482
2483 nbraddr = nbr->address.u.prefix4;
2484
2485 msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
2486 if (!msg)
2487 {
2488 zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
2489 return;
2490 }
2491
2492 ospf_apiserver_clients_notify_all (msg);
2493 msg_free (msg);
2494}
2495
2496void
2497apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
2498{
2499 struct msg *msg;
paul87d6f872004-09-24 08:01:38 +00002500 struct listnode *node;
2501 struct ospf_apiserver *apiserv;
paul2d33f152003-03-17 01:10:58 +00002502
2503 /* Default area for AS-External and Opaque11 LSAs */
2504 struct in_addr area_id = { 0L };
2505
2506 /* Default interface for non Opaque9 LSAs */
2507 struct in_addr ifaddr = { 0L };
2508
2509 if (lsa->area)
2510 {
2511 area_id = lsa->area->area_id;
2512 }
2513 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2514 {
2515 assert (lsa->oi);
2516 ifaddr = lsa->oi->address->u.prefix4;
2517 }
2518
2519 /* Prepare message that can be sent to clients that have a matching
2520 filter */
2521 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2522 ifaddr, area_id,
2523 lsa->flags & OSPF_LSA_SELF, lsa->data);
2524 if (!msg)
2525 {
2526 zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
2527 return;
2528 }
2529
2530 /* Now send message to all clients with a matching filter */
paul87d6f872004-09-24 08:01:38 +00002531 LIST_LOOP (apiserver_list, apiserv, node)
paul2d33f152003-03-17 01:10:58 +00002532 {
paul2d33f152003-03-17 01:10:58 +00002533 struct lsa_filter_type *filter;
2534 u_int16_t mask;
2535 u_int32_t *area;
2536 int i;
2537
2538 /* Check filter for this client. */
2539 filter = apiserv->filter;
2540
2541 /* Check area IDs in case of non AS-E LSAs.
2542 * If filter has areas (num_areas > 0),
2543 * then one of the areas must match the area ID of this LSA. */
2544
2545 i = filter->num_areas;
2546 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
2547 (lsa->data->type == OSPF_OPAQUE_AS_LSA))
2548 {
2549 i = 0;
2550 }
2551
2552 if (i > 0)
2553 {
2554 area = (u_int32_t *) (filter + 1);
2555 while (i)
2556 {
2557 if (*area == area_id.s_addr)
2558 {
2559 break;
2560 }
2561 i--;
2562 area++;
2563 }
2564 }
2565 else
2566 {
2567 i = 1;
2568 }
2569
2570 if (i > 0)
2571 {
2572 /* Area match. Check LSA type. */
2573 mask = ntohs (filter->typemask);
2574
2575 if (mask & Power2[lsa->data->type])
2576 {
2577 /* Type also matches. Check origin. */
2578 if ((filter->origin == ANY_ORIGIN) ||
2579 (filter->origin == IS_LSA_SELF (lsa)))
2580 {
2581 ospf_apiserver_send_msg (apiserv, msg);
2582 }
2583 }
2584 }
2585 }
2586 /* Free message since it is not used anymore */
2587 msg_free (msg);
2588}
2589
2590
2591/* -------------------------------------------------------------
2592 * Followings are hooks invoked when LSAs are updated or deleted
2593 * -------------------------------------------------------------
2594 */
2595
2596
2597int
2598apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
2599{
2600 struct msg *msg;
2601 /* default area for AS-External and Opaque11 LSAs */
2602 struct in_addr area_id = { 0L };
2603
2604 /* default interface for non Opaque9 LSAs */
2605 struct in_addr ifaddr = { 0L };
2606
2607 /* Only notify this update if the LSA's age is smaller than
2608 MAXAGE. Otherwise clients would see LSA updates with max age just
2609 before they are deleted from the LSDB. LSA delete messages have
2610 MAXAGE too but should not be filtered. */
2611 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2612 return 0;
2613 }
2614
2615 if (lsa->area)
2616 {
2617 area_id = lsa->area->area_id;
2618 }
2619 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
2620 {
2621 ifaddr = lsa->oi->address->u.prefix4;
2622 }
2623 msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
2624 ifaddr, area_id,
2625 lsa->flags & OSPF_LSA_SELF, lsa->data);
2626 if (!msg)
2627 {
2628 zlog_warn ("notify_clients_lsa: msg_new failed");
2629 return -1;
2630 }
2631 /* Notify all clients that new LSA is added/updated */
2632 apiserver_clients_lsa_change_notify (msgtype, lsa);
2633
2634 /* Clients made their own copies of msg so we can free msg here */
2635 msg_free (msg);
2636
2637 return 0;
2638}
2639
2640int
2641ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
2642{
2643 return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
2644}
2645
2646int
2647ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
2648{
2649 return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
2650}
2651
2652#endif /* SUPPORT_OSPF_API */
2653