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