blob: 671bbc501441330f9b176c157e06520ad9138e87 [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",
ajs6099b3b2004-11-20 02:06:59 +0000649 safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000650 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 {
ajs6099b3b2004-11-20 02:06:59 +0000683 zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000684 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 {
ajs6099b3b2004-11-20 02:06:59 +0000696 zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000697 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 {
ajs6099b3b2004-11-20 02:06:59 +0000721 zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000722 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 {
ajs6099b3b2004-11-20 02:06:59 +0000731 zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000732 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 {
ajs6099b3b2004-11-20 02:06:59 +0000743 zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno));
paul2d33f152003-03-17 01:10:58 +0000744 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() ?");
paul788dab12004-11-15 11:48:37 +00001532 ospf_lsa_unlock (new);
paul2d33f152003-03-17 01:10:58 +00001533 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");
paul788dab12004-11-15 11:48:37 +00001897 ospf_lsa_unlock (new);
paul2d33f152003-03-17 01:10:58 +00001898 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