]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_apiserver.c
zebra: Allow ns delete to happen after under/over flow checks
[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"
85c9b439 57#include "ospfd/ospf_errors.h"
2d33f157 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
d62a17ae 80struct ospf_interface *ospf_apiserver_if_lookup_by_addr(struct in_addr address)
2d33f157 81{
d62a17ae 82 struct listnode *node, *nnode;
83 struct ospf_interface *oi;
b5a8894d 84 struct ospf *ospf = NULL;
99b7c5d6 85
b5a8894d
CS
86 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
87 if (!ospf)
d62a17ae 88 return NULL;
2d33f157 89
d62a17ae 90 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
91 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
92 if (IPV4_ADDR_SAME(&address, &oi->address->u.prefix4))
93 return oi;
87d6f87a 94
d62a17ae 95 return NULL;
2d33f157 96}
97
d62a17ae 98struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
2d33f157 99{
d62a17ae 100 struct listnode *node, *nnode;
101 struct ospf_interface *oi;
b5a8894d 102 struct ospf *ospf = NULL;
99b7c5d6 103
b5a8894d
CS
104 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
105 if (!ospf)
d62a17ae 106 return NULL;
2d33f157 107
d62a17ae 108 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
109 if (oi->ifp == ifp)
110 return oi;
87d6f87a 111
d62a17ae 112 return NULL;
2d33f157 113}
114
115/* -----------------------------------------------------------
116 * Initialization
117 * -----------------------------------------------------------
118 */
119
d62a17ae 120unsigned short ospf_apiserver_getport(void)
2d33f157 121{
d62a17ae 122 struct servent *sp = getservbyname("ospfapi", "tcp");
2d33f157 123
d62a17ae 124 return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
2d33f157 125}
126
127/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
d62a17ae 128int ospf_apiserver_init(void)
2d33f157 129{
d62a17ae 130 int fd;
131 int rc = -1;
132
133 /* Create new socket for synchronous messages. */
134 fd = ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET);
135
136 if (fd < 0)
137 goto out;
138
139 /* Schedule new thread that handles accepted connections. */
140 ospf_apiserver_event(OSPF_APISERVER_ACCEPT, fd, NULL);
141
142 /* Initialize list that keeps track of all connections. */
143 apiserver_list = list_new();
144
145 /* Register opaque-independent call back functions. These functions
146 are invoked on ISM, NSM changes and LSA update and LSA deletes */
147 rc = ospf_register_opaque_functab(
148 0 /* all LSAs */, 0 /* all opaque types */,
149 ospf_apiserver_new_if, ospf_apiserver_del_if,
150 ospf_apiserver_ism_change, ospf_apiserver_nsm_change, NULL,
151 NULL, NULL, NULL, /* ospf_apiserver_show_info */
152 NULL, /* originator_func */
153 NULL, /* ospf_apiserver_lsa_refresher */
154 ospf_apiserver_lsa_update, ospf_apiserver_lsa_delete);
155 if (rc != 0) {
ade6974d 156 flog_warn(
cf444bcf 157 EC_OSPF_OPAQUE_REGISTRATION,
ade6974d 158 "ospf_apiserver_init: Failed to register opaque type [0/0]");
d62a17ae 159 }
160
161 rc = 0;
2d33f157 162
163out:
d62a17ae 164 return rc;
2d33f157 165}
166
167/* Terminate OSPF API module. */
d62a17ae 168void ospf_apiserver_term(void)
2d33f157 169{
d62a17ae 170 struct ospf_apiserver *apiserv;
171
172 /* Unregister wildcard [0/0] type */
173 ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */);
174
175 /*
176 * Free all client instances. ospf_apiserver_free removes the node
177 * from the list, so we examine the head of the list anew each time.
178 */
179 while (apiserver_list
180 && (apiserv = listgetdata(listhead(apiserver_list))) != NULL)
181 ospf_apiserver_free(apiserv);
182
183 /* Free client list itself */
184 if (apiserver_list)
6a154c88 185 list_delete(&apiserver_list);
d62a17ae 186
187 /* Free wildcard list */
188 /* XXX */
2d33f157 189}
190
d7c0a89a
QY
191static struct ospf_apiserver *lookup_apiserver(uint8_t lsa_type,
192 uint8_t opaque_type)
2d33f157 193{
d62a17ae 194 struct listnode *n1, *n2;
195 struct registered_opaque_type *r;
196 struct ospf_apiserver *apiserv, *found = NULL;
197
198 /* XXX: this approaches O(n**2) */
199 for (ALL_LIST_ELEMENTS_RO(apiserver_list, n1, apiserv)) {
200 for (ALL_LIST_ELEMENTS_RO(apiserv->opaque_types, n2, r))
201 if (r->lsa_type == lsa_type
202 && r->opaque_type == opaque_type) {
203 found = apiserv;
204 goto out;
205 }
206 }
2d33f157 207out:
d62a17ae 208 return found;
2d33f157 209}
210
d62a17ae 211static struct ospf_apiserver *lookup_apiserver_by_lsa(struct ospf_lsa *lsa)
2d33f157 212{
d62a17ae 213 struct lsa_header *lsah = lsa->data;
214 struct ospf_apiserver *found = NULL;
215
216 if (IS_OPAQUE_LSA(lsah->type)) {
217 found = lookup_apiserver(
218 lsah->type, GET_OPAQUE_TYPE(ntohl(lsah->id.s_addr)));
219 }
220 return found;
2d33f157 221}
222
223/* -----------------------------------------------------------
224 * Followings are functions to manage client connections.
225 * -----------------------------------------------------------
226 */
d62a17ae 227static int ospf_apiserver_new_lsa_hook(struct ospf_lsa *lsa)
2d33f157 228{
d62a17ae 229 if (IS_DEBUG_OSPF_EVENT)
230 zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
231 (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total);
232 return 0;
2d33f157 233}
234
d62a17ae 235static int ospf_apiserver_del_lsa_hook(struct ospf_lsa *lsa)
2d33f157 236{
d62a17ae 237 if (IS_DEBUG_OSPF_EVENT)
238 zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
239 (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total);
240 return 0;
2d33f157 241}
242
243/* Allocate new connection structure. */
d62a17ae 244struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async)
2d33f157 245{
d62a17ae 246 struct ospf_apiserver *new =
247 XMALLOC(MTYPE_OSPF_APISERVER, sizeof(struct ospf_apiserver));
2d33f157 248
d62a17ae 249 new->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER,
250 sizeof(struct lsa_filter_type));
2d33f157 251
d62a17ae 252 new->fd_sync = fd_sync;
253 new->fd_async = fd_async;
2d33f157 254
d62a17ae 255 /* list of registered opaque types that application uses */
256 new->opaque_types = list_new();
2d33f157 257
d62a17ae 258 /* Initialize temporary strage for LSA instances to be refreshed. */
259 memset(&new->reserve, 0, sizeof(struct ospf_lsdb));
260 ospf_lsdb_init(&new->reserve);
2d33f157 261
d62a17ae 262 new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
263 new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
2d33f157 264
d62a17ae 265 new->out_sync_fifo = msg_fifo_new();
266 new->out_async_fifo = msg_fifo_new();
267 new->t_sync_read = NULL;
2d33f157 268#ifdef USE_ASYNC_READ
d62a17ae 269 new->t_async_read = NULL;
2d33f157 270#endif /* USE_ASYNC_READ */
d62a17ae 271 new->t_sync_write = NULL;
272 new->t_async_write = NULL;
2d33f157 273
d62a17ae 274 new->filter->typemask = 0; /* filter all LSAs */
275 new->filter->origin = ANY_ORIGIN;
276 new->filter->num_areas = 0;
2d33f157 277
d62a17ae 278 return new;
2d33f157 279}
280
d62a17ae 281void ospf_apiserver_event(enum event event, int fd,
282 struct ospf_apiserver *apiserv)
2d33f157 283{
d62a17ae 284 switch (event) {
285 case OSPF_APISERVER_ACCEPT:
286 (void)thread_add_read(master, ospf_apiserver_accept, apiserv,
287 fd, NULL);
288 break;
289 case OSPF_APISERVER_SYNC_READ:
290 apiserv->t_sync_read = NULL;
291 thread_add_read(master, ospf_apiserver_read, apiserv, fd,
292 &apiserv->t_sync_read);
293 break;
2d33f157 294#ifdef USE_ASYNC_READ
d62a17ae 295 case OSPF_APISERVER_ASYNC_READ:
296 apiserv->t_async_read = NULL;
297 thread_add_read(master, ospf_apiserver_read, apiserv, fd,
298 &apiserv->t_async_read);
299 break;
2d33f157 300#endif /* USE_ASYNC_READ */
d62a17ae 301 case OSPF_APISERVER_SYNC_WRITE:
302 thread_add_write(master, ospf_apiserver_sync_write, apiserv, fd,
303 &apiserv->t_sync_write);
304 break;
305 case OSPF_APISERVER_ASYNC_WRITE:
306 thread_add_write(master, ospf_apiserver_async_write, apiserv,
307 fd, &apiserv->t_async_write);
308 break;
309 }
2d33f157 310}
311
312/* Free instance. First unregister all opaque types used by
d62a17ae 313 application, flush opaque LSAs injected by application
2d33f157 314 from network and close connection. */
d62a17ae 315void ospf_apiserver_free(struct ospf_apiserver *apiserv)
2d33f157 316{
d62a17ae 317 struct listnode *node;
2d33f157 318
d62a17ae 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
d62a17ae 324 if (apiserv->t_async_read) {
325 thread_cancel(apiserv->t_async_read);
326 }
2d33f157 327#endif /* USE_ASYNC_READ */
d62a17ae 328 if (apiserv->t_sync_write) {
329 thread_cancel(apiserv->t_sync_write);
330 }
2d33f157 331
d62a17ae 332 if (apiserv->t_async_write) {
333 thread_cancel(apiserv->t_async_write);
334 }
2d33f157 335
d62a17ae 336 /* Unregister all opaque types that application registered
337 and flush opaque LSAs if still in LSDB. */
2d33f157 338
d62a17ae 339 while ((node = listhead(apiserv->opaque_types)) != NULL) {
340 struct registered_opaque_type *regtype = listgetdata(node);
2d33f157 341
d62a17ae 342 ospf_apiserver_unregister_opaque_type(
343 apiserv, regtype->lsa_type, regtype->opaque_type);
344 }
2d33f157 345
d62a17ae 346 /* Close connections to OSPFd. */
347 if (apiserv->fd_sync > 0) {
348 close(apiserv->fd_sync);
349 }
2d33f157 350
d62a17ae 351 if (apiserv->fd_async > 0) {
352 close(apiserv->fd_async);
353 }
2d33f157 354
d62a17ae 355 /* Free fifos */
356 msg_fifo_free(apiserv->out_sync_fifo);
357 msg_fifo_free(apiserv->out_async_fifo);
2d33f157 358
d62a17ae 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
d62a17ae 363 /* Remove from the list of active clients. */
364 listnode_delete(apiserver_list, apiserv);
2d33f157 365
d62a17ae 366 if (IS_DEBUG_OSPF_EVENT)
367 zlog_debug("API: Delete apiserv(%p), total#(%d)",
368 (void *)apiserv, apiserver_list->count);
2d33f157 369
d62a17ae 370 /* And free instance. */
371 XFREE(MTYPE_OSPF_APISERVER, apiserv);
2d33f157 372}
373
d62a17ae 374int ospf_apiserver_read(struct thread *thread)
2d33f157 375{
d62a17ae 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
d62a17ae 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 */
d62a17ae 405 else {
406 zlog_warn("ospf_apiserver_read: Unknown fd(%d)", fd);
407 ospf_apiserver_free(apiserv);
408 goto out;
409 }
2d33f157 410
d62a17ae 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
d62a17ae 418 /* Perform cleanup. */
419 ospf_apiserver_free(apiserv);
420 goto out;
421 }
2d33f157 422
d62a17ae 423 if (IS_DEBUG_OSPF_EVENT)
424 msg_print(msg);
2d33f157 425
d62a17ae 426 /* Dispatch to corresponding message handler. */
427 rc = ospf_apiserver_handle_msg(apiserv, msg);
2d33f157 428
d62a17ae 429 /* Prepare for next message, add read thread. */
430 ospf_apiserver_event(event, fd, apiserv);
2d33f157 431
d62a17ae 432 msg_free(msg);
2d33f157 433
434out:
d62a17ae 435 return rc;
2d33f157 436}
437
d62a17ae 438int ospf_apiserver_sync_write(struct thread *thread)
2d33f157 439{
d62a17ae 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
d62a17ae 502int ospf_apiserver_async_write(struct thread *thread)
2d33f157 503{
d62a17ae 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
d62a17ae 566int ospf_apiserver_serv_sock_family(unsigned short port, int family)
2d33f157 567{
d62a17ae 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. */
d62a17ae 605int ospf_apiserver_accept(struct thread *thread)
2d33f157 606{
d62a17ae 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
d62a17ae 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
d62a17ae 699 /* Allocate new server-side connection structure */
700 apiserv = ospf_apiserver_new(new_sync_sock, new_async_sock);
2d33f157 701
d62a17ae 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
d62a17ae 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
d62a17ae 710 ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ, new_async_sock,
711 apiserv);
2d33f157 712#endif /* USE_ASYNC_READ */
713
d62a17ae 714 if (IS_DEBUG_OSPF_EVENT)
715 zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv,
716 apiserver_list->count);
2d33f157 717
d62a17ae 718 return 0;
2d33f157 719}
720
721
722/* -----------------------------------------------------------
723 * Send reply with return code to client application
724 * -----------------------------------------------------------
725 */
726
d62a17ae 727static int ospf_apiserver_send_msg(struct ospf_apiserver *apiserv,
728 struct msg *msg)
2d33f157 729{
d62a17ae 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
d7c0a89a
QY
771int ospf_apiserver_send_reply(struct ospf_apiserver *apiserv, uint32_t seqnr,
772 uint8_t rc)
2d33f157 773{
d62a17ae 774 struct msg *msg = new_msg_reply(seqnr, rc);
775 int ret;
2d33f157 776
d62a17ae 777 if (!msg) {
778 zlog_warn("ospf_apiserver_send_reply: msg_new failed");
2d33f157 779#ifdef NOTYET
d62a17ae 780 /* Cannot allocate new message. What should we do? */
781 ospf_apiserver_free(apiserv);
2d33f157 782#endif
d62a17ae 783 return -1;
784 }
2d33f157 785
d62a17ae 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
d62a17ae 797int ospf_apiserver_handle_msg(struct ospf_apiserver *apiserv, struct msg *msg)
2d33f157 798{
d62a17ae 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
d62a17ae 835int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv,
d7c0a89a 836 uint8_t lsa_type, uint8_t opaque_type)
2d33f157 837{
d62a17ae 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) {
cf444bcf 872 flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
85c9b439 873 "Failed to register opaque type [%d/%d]", lsa_type,
d62a17ae 874 opaque_type);
875 return OSPF_API_OPAQUETYPEINUSE;
876 }
877
878 /* Remember the opaque type that application registers so when
879 connection shuts down, we can flush all LSAs of this opaque
880 type. */
881
882 regtype = XCALLOC(MTYPE_OSPF_APISERVER,
883 sizeof(struct registered_opaque_type));
884 regtype->lsa_type = lsa_type;
885 regtype->opaque_type = opaque_type;
886
887 /* Add to list of registered opaque types */
888 listnode_add(apiserv->opaque_types, regtype);
889
890 if (IS_DEBUG_OSPF_EVENT)
891 zlog_debug(
892 "API: Add LSA-type(%d)/Opaque-type(%d) into"
893 " apiserv(%p), total#(%d)",
894 lsa_type, opaque_type, (void *)apiserv,
895 listcount(apiserv->opaque_types));
896
897 return 0;
2d33f157 898}
899
d62a17ae 900int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver *apiserv,
d7c0a89a 901 uint8_t lsa_type, uint8_t opaque_type)
2d33f157 902{
d62a17ae 903 struct listnode *node, *nnode;
904 struct registered_opaque_type *regtype;
2d33f157 905
d62a17ae 906 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) {
907 /* Check if we really registered this opaque type */
908 if (regtype->lsa_type == lsa_type
909 && regtype->opaque_type == opaque_type) {
2d33f157 910
d62a17ae 911 /* Yes, we registered this opaque type. Flush
912 all existing opaque LSAs of this type */
2d33f157 913
d62a17ae 914 ospf_apiserver_flush_opaque_lsa(apiserv, lsa_type,
915 opaque_type);
916 ospf_delete_opaque_functab(lsa_type, opaque_type);
2d33f157 917
d62a17ae 918 /* Remove from list of registered opaque types */
919 listnode_delete(apiserv->opaque_types, regtype);
2d33f157 920
d62a17ae 921 if (IS_DEBUG_OSPF_EVENT)
922 zlog_debug(
923 "API: Del LSA-type(%d)/Opaque-type(%d)"
924 " from apiserv(%p), total#(%d)",
925 lsa_type, opaque_type, (void *)apiserv,
926 listcount(apiserv->opaque_types));
2d33f157 927
d62a17ae 928 return 0;
929 }
2d33f157 930 }
2d33f157 931
d62a17ae 932 /* Opaque type is not registered */
933 zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type,
934 opaque_type);
935 return OSPF_API_OPAQUETYPENOTREGISTERED;
2d33f157 936}
937
938
d62a17ae 939static int apiserver_is_opaque_type_registered(struct ospf_apiserver *apiserv,
d7c0a89a
QY
940 uint8_t lsa_type,
941 uint8_t opaque_type)
2d33f157 942{
d62a17ae 943 struct listnode *node, *nnode;
944 struct registered_opaque_type *regtype;
945
946 /* XXX: how many types are there? if few, why not just a bitmap? */
947 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) {
948 /* Check if we really registered this opaque type */
949 if (regtype->lsa_type == lsa_type
950 && regtype->opaque_type == opaque_type) {
951 /* Yes registered */
952 return 1;
953 }
954 }
955 /* Not registered */
956 return 0;
2d33f157 957}
958
d62a17ae 959int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver *apiserv,
960 struct msg *msg)
2d33f157 961{
d62a17ae 962 struct msg_register_opaque_type *rmsg;
d7c0a89a
QY
963 uint8_t lsa_type;
964 uint8_t opaque_type;
d62a17ae 965 int rc = 0;
966
967 /* Extract parameters from register opaque type message */
968 rmsg = (struct msg_register_opaque_type *)STREAM_DATA(msg->s);
969
970 lsa_type = rmsg->lsatype;
971 opaque_type = rmsg->opaquetype;
972
973 rc = ospf_apiserver_register_opaque_type(apiserv, lsa_type,
974 opaque_type);
975
976 /* Send a reply back to client including return code */
977 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
978 if (rc < 0)
979 goto out;
980
981 /* Now inform application about opaque types that are ready */
982 switch (lsa_type) {
983 case OSPF_OPAQUE_LINK_LSA:
984 ospf_apiserver_notify_ready_type9(apiserv);
985 break;
986 case OSPF_OPAQUE_AREA_LSA:
987 ospf_apiserver_notify_ready_type10(apiserv);
988 break;
989 case OSPF_OPAQUE_AS_LSA:
990 ospf_apiserver_notify_ready_type11(apiserv);
991 break;
992 }
2d33f157 993out:
d62a17ae 994 return rc;
2d33f157 995}
996
997
998/* Notify specific client about all opaque types 9 that are ready. */
d62a17ae 999void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv)
2d33f157 1000{
d62a17ae 1001 struct listnode *node, *nnode;
1002 struct listnode *node2, *nnode2;
1003 struct ospf *ospf;
1004 struct ospf_interface *oi;
1005 struct registered_opaque_type *r;
1006
b5a8894d 1007 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1008
1009 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
1010 /* Check if this interface is indeed ready for type 9 */
1011 if (!ospf_apiserver_is_ready_type9(oi))
1012 continue;
1013
1014 /* Check for registered opaque type 9 types */
1015 /* XXX: loop-de-loop - optimise me */
1016 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
1017 r)) {
1018 struct msg *msg;
1019
1020 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
1021
1022 /* Yes, this opaque type is ready */
1023 msg = new_msg_ready_notify(
1024 0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
1025 oi->address->u.prefix4);
1026 if (!msg) {
1027 zlog_warn(
1028 "apiserver_notify_ready_type9: msg_new failed");
2d33f157 1029#ifdef NOTYET
d62a17ae 1030 /* Cannot allocate new message. What
1031 * should we do? */
1032 ospf_apiserver_free(apiserv);
2d33f157 1033#endif
d62a17ae 1034 goto out;
1035 }
1036 ospf_apiserver_send_msg(apiserv, msg);
1037 msg_free(msg);
1038 }
2d33f157 1039 }
2d33f157 1040 }
2d33f157 1041
1042out:
d62a17ae 1043 return;
2d33f157 1044}
1045
1046
1047/* Notify specific client about all opaque types 10 that are ready. */
d62a17ae 1048void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv)
2d33f157 1049{
d62a17ae 1050 struct listnode *node, *nnode;
1051 struct listnode *node2, *nnode2;
1052 struct ospf *ospf;
1053 struct ospf_area *area;
1054
b5a8894d 1055 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1056
1057 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1058 struct registered_opaque_type *r;
1059
1060 if (!ospf_apiserver_is_ready_type10(area)) {
1061 continue;
1062 }
1063
1064 /* Check for registered opaque type 10 types */
1065 /* XXX: loop in loop - optimise me */
1066 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
1067 r)) {
1068 struct msg *msg;
1069
1070 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
1071 /* Yes, this opaque type is ready */
1072 msg = new_msg_ready_notify(
1073 0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
1074 area->area_id);
1075 if (!msg) {
1076 zlog_warn(
1077 "apiserver_notify_ready_type10: msg_new failed");
2d33f157 1078#ifdef NOTYET
d62a17ae 1079 /* Cannot allocate new message. What
1080 * should we do? */
1081 ospf_apiserver_free(apiserv);
2d33f157 1082#endif
d62a17ae 1083 goto out;
1084 }
1085 ospf_apiserver_send_msg(apiserv, msg);
1086 msg_free(msg);
1087 }
2d33f157 1088 }
2d33f157 1089 }
2d33f157 1090
1091out:
d62a17ae 1092 return;
2d33f157 1093}
1094
1095/* Notify specific client about all opaque types 11 that are ready */
d62a17ae 1096void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv)
2d33f157 1097{
d62a17ae 1098 struct listnode *node, *nnode;
1099 struct ospf *ospf;
1100 struct registered_opaque_type *r;
1101
b5a8894d 1102 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1103
1104 /* Can type 11 be originated? */
1105 if (!ospf_apiserver_is_ready_type11(ospf))
1106 goto out;
1107
1108 /* Check for registered opaque type 11 types */
1109 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, r)) {
1110 struct msg *msg;
1111 struct in_addr noarea_id = {.s_addr = 0L};
1112
1113 if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
1114 /* Yes, this opaque type is ready */
1115 msg = new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA,
1116 r->opaque_type, noarea_id);
1117
1118 if (!msg) {
1119 zlog_warn(
1120 "apiserver_notify_ready_type11: msg_new failed");
2d33f157 1121#ifdef NOTYET
d62a17ae 1122 /* Cannot allocate new message. What should we
1123 * do? */
1124 ospf_apiserver_free(apiserv);
2d33f157 1125#endif
d62a17ae 1126 goto out;
1127 }
1128 ospf_apiserver_send_msg(apiserv, msg);
1129 msg_free(msg);
1130 }
2d33f157 1131 }
2d33f157 1132
1133out:
d62a17ae 1134 return;
2d33f157 1135}
1136
d62a17ae 1137int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver *apiserv,
1138 struct msg *msg)
2d33f157 1139{
d62a17ae 1140 struct msg_unregister_opaque_type *umsg;
d7c0a89a
QY
1141 uint8_t ltype;
1142 uint8_t otype;
d62a17ae 1143 int rc = 0;
2d33f157 1144
d62a17ae 1145 /* Extract parameters from unregister opaque type message */
1146 umsg = (struct msg_unregister_opaque_type *)STREAM_DATA(msg->s);
2d33f157 1147
d62a17ae 1148 ltype = umsg->lsatype;
1149 otype = umsg->opaquetype;
2d33f157 1150
d62a17ae 1151 rc = ospf_apiserver_unregister_opaque_type(apiserv, ltype, otype);
2d33f157 1152
d62a17ae 1153 /* Send a reply back to client including return code */
1154 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
2d33f157 1155
d62a17ae 1156 return rc;
2d33f157 1157}
1158
1159
1160/* -----------------------------------------------------------
1161 * Following are functions for event (filter) registration.
1162 * -----------------------------------------------------------
1163 */
d62a17ae 1164int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
1165 struct msg *msg)
2d33f157 1166{
d62a17ae 1167 struct msg_register_event *rmsg;
1168 int rc;
d7c0a89a 1169 uint32_t seqnum;
d62a17ae 1170
1171 rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
1172
1173 /* Get request sequence number */
1174 seqnum = msg_get_seq(msg);
1175
1176 /* Free existing filter in apiserv. */
1177 XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1178 /* Alloc new space for filter. */
1179
1180 apiserv->filter =
1181 XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen));
0ce1ca80
DS
1182
1183 /* copy it over. */
1184 memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen));
1185 rc = OSPF_API_OK;
1186
d62a17ae 1187 /* Send a reply back to client with return code */
1188 rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1189 return rc;
2d33f157 1190}
1191
1192
1193/* -----------------------------------------------------------
1194 * Followings are functions for LSDB synchronization.
1195 * -----------------------------------------------------------
1196 */
1197
d62a17ae 1198static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg,
1199 int int_arg)
2d33f157 1200{
d62a17ae 1201 struct ospf_apiserver *apiserv;
1202 int seqnum;
1203 struct msg *msg;
1204 struct param_t {
1205 struct ospf_apiserver *apiserv;
1206 struct lsa_filter_type *filter;
1207 } * param;
1208 int rc = -1;
1209
1210 /* Sanity check */
1211 assert(lsa->data);
1212 assert(p_arg);
1213
1214 param = (struct param_t *)p_arg;
1215 apiserv = param->apiserv;
d7c0a89a 1216 seqnum = (uint32_t)int_arg;
d62a17ae 1217
1218 /* Check origin in filter. */
1219 if ((param->filter->origin == ANY_ORIGIN)
1220 || (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) {
1221
1222 /* Default area for AS-External and Opaque11 LSAs */
1223 struct in_addr area_id = {.s_addr = 0L};
1224
1225 /* Default interface for non Opaque9 LSAs */
1226 struct in_addr ifaddr = {.s_addr = 0L};
1227
1228 if (lsa->area) {
1229 area_id = lsa->area->area_id;
1230 }
1231 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
1232 ifaddr = lsa->oi->address->u.prefix4;
1233 }
1234
1235 msg = new_msg_lsa_change_notify(
1236 MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id,
1237 lsa->flags & OSPF_LSA_SELF, lsa->data);
1238 if (!msg) {
1239 zlog_warn(
1240 "apiserver_sync_callback: new_msg_update failed");
2d33f157 1241#ifdef NOTYET
9d303b37
DL
1242 /* Cannot allocate new message. What should we do? */
1243 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1244 here XXX
1245 */
2d33f157 1246#endif
d62a17ae 1247 goto out;
1248 }
2d33f157 1249
d62a17ae 1250 /* Send LSA */
1251 ospf_apiserver_send_msg(apiserv, msg);
1252 msg_free(msg);
1253 }
1254 rc = 0;
2d33f157 1255
1256out:
d62a17ae 1257 return rc;
2d33f157 1258}
1259
d62a17ae 1260int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
1261 struct msg *msg)
2d33f157 1262{
d62a17ae 1263 struct listnode *node, *nnode;
d7c0a89a 1264 uint32_t seqnum;
d62a17ae 1265 int rc = 0;
1266 struct msg_sync_lsdb *smsg;
1267 struct ospf_apiserver_param_t {
1268 struct ospf_apiserver *apiserv;
1269 struct lsa_filter_type *filter;
1270 } param;
d7c0a89a 1271 uint16_t mask;
d62a17ae 1272 struct route_node *rn;
1273 struct ospf_lsa *lsa;
1274 struct ospf *ospf;
1275 struct ospf_area *area;
1276
b5a8894d 1277 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1278
1279 /* Get request sequence number */
1280 seqnum = msg_get_seq(msg);
1281 /* Set sync msg. */
1282 smsg = (struct msg_sync_lsdb *)STREAM_DATA(msg->s);
1283
1284 /* Set parameter struct. */
1285 param.apiserv = apiserv;
1286 param.filter = &smsg->filter;
1287
1288 /* Remember mask. */
1289 mask = ntohs(smsg->filter.typemask);
1290
1291 /* Iterate over all areas. */
1292 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1293 int i;
d7c0a89a 1294 uint32_t *area_id = NULL;
d62a17ae 1295
1296 /* Compare area_id with area_ids in sync request. */
1297 if ((i = smsg->filter.num_areas) > 0) {
1298 /* Let area_id point to the list of area IDs,
1299 * which is at the end of smsg->filter. */
d7c0a89a 1300 area_id = (uint32_t *)(&smsg->filter + 1);
d62a17ae 1301 while (i) {
1302 if (*area_id == area->area_id.s_addr) {
1303 break;
1304 }
1305 i--;
1306 area_id++;
1307 }
1308 } else {
1309 i = 1;
1310 }
1311
1312 /* If area was found, then i>0 here. */
1313 if (i) {
1314 /* Check msg type. */
1315 if (mask & Power2[OSPF_ROUTER_LSA])
996c9314 1316 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
044506e7
DS
1317 apiserver_sync_callback(
1318 lsa, (void *)&param, seqnum);
d62a17ae 1319 if (mask & Power2[OSPF_NETWORK_LSA])
996c9314 1320 LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
044506e7
DS
1321 apiserver_sync_callback(
1322 lsa, (void *)&param, seqnum);
d62a17ae 1323 if (mask & Power2[OSPF_SUMMARY_LSA])
996c9314 1324 LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
044506e7
DS
1325 apiserver_sync_callback(
1326 lsa, (void *)&param, seqnum);
d62a17ae 1327 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
996c9314 1328 LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
044506e7
DS
1329 apiserver_sync_callback(
1330 lsa, (void *)&param, seqnum);
d62a17ae 1331 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
996c9314 1332 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
044506e7
DS
1333 apiserver_sync_callback(
1334 lsa, (void *)&param, seqnum);
d62a17ae 1335 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
996c9314 1336 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
044506e7
DS
1337 apiserver_sync_callback(
1338 lsa, (void *)&param, seqnum);
2d33f157 1339 }
d62a17ae 1340 }
1341
1342 /* For AS-external LSAs */
1343 if (ospf->lsdb) {
1344 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
996c9314 1345 LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
044506e7
DS
1346 apiserver_sync_callback(lsa, (void *)&param,
1347 seqnum);
d62a17ae 1348 }
1349
1350 /* For AS-external opaque LSAs */
1351 if (ospf->lsdb) {
1352 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
996c9314 1353 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
044506e7
DS
1354 apiserver_sync_callback(lsa, (void *)&param,
1355 seqnum);
d62a17ae 1356 }
1357
1358 /* Send a reply back to client with return code */
1359 rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1360 return rc;
2d33f157 1361}
1362
1363
1364/* -----------------------------------------------------------
1365 * Followings are functions to originate or update LSA
1366 * from an application.
1367 * -----------------------------------------------------------
1368 */
1369
1370/* Create a new internal opaque LSA by taking prototype and filling in
1371 missing fields such as age, sequence number, advertising router,
1372 checksum and so on. The interface parameter is used for type 9
1373 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1374 nor interface. */
1375
d62a17ae 1376struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
1377 struct ospf_interface *oi,
1378 struct lsa_header *protolsa)
2d33f157 1379{
d62a17ae 1380 struct stream *s;
1381 struct lsa_header *newlsa;
1382 struct ospf_lsa *new = NULL;
d7c0a89a
QY
1383 uint8_t options = 0x0;
1384 uint16_t length;
d62a17ae 1385
1386 struct ospf *ospf;
1387
c0f3f7cd 1388 if (oi && oi->ospf)
0d31e63e
CS
1389 ospf = oi->ospf;
1390 else
1391 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1392
d62a17ae 1393 assert(ospf);
1394
1395 /* Create a stream for internal opaque LSA */
1396 if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
1397 zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
1398 return NULL;
1399 }
1400
1401 newlsa = (struct lsa_header *)STREAM_DATA(s);
1402
1403 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1404 have to set options? */
1405
1406 if (area) {
1407 options = LSA_OPTIONS_GET(area);
1408 options |= LSA_OPTIONS_NSSA_GET(area);
1409 }
1410
1411 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1412
1413 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1414 zlog_debug("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
1415 protolsa->type, inet_ntoa(protolsa->id));
1416 }
1417
1418 /* Set opaque-LSA header fields. */
1419 lsa_header_set(s, options, protolsa->type, protolsa->id,
1420 ospf->router_id);
1421
1422 /* Set opaque-LSA body fields. */
d7c0a89a 1423 stream_put(s, ((uint8_t *)protolsa) + sizeof(struct lsa_header),
d62a17ae 1424 ntohs(protolsa->length) - sizeof(struct lsa_header));
1425
1426 /* Determine length of LSA. */
1427 length = stream_get_endp(s);
1428 newlsa->length = htons(length);
1429
1430 /* Create OSPF LSA. */
5b3d4186 1431 new = ospf_lsa_new_and_data(length);
d62a17ae 1432
1433 new->area = area;
1434 new->oi = oi;
0d31e63e 1435 new->vrf_id = ospf->vrf_id;
d62a17ae 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
d62a17ae 1445int ospf_apiserver_is_ready_type9(struct ospf_interface *oi)
2d33f157 1446{
d62a17ae 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
d62a17ae 1451 return (ospf_nbr_count_opaque_capable(oi) > 0);
2d33f157 1452}
1453
d62a17ae 1454int ospf_apiserver_is_ready_type10(struct ospf_area *area)
2d33f157 1455{
d62a17ae 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
d62a17ae 1471int ospf_apiserver_is_ready_type11(struct ospf *ospf)
2d33f157 1472{
d62a17ae 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
d62a17ae 1489int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
1490 struct msg *msg)
2d33f157 1491{
d62a17ae 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
b5a8894d 1504 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 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
d62a17ae 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/* -----------------------------------------------------------
d62a17ae 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
d62a17ae 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
d62a17ae 1625void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa)
2d33f157 1626{
d62a17ae 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
b5a8894d 1647 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 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
d62a17ae 1659int ospf_apiserver_originate1(struct ospf_lsa *lsa)
2d33f157 1660{
d62a17ae 1661 struct ospf *ospf;
99b7c5d6 1662
b5a8894d 1663 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1664 assert(ospf);
99b7c5d6 1665
d62a17ae 1666 /* Install this LSA into LSDB. */
1667 if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
cf444bcf 1668 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
542a208f 1669 "ospf_apiserver_originate1: ospf_lsa_install failed");
d62a17ae 1670 return -1;
1671 }
2d33f157 1672
d62a17ae 1673/* Flood LSA within scope */
2d33f157 1674
1675#ifdef NOTYET
d62a17ae 1676 /*
1677 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1678 * parameter, and thus it does not cause SIGSEGV error.
1679 */
1680 ospf_flood_through(NULL /*nbr */, lsa);
1681#else /* NOTYET */
1682
1683 ospf_apiserver_flood_opaque_lsa(lsa);
2d33f157 1684#endif /* NOTYET */
1685
d62a17ae 1686 return 0;
2d33f157 1687}
1688
1689
1690/* Opaque LSAs of type 9 on a specific interface can now be
1691 originated. Tell clients that registered type 9. */
d62a17ae 1692int ospf_apiserver_lsa9_originator(void *arg)
2d33f157 1693{
d62a17ae 1694 struct ospf_interface *oi;
2d33f157 1695
d62a17ae 1696 oi = (struct ospf_interface *)arg;
1697 if (listcount(apiserver_list) > 0) {
1698 ospf_apiserver_clients_notify_ready_type9(oi);
1699 }
1700 return 0;
2d33f157 1701}
1702
d62a17ae 1703int ospf_apiserver_lsa10_originator(void *arg)
2d33f157 1704{
d62a17ae 1705 struct ospf_area *area;
2d33f157 1706
d62a17ae 1707 area = (struct ospf_area *)arg;
1708 if (listcount(apiserver_list) > 0) {
1709 ospf_apiserver_clients_notify_ready_type10(area);
1710 }
1711 return 0;
2d33f157 1712}
1713
d62a17ae 1714int ospf_apiserver_lsa11_originator(void *arg)
2d33f157 1715{
d62a17ae 1716 struct ospf *ospf;
2d33f157 1717
d62a17ae 1718 ospf = (struct ospf *)arg;
1719 if (listcount(apiserver_list) > 0) {
1720 ospf_apiserver_clients_notify_ready_type11(ospf);
1721 }
1722 return 0;
2d33f157 1723}
1724
1725
1726/* Periodically refresh opaque LSAs so that they do not expire in
1727 other routers. */
d62a17ae 1728struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
2d33f157 1729{
d62a17ae 1730 struct ospf_apiserver *apiserv;
1731 struct ospf_lsa *new = NULL;
1732 struct ospf *ospf;
1733
ed35fc05 1734 assert(lsa);
1735
b5a8894d 1736 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1737 assert(ospf);
1738
1739 apiserv = lookup_apiserver_by_lsa(lsa);
1740 if (!apiserv) {
1741 zlog_warn(
1742 "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
1743 dump_lsa_key(lsa));
1744 lsa->data->ls_age =
1745 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
4adf00f7 1746 goto out;
d62a17ae 1747 }
1748
1749 if (IS_LSA_MAXAGE(lsa)) {
1750 ospf_opaque_lsa_flush_schedule(lsa);
1751 goto out;
1752 }
1753
1754 /* Check if updated version of LSA instance has already prepared. */
1755 new = ospf_lsdb_lookup(&apiserv->reserve, lsa);
1756 if (!new) {
1757 /* This is a periodic refresh, driven by core OSPF mechanism. */
1758 new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi,
1759 lsa->data);
1760 if (!new) {
1761 zlog_warn(
1762 "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1763 goto out;
1764 }
1765 } else {
1766 /* This is a forcible refresh, requested by OSPF-API client. */
1767 ospf_lsdb_delete(&apiserv->reserve, new);
1768 new->lsdb = NULL;
1769 }
1770
1771 /* Increment sequence number */
1772 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1773
1774 /* New LSA is in same area. */
1775 new->area = lsa->area;
1776 SET_FLAG(new->flags, OSPF_LSA_SELF);
1777
1778 /* Install LSA into LSDB. */
1779 if (ospf_lsa_install(ospf, new->oi, new) == NULL) {
542a208f 1780 flog_warn(
cf444bcf 1781 EC_OSPF_LSA_INSTALL_FAILURE,
d62a17ae 1782 "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1783 ospf_lsa_unlock(&new);
1784 goto out;
1785 }
1786
1787/* Flood updated LSA through interface, area or AS */
2d33f157 1788
1789#ifdef NOTYET
d62a17ae 1790 ospf_flood_through(NULL /*nbr */, new);
2d33f157 1791#endif /* NOTYET */
d62a17ae 1792 ospf_apiserver_flood_opaque_lsa(new);
2d33f157 1793
d62a17ae 1794 /* Debug logging. */
1795 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1796 zlog_debug("LSA[Type%d:%s]: Refresh Opaque LSA",
1797 new->data->type, inet_ntoa(new->data->id));
1798 ospf_lsa_header_dump(new->data);
1799 }
2d33f157 1800
1801out:
d62a17ae 1802 return new;
2d33f157 1803}
1804
1805
1806/* -----------------------------------------------------------
1807 * Followings are functions to delete LSAs
1808 * -----------------------------------------------------------
1809 */
1810
d62a17ae 1811int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
1812 struct msg *msg)
2d33f157 1813{
d62a17ae 1814 struct msg_delete_request *dmsg;
1815 struct ospf_lsa *old;
1816 struct ospf_area *area = NULL;
1817 struct in_addr id;
1818 int lsa_type, opaque_type;
1819 int rc = 0;
1820 struct ospf *ospf;
1821
b5a8894d 1822 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1823 assert(ospf);
1824
1825 /* Extract opaque LSA from message */
1826 dmsg = (struct msg_delete_request *)STREAM_DATA(msg->s);
1827
1828 /* Lookup area for link-local and area-local opaque LSAs */
1829 switch (dmsg->lsa_type) {
1830 case OSPF_OPAQUE_LINK_LSA:
1831 case OSPF_OPAQUE_AREA_LSA:
1832 area = ospf_area_lookup_by_area_id(ospf, dmsg->area_id);
1833 if (!area) {
1834 zlog_warn("ospf_apiserver_lsa_delete: unknown area %s",
1835 inet_ntoa(dmsg->area_id));
1836 rc = OSPF_API_NOSUCHAREA;
1837 goto out;
1838 }
1839 break;
1840 case OSPF_OPAQUE_AS_LSA:
1841 /* AS-external opaque LSAs have no designated area */
1842 area = NULL;
1843 break;
1844 default:
1845 zlog_warn(
1846 "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1847 dmsg->lsa_type);
1848 rc = OSPF_API_ILLEGALLSATYPE;
1849 goto out;
1850 }
1851
1852 /* Check if we registered this opaque type */
1853 lsa_type = dmsg->lsa_type;
1854 opaque_type = dmsg->opaque_type;
1855
1856 if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1857 opaque_type)) {
1858 zlog_warn(
1859 "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
1860 lsa_type, opaque_type);
1861 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1862 goto out;
1863 }
1864
1865 /* opaque_id is in network byte order */
1866 id.s_addr = htonl(
1867 SET_OPAQUE_LSID(dmsg->opaque_type, ntohl(dmsg->opaque_id)));
1868
1869 /*
1870 * Even if the target LSA has once scheduled to flush, it remains in
1871 * the LSDB until it is finally handled by the maxage remover thread.
1872 * Therefore, the lookup function below may return non-NULL result.
1873 */
b5a8894d 1874 old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id);
d62a17ae 1875 if (!old) {
1876 zlog_warn(
1877 "ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
1878 dmsg->lsa_type, inet_ntoa(id));
1879 rc = OSPF_API_NOSUCHLSA;
1880 goto out;
1881 }
1882
1883 /* Schedule flushing of LSA from LSDB */
1884 /* NB: Multiple scheduling will produce a warning message, but harmless.
1885 */
1886 ospf_opaque_lsa_flush_schedule(old);
2d33f157 1887
1888out:
1889
d62a17ae 1890 /* Send reply back to client including return code */
1891 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1892 return rc;
2d33f157 1893}
1894
1895/* Flush self-originated opaque LSA */
d62a17ae 1896static int apiserver_flush_opaque_type_callback(struct ospf_lsa *lsa,
1897 void *p_arg, int int_arg)
2d33f157 1898{
d62a17ae 1899 struct param_t {
1900 struct ospf_apiserver *apiserv;
d7c0a89a
QY
1901 uint8_t lsa_type;
1902 uint8_t opaque_type;
d62a17ae 1903 } * param;
1904
1905 /* Sanity check */
1906 assert(lsa->data);
1907 assert(p_arg);
1908 param = (struct param_t *)p_arg;
1909
1910 /* If LSA matches type and opaque type then delete it */
1911 if (IS_LSA_SELF(lsa) && lsa->data->type == param->lsa_type
1912 && GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1913 == param->opaque_type) {
1914 ospf_opaque_lsa_flush_schedule(lsa);
1915 }
1916 return 0;
2d33f157 1917}
1918
1919/* Delete self-originated opaque LSAs of a given opaque type. This
1920 function is called when an application unregisters a given opaque
1921 type or a connection to an application closes and all those opaque
1922 LSAs need to be flushed the LSDB. */
d62a17ae 1923void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
d7c0a89a 1924 uint8_t lsa_type, uint8_t opaque_type)
2d33f157 1925{
d62a17ae 1926 struct param_t {
1927 struct ospf_apiserver *apiserv;
d7c0a89a
QY
1928 uint8_t lsa_type;
1929 uint8_t opaque_type;
d62a17ae 1930 } param;
1931 struct listnode *node, *nnode;
1932 struct ospf *ospf;
1933 struct ospf_area *area;
1934
b5a8894d 1935 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1936 assert(ospf);
1937
1938 /* Set parameter struct. */
1939 param.apiserv = apiserv;
1940 param.lsa_type = lsa_type;
1941 param.opaque_type = opaque_type;
1942
1943 switch (lsa_type) {
1944 struct route_node *rn;
1945 struct ospf_lsa *lsa;
1946
1947 case OSPF_OPAQUE_LINK_LSA:
1948 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
996c9314 1949 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
044506e7
DS
1950 apiserver_flush_opaque_type_callback(
1951 lsa, (void *)&param, 0);
d62a17ae 1952 break;
1953 case OSPF_OPAQUE_AREA_LSA:
1954 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
996c9314 1955 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
044506e7
DS
1956 apiserver_flush_opaque_type_callback(
1957 lsa, (void *)&param, 0);
d62a17ae 1958 break;
1959 case OSPF_OPAQUE_AS_LSA:
996c9314 1960 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf), rn, lsa)
044506e7
DS
1961 apiserver_flush_opaque_type_callback(lsa,
1962 (void *)&param, 0);
d62a17ae 1963 break;
1964 default:
1965 break;
1966 }
1967 return;
2d33f157 1968}
1969
1970
1971/* -----------------------------------------------------------
d62a17ae 1972 * Followings are callback functions to handle opaque types
2d33f157 1973 * -----------------------------------------------------------
1974 */
1975
d62a17ae 1976int ospf_apiserver_new_if(struct interface *ifp)
2d33f157 1977{
d62a17ae 1978 struct ospf_interface *oi;
1979
1980 /* For some strange reason it seems possible that we are invoked
1981 with an interface that has no name. This seems to happen during
1982 initialization. Return if this happens */
1983
1984 if (ifp->name[0] == '\0') {
1985 /* interface has empty name */
1986 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1987 return 0;
1988 }
1989
1990 /* zlog_warn for debugging */
1991 zlog_warn("ospf_apiserver_new_if");
1992 zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
1993 ifp->ifindex);
1994
1995 if (ifp->name[0] == '\0') {
1996 /* interface has empty name */
1997 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1998 return 0;
1999 }
2000
2001 oi = ospf_apiserver_if_lookup_by_ifp(ifp);
2002
2003 if (!oi) {
2004 /* This interface is known to Zebra but not to OSPF daemon yet.
2005 */
2006 zlog_warn(
2007 "ospf_apiserver_new_if: interface %s not known to OSPFd?",
2008 ifp->name);
2009 return 0;
2010 }
2011
2012 assert(oi);
2013
2014 /* New interface added to OSPF, tell clients about it */
2015 if (listcount(apiserver_list) > 0) {
2016 ospf_apiserver_clients_notify_new_if(oi);
2017 }
2018 return 0;
2d33f157 2019}
2020
d62a17ae 2021int ospf_apiserver_del_if(struct interface *ifp)
2d33f157 2022{
d62a17ae 2023 struct ospf_interface *oi;
2024
2025 /* zlog_warn for debugging */
2026 zlog_warn("ospf_apiserver_del_if");
2027 zlog_warn("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
2028 ifp->ifindex);
2029
2030 oi = ospf_apiserver_if_lookup_by_ifp(ifp);
2031
2032 if (!oi) {
2033 /* This interface is known to Zebra but not to OSPF daemon
2034 anymore. No need to tell clients about it */
2035 return 0;
2036 }
2037
2038 /* Interface deleted, tell clients about it */
2039 if (listcount(apiserver_list) > 0) {
2040 ospf_apiserver_clients_notify_del_if(oi);
2041 }
2042 return 0;
2d33f157 2043}
2044
d62a17ae 2045void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state)
2d33f157 2046{
d62a17ae 2047 /* Tell clients about interface change */
2d33f157 2048
d62a17ae 2049 /* zlog_warn for debugging */
2050 zlog_warn("ospf_apiserver_ism_change");
2051 if (listcount(apiserver_list) > 0) {
2052 ospf_apiserver_clients_notify_ism_change(oi);
2053 }
2d33f157 2054
d62a17ae 2055 zlog_warn("oi->ifp->name=%s", oi->ifp->name);
2056 zlog_warn("old_state=%d", old_state);
2057 zlog_warn("oi->state=%d", oi->state);
2d33f157 2058}
2059
d62a17ae 2060void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
2d33f157 2061{
d62a17ae 2062 /* Neighbor status changed, tell clients about it */
2063 zlog_warn("ospf_apiserver_nsm_change");
2064 if (listcount(apiserver_list) > 0) {
2065 ospf_apiserver_clients_notify_nsm_change(nbr);
2066 }
2d33f157 2067}
2068
d62a17ae 2069void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa)
2d33f157 2070{
d62a17ae 2071 struct opaque_lsa {
2072 struct lsa_header header;
d7c0a89a 2073 uint8_t data[1]; /* opaque data have variable length. This is
d62a17ae 2074 start
2075 address */
2076 };
2077 struct opaque_lsa *olsa;
2078 int opaquelen;
2079
2080 olsa = (struct opaque_lsa *)lsa->data;
2081
2082 if (VALID_OPAQUE_INFO_LEN(lsa->data))
2083 opaquelen = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2084 else
2085 opaquelen = 0;
2086
2087 /* Output information about opaque LSAs */
2088 if (vty != NULL) {
2089 int i;
2090 vty_out(vty,
2091 " Added using OSPF API: %u octets of opaque data %s\n",
2092 opaquelen,
2093 VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2094 : "(Invalid length?)");
2095 vty_out(vty, " Opaque data: ");
2096
2097 for (i = 0; i < opaquelen; i++) {
2098 vty_out(vty, "0x%x ", olsa->data[i]);
2099 }
2100 vty_out(vty, "\n");
2101 } else {
2102 int i;
2103 zlog_debug(
2104 " Added using OSPF API: %u octets of opaque data %s",
2105 opaquelen,
2106 VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2107 : "(Invalid length?)");
2108 zlog_debug(" Opaque data: ");
2109
2110 for (i = 0; i < opaquelen; i++) {
2111 zlog_debug("0x%x ", olsa->data[i]);
2112 }
2113 zlog_debug("\n");
2114 }
2115 return;
2d33f157 2116}
2117
2118/* -----------------------------------------------------------
2119 * Followings are functions to notify clients about events
2120 * -----------------------------------------------------------
2121 */
2122
2123/* Send a message to all clients. This is useful for messages
2124 that need to be notified to all clients (such as interface
2125 changes) */
2126
d62a17ae 2127void ospf_apiserver_clients_notify_all(struct msg *msg)
2d33f157 2128{
d62a17ae 2129 struct listnode *node, *nnode;
2130 struct ospf_apiserver *apiserv;
2d33f157 2131
d62a17ae 2132 /* Send message to all clients */
2133 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv))
2134 ospf_apiserver_send_msg(apiserv, msg);
2d33f157 2135}
2136
2137/* An interface is now ready to accept opaque LSAs. Notify all
2138 clients that registered to use this opaque type */
d62a17ae 2139void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi)
2d33f157 2140{
d62a17ae 2141 struct listnode *node, *nnode;
2142 struct msg *msg;
2143 struct ospf_apiserver *apiserv;
2144
2145 assert(oi);
2146 if (!oi->address) {
2147 zlog_warn("Interface has no address?");
2148 return;
2149 }
2150
2151 if (!ospf_apiserver_is_ready_type9(oi)) {
2152 zlog_warn("Interface not ready for type 9?");
2153 return;
2154 }
2155
2156 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2157 struct listnode *node2, *nnode2;
2158 struct registered_opaque_type *r;
2159
2160 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2161 r)) {
2162 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
2163 msg = new_msg_ready_notify(
2164 0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
2165 oi->address->u.prefix4);
2166 if (!msg) {
2167 zlog_warn(
2168 "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2d33f157 2169#ifdef NOTYET
d62a17ae 2170 /* Cannot allocate new message. What
2171 * should we do? */
2172 ospf_apiserver_free(apiserv);
2d33f157 2173#endif
d62a17ae 2174 goto out;
2175 }
2d33f157 2176
d62a17ae 2177 ospf_apiserver_send_msg(apiserv, msg);
2178 msg_free(msg);
2179 }
2180 }
2d33f157 2181 }
2d33f157 2182
2183out:
d62a17ae 2184 return;
2d33f157 2185}
2186
d62a17ae 2187void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area)
2d33f157 2188{
d62a17ae 2189 struct listnode *node, *nnode;
2190 struct msg *msg;
2191 struct ospf_apiserver *apiserv;
2192
2193 assert(area);
2194
2195 if (!ospf_apiserver_is_ready_type10(area)) {
2196 zlog_warn("Area not ready for type 10?");
2197 return;
2198 }
2199
2200 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2201 struct listnode *node2, *nnode2;
2202 struct registered_opaque_type *r;
2203
2204 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2205 r)) {
2206 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
2207 msg = new_msg_ready_notify(
2208 0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
2209 area->area_id);
2210 if (!msg) {
2211 zlog_warn(
2212 "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2d33f157 2213#ifdef NOTYET
d62a17ae 2214 /* Cannot allocate new message. What
2215 * should we do? */
2216 ospf_apiserver_free(apiserv);
2d33f157 2217#endif
d62a17ae 2218 goto out;
2219 }
2d33f157 2220
d62a17ae 2221 ospf_apiserver_send_msg(apiserv, msg);
2222 msg_free(msg);
2223 }
2224 }
2d33f157 2225 }
2d33f157 2226
2227out:
d62a17ae 2228 return;
2d33f157 2229}
2230
2231
d62a17ae 2232void ospf_apiserver_clients_notify_ready_type11(struct ospf *top)
2d33f157 2233{
d62a17ae 2234 struct listnode *node, *nnode;
2235 struct msg *msg;
2236 struct in_addr id_null = {.s_addr = 0L};
2237 struct ospf_apiserver *apiserv;
2238
2239 assert(top);
2240
2241 if (!ospf_apiserver_is_ready_type11(top)) {
2242 zlog_warn("AS not ready for type 11?");
2243 return;
2244 }
2245
2246 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2247 struct listnode *node2, *nnode2;
2248 struct registered_opaque_type *r;
2249
2250 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2251 r)) {
2252 if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
2253 msg = new_msg_ready_notify(
2254 0, OSPF_OPAQUE_AS_LSA, r->opaque_type,
2255 id_null);
2256 if (!msg) {
2257 zlog_warn(
2258 "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2d33f157 2259#ifdef NOTYET
d62a17ae 2260 /* Cannot allocate new message. What
2261 * should we do? */
2262 ospf_apiserver_free(apiserv);
2d33f157 2263#endif
d62a17ae 2264 goto out;
2265 }
2d33f157 2266
d62a17ae 2267 ospf_apiserver_send_msg(apiserv, msg);
2268 msg_free(msg);
2269 }
2270 }
2d33f157 2271 }
2d33f157 2272
2273out:
d62a17ae 2274 return;
2d33f157 2275}
2276
d62a17ae 2277void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi)
2d33f157 2278{
d62a17ae 2279 struct msg *msg;
2280
2281 msg = new_msg_new_if(0, oi->address->u.prefix4, oi->area->area_id);
2282 if (msg != NULL) {
2283 ospf_apiserver_clients_notify_all(msg);
2284 msg_free(msg);
2285 }
2d33f157 2286}
2287
d62a17ae 2288void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi)
2d33f157 2289{
d62a17ae 2290 struct msg *msg;
2291
2292 msg = new_msg_del_if(0, oi->address->u.prefix4);
2293 if (msg != NULL) {
2294 ospf_apiserver_clients_notify_all(msg);
2295 msg_free(msg);
2296 }
2d33f157 2297}
2298
d62a17ae 2299void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi)
2d33f157 2300{
d62a17ae 2301 struct msg *msg;
2302 struct in_addr ifaddr = {.s_addr = 0L};
2303 struct in_addr area_id = {.s_addr = 0L};
2304
2305 assert(oi);
2306 assert(oi->ifp);
2307
2308 if (oi->address) {
2309 ifaddr = oi->address->u.prefix4;
2310 }
2311 if (oi->area) {
2312 area_id = oi->area->area_id;
2313 }
2314
2315 msg = new_msg_ism_change(0, ifaddr, area_id, oi->state);
2316 if (!msg) {
2317 zlog_warn(
2318 "apiserver_clients_notify_ism_change: msg_new failed");
2319 return;
2320 }
2321
2322 ospf_apiserver_clients_notify_all(msg);
2323 msg_free(msg);
2d33f157 2324}
2325
d62a17ae 2326void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr)
2d33f157 2327{
d62a17ae 2328 struct msg *msg;
2329 struct in_addr ifaddr = {.s_addr = 0L};
7295876a 2330 struct in_addr nbraddr;
2d33f157 2331
d62a17ae 2332 assert(nbr);
2d33f157 2333
d62a17ae 2334 if (nbr->oi) {
2335 ifaddr = nbr->oi->address->u.prefix4;
2336 }
2d33f157 2337
d62a17ae 2338 nbraddr = nbr->address.u.prefix4;
2d33f157 2339
d62a17ae 2340 msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id,
2341 nbr->state);
2342 if (!msg) {
2343 zlog_warn(
2344 "apiserver_clients_notify_nsm_change: msg_new failed");
2345 return;
2346 }
2d33f157 2347
d62a17ae 2348 ospf_apiserver_clients_notify_all(msg);
2349 msg_free(msg);
2d33f157 2350}
2351
d7c0a89a 2352static void apiserver_clients_lsa_change_notify(uint8_t msgtype,
d62a17ae 2353 struct ospf_lsa *lsa)
2d33f157 2354{
d62a17ae 2355 struct msg *msg;
2356 struct listnode *node, *nnode;
2357 struct ospf_apiserver *apiserv;
2358
2359 /* Default area for AS-External and Opaque11 LSAs */
2360 struct in_addr area_id = {.s_addr = 0L};
2361
2362 /* Default interface for non Opaque9 LSAs */
2363 struct in_addr ifaddr = {.s_addr = 0L};
2364
2365 if (lsa->area) {
2366 area_id = lsa->area->area_id;
2367 }
2368 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2369 assert(lsa->oi);
2370 ifaddr = lsa->oi->address->u.prefix4;
2371 }
2372
2373 /* Prepare message that can be sent to clients that have a matching
2374 filter */
2375 msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2376 ifaddr, area_id,
2377 lsa->flags & OSPF_LSA_SELF, lsa->data);
2378 if (!msg) {
2379 zlog_warn(
2380 "apiserver_clients_lsa_change_notify: msg_new failed");
2381 return;
2382 }
2383
2384 /* Now send message to all clients with a matching filter */
2385 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2386 struct lsa_filter_type *filter;
d7c0a89a
QY
2387 uint16_t mask;
2388 uint32_t *area;
d62a17ae 2389 int i;
2390
2391 /* Check filter for this client. */
2392 filter = apiserv->filter;
2393
2394 /* Check area IDs in case of non AS-E LSAs.
2395 * If filter has areas (num_areas > 0),
2396 * then one of the areas must match the area ID of this LSA. */
2397
2398 i = filter->num_areas;
2399 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA)
2400 || (lsa->data->type == OSPF_OPAQUE_AS_LSA)) {
2401 i = 0;
2d33f157 2402 }
d62a17ae 2403
2404 if (i > 0) {
d7c0a89a 2405 area = (uint32_t *)(filter + 1);
d62a17ae 2406 while (i) {
2407 if (*area == area_id.s_addr) {
2408 break;
2409 }
2410 i--;
2411 area++;
2412 }
2413 } else {
2414 i = 1;
2415 }
2416
2417 if (i > 0) {
2418 /* Area match. Check LSA type. */
2419 mask = ntohs(filter->typemask);
2420
2421 if (mask & Power2[lsa->data->type]) {
2422 /* Type also matches. Check origin. */
2423 if ((filter->origin == ANY_ORIGIN)
2424 || (filter->origin == IS_LSA_SELF(lsa))) {
2425 ospf_apiserver_send_msg(apiserv, msg);
2426 }
2427 }
2d33f157 2428 }
2d33f157 2429 }
d62a17ae 2430 /* Free message since it is not used anymore */
2431 msg_free(msg);
2d33f157 2432}
2433
2434
2435/* -------------------------------------------------------------
2436 * Followings are hooks invoked when LSAs are updated or deleted
2437 * -------------------------------------------------------------
2438 */
2439
2440
d7c0a89a 2441static int apiserver_notify_clients_lsa(uint8_t msgtype, struct ospf_lsa *lsa)
2d33f157 2442{
d62a17ae 2443 struct msg *msg;
2444 /* default area for AS-External and Opaque11 LSAs */
2445 struct in_addr area_id = {.s_addr = 0L};
2446
2447 /* default interface for non Opaque9 LSAs */
2448 struct in_addr ifaddr = {.s_addr = 0L};
2449
2450 /* Only notify this update if the LSA's age is smaller than
2451 MAXAGE. Otherwise clients would see LSA updates with max age just
2452 before they are deleted from the LSDB. LSA delete messages have
2453 MAXAGE too but should not be filtered. */
2454 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2455 return 0;
2456 }
2457
2458 if (lsa->area) {
2459 area_id = lsa->area->area_id;
2460 }
2461 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2462 ifaddr = lsa->oi->address->u.prefix4;
2463 }
2464 msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2465 ifaddr, area_id,
2466 lsa->flags & OSPF_LSA_SELF, lsa->data);
2467 if (!msg) {
2468 zlog_warn("notify_clients_lsa: msg_new failed");
2469 return -1;
2470 }
2471 /* Notify all clients that new LSA is added/updated */
2472 apiserver_clients_lsa_change_notify(msgtype, lsa);
2473
2474 /* Clients made their own copies of msg so we can free msg here */
2475 msg_free(msg);
2476
2477 return 0;
2d33f157 2478}
2479
d62a17ae 2480int ospf_apiserver_lsa_update(struct ospf_lsa *lsa)
2d33f157 2481{
d62a17ae 2482 return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY, lsa);
2d33f157 2483}
2484
d62a17ae 2485int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa)
2d33f157 2486{
d62a17ae 2487 return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY, lsa);
2d33f157 2488}
2489
2490#endif /* SUPPORT_OSPF_API */