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