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