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