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