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