]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_apiserver.c
Merge pull request #9324 from donaldsharp/bgp_info_cmp
[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;
8db278b5 1159 size_t size;
d62a17ae 1160
1161 rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
1162
1163 /* Get request sequence number */
1164 seqnum = msg_get_seq(msg);
1165
1166 /* Free existing filter in apiserv. */
1167 XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1168 /* Alloc new space for filter. */
8db278b5
OD
1169 size = ntohs(msg->hdr.msglen);
1170 if (size < OSPF_MAX_LSA_SIZE) {
d62a17ae 1171
8db278b5 1172 apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size);
0ce1ca80 1173
8db278b5
OD
1174 /* copy it over. */
1175 memcpy(apiserv->filter, &rmsg->filter, size);
1176 rc = OSPF_API_OK;
1177 } else
1178 rc = OSPF_API_NOMEMORY;
0ce1ca80 1179
d62a17ae 1180 /* Send a reply back to client with return code */
1181 rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1182 return rc;
2d33f157 1183}
1184
1185
1186/* -----------------------------------------------------------
1187 * Followings are functions for LSDB synchronization.
1188 * -----------------------------------------------------------
1189 */
1190
d62a17ae 1191static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg,
1192 int int_arg)
2d33f157 1193{
d62a17ae 1194 struct ospf_apiserver *apiserv;
1195 int seqnum;
1196 struct msg *msg;
1197 struct param_t {
1198 struct ospf_apiserver *apiserv;
1199 struct lsa_filter_type *filter;
1200 } * param;
1201 int rc = -1;
1202
1203 /* Sanity check */
1204 assert(lsa->data);
1205 assert(p_arg);
1206
1207 param = (struct param_t *)p_arg;
1208 apiserv = param->apiserv;
d7c0a89a 1209 seqnum = (uint32_t)int_arg;
d62a17ae 1210
1211 /* Check origin in filter. */
1212 if ((param->filter->origin == ANY_ORIGIN)
1213 || (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) {
1214
1215 /* Default area for AS-External and Opaque11 LSAs */
1216 struct in_addr area_id = {.s_addr = 0L};
1217
1218 /* Default interface for non Opaque9 LSAs */
1219 struct in_addr ifaddr = {.s_addr = 0L};
1220
1221 if (lsa->area) {
1222 area_id = lsa->area->area_id;
1223 }
1224 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
1225 ifaddr = lsa->oi->address->u.prefix4;
1226 }
1227
1228 msg = new_msg_lsa_change_notify(
1229 MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id,
1230 lsa->flags & OSPF_LSA_SELF, lsa->data);
1231 if (!msg) {
1232 zlog_warn(
1233 "apiserver_sync_callback: new_msg_update failed");
2d33f157 1234#ifdef NOTYET
9d303b37
DL
1235 /* Cannot allocate new message. What should we do? */
1236 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1237 here XXX
1238 */
2d33f157 1239#endif
d62a17ae 1240 goto out;
1241 }
2d33f157 1242
d62a17ae 1243 /* Send LSA */
1244 ospf_apiserver_send_msg(apiserv, msg);
1245 msg_free(msg);
1246 }
1247 rc = 0;
2d33f157 1248
1249out:
d62a17ae 1250 return rc;
2d33f157 1251}
1252
d62a17ae 1253int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
1254 struct msg *msg)
2d33f157 1255{
d62a17ae 1256 struct listnode *node, *nnode;
d7c0a89a 1257 uint32_t seqnum;
d62a17ae 1258 int rc = 0;
1259 struct msg_sync_lsdb *smsg;
1260 struct ospf_apiserver_param_t {
1261 struct ospf_apiserver *apiserv;
1262 struct lsa_filter_type *filter;
1263 } param;
d7c0a89a 1264 uint16_t mask;
d62a17ae 1265 struct route_node *rn;
1266 struct ospf_lsa *lsa;
1267 struct ospf *ospf;
1268 struct ospf_area *area;
1269
b5a8894d 1270 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1271
1272 /* Get request sequence number */
1273 seqnum = msg_get_seq(msg);
1274 /* Set sync msg. */
1275 smsg = (struct msg_sync_lsdb *)STREAM_DATA(msg->s);
1276
1277 /* Set parameter struct. */
1278 param.apiserv = apiserv;
1279 param.filter = &smsg->filter;
1280
1281 /* Remember mask. */
1282 mask = ntohs(smsg->filter.typemask);
1283
1284 /* Iterate over all areas. */
1285 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1286 int i;
d7c0a89a 1287 uint32_t *area_id = NULL;
d62a17ae 1288
1289 /* Compare area_id with area_ids in sync request. */
1290 if ((i = smsg->filter.num_areas) > 0) {
1291 /* Let area_id point to the list of area IDs,
1292 * which is at the end of smsg->filter. */
d7c0a89a 1293 area_id = (uint32_t *)(&smsg->filter + 1);
d62a17ae 1294 while (i) {
1295 if (*area_id == area->area_id.s_addr) {
1296 break;
1297 }
1298 i--;
1299 area_id++;
1300 }
1301 } else {
1302 i = 1;
1303 }
1304
1305 /* If area was found, then i>0 here. */
1306 if (i) {
1307 /* Check msg type. */
1308 if (mask & Power2[OSPF_ROUTER_LSA])
996c9314 1309 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
044506e7
DS
1310 apiserver_sync_callback(
1311 lsa, (void *)&param, seqnum);
d62a17ae 1312 if (mask & Power2[OSPF_NETWORK_LSA])
996c9314 1313 LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
044506e7
DS
1314 apiserver_sync_callback(
1315 lsa, (void *)&param, seqnum);
d62a17ae 1316 if (mask & Power2[OSPF_SUMMARY_LSA])
996c9314 1317 LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
044506e7
DS
1318 apiserver_sync_callback(
1319 lsa, (void *)&param, seqnum);
d62a17ae 1320 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
996c9314 1321 LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
044506e7
DS
1322 apiserver_sync_callback(
1323 lsa, (void *)&param, seqnum);
d62a17ae 1324 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
996c9314 1325 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
044506e7
DS
1326 apiserver_sync_callback(
1327 lsa, (void *)&param, seqnum);
d62a17ae 1328 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
996c9314 1329 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
044506e7
DS
1330 apiserver_sync_callback(
1331 lsa, (void *)&param, seqnum);
2d33f157 1332 }
d62a17ae 1333 }
1334
1335 /* For AS-external LSAs */
1336 if (ospf->lsdb) {
1337 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
996c9314 1338 LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
044506e7
DS
1339 apiserver_sync_callback(lsa, (void *)&param,
1340 seqnum);
d62a17ae 1341 }
1342
1343 /* For AS-external opaque LSAs */
1344 if (ospf->lsdb) {
1345 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
996c9314 1346 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
044506e7
DS
1347 apiserver_sync_callback(lsa, (void *)&param,
1348 seqnum);
d62a17ae 1349 }
1350
1351 /* Send a reply back to client with return code */
1352 rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1353 return rc;
2d33f157 1354}
1355
1356
1357/* -----------------------------------------------------------
1358 * Followings are functions to originate or update LSA
1359 * from an application.
1360 * -----------------------------------------------------------
1361 */
1362
1363/* Create a new internal opaque LSA by taking prototype and filling in
1364 missing fields such as age, sequence number, advertising router,
1365 checksum and so on. The interface parameter is used for type 9
1366 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1367 nor interface. */
1368
d62a17ae 1369struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
1370 struct ospf_interface *oi,
1371 struct lsa_header *protolsa)
2d33f157 1372{
d62a17ae 1373 struct stream *s;
1374 struct lsa_header *newlsa;
1375 struct ospf_lsa *new = NULL;
d7c0a89a
QY
1376 uint8_t options = 0x0;
1377 uint16_t length;
d62a17ae 1378
1379 struct ospf *ospf;
1380
c0f3f7cd 1381 if (oi && oi->ospf)
0d31e63e
CS
1382 ospf = oi->ospf;
1383 else
1384 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1385
d62a17ae 1386 assert(ospf);
1387
1388 /* Create a stream for internal opaque LSA */
1389 if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
1390 zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
1391 return NULL;
1392 }
1393
1394 newlsa = (struct lsa_header *)STREAM_DATA(s);
1395
1396 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1397 have to set options? */
1398
1399 if (area) {
1400 options = LSA_OPTIONS_GET(area);
1401 options |= LSA_OPTIONS_NSSA_GET(area);
1402 }
1403
1404 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1405
1406 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
96b663a3
MS
1407 zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
1408 protolsa->type, &protolsa->id);
d62a17ae 1409 }
1410
1411 /* Set opaque-LSA header fields. */
1412 lsa_header_set(s, options, protolsa->type, protolsa->id,
1413 ospf->router_id);
1414
1415 /* Set opaque-LSA body fields. */
d7c0a89a 1416 stream_put(s, ((uint8_t *)protolsa) + sizeof(struct lsa_header),
d62a17ae 1417 ntohs(protolsa->length) - sizeof(struct lsa_header));
1418
1419 /* Determine length of LSA. */
1420 length = stream_get_endp(s);
1421 newlsa->length = htons(length);
1422
1423 /* Create OSPF LSA. */
5b3d4186 1424 new = ospf_lsa_new_and_data(length);
d62a17ae 1425
1426 new->area = area;
1427 new->oi = oi;
0d31e63e 1428 new->vrf_id = ospf->vrf_id;
d62a17ae 1429
1430 SET_FLAG(new->flags, OSPF_LSA_SELF);
1431 memcpy(new->data, newlsa, length);
1432 stream_free(s);
1433
1434 return new;
2d33f157 1435}
1436
1437
d62a17ae 1438int ospf_apiserver_is_ready_type9(struct ospf_interface *oi)
2d33f157 1439{
d62a17ae 1440 /* Type 9 opaque LSA can be originated if there is at least one
1441 active opaque-capable neighbor attached to the outgoing
1442 interface. */
2d33f157 1443
d62a17ae 1444 return (ospf_nbr_count_opaque_capable(oi) > 0);
2d33f157 1445}
1446
d62a17ae 1447int ospf_apiserver_is_ready_type10(struct ospf_area *area)
2d33f157 1448{
d62a17ae 1449 /* Type 10 opaque LSA can be originated if there is at least one
1450 interface belonging to the area that has an active opaque-capable
1451 neighbor. */
1452 struct listnode *node, *nnode;
1453 struct ospf_interface *oi;
1454
1455 for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi))
1456 /* Is there an active neighbor attached to this interface? */
1457 if (ospf_apiserver_is_ready_type9(oi))
1458 return 1;
1459
1460 /* No active neighbor in area */
1461 return 0;
2d33f157 1462}
1463
d62a17ae 1464int ospf_apiserver_is_ready_type11(struct ospf *ospf)
2d33f157 1465{
d62a17ae 1466 /* Type 11 opaque LSA can be originated if there is at least one
1467 interface
1468 that has an active opaque-capable neighbor. */
1469 struct listnode *node, *nnode;
1470 struct ospf_interface *oi;
1471
1472 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
1473 /* Is there an active neighbor attached to this interface? */
1474 if (ospf_apiserver_is_ready_type9(oi))
1475 return 1;
1476
1477 /* No active neighbor at all */
1478 return 0;
2d33f157 1479}
1480
1481
d62a17ae 1482int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
1483 struct msg *msg)
2d33f157 1484{
d62a17ae 1485 struct msg_originate_request *omsg;
1486 struct lsa_header *data;
1487 struct ospf_lsa *new;
1488 struct ospf_lsa *old;
1489 struct ospf_area *area = NULL;
1490 struct ospf_interface *oi = NULL;
1491 struct ospf_lsdb *lsdb = NULL;
1492 struct ospf *ospf;
1493 int lsa_type, opaque_type;
1494 int ready = 0;
1495 int rc = 0;
1496
b5a8894d 1497 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1498
1499 /* Extract opaque LSA data from message */
1500 omsg = (struct msg_originate_request *)STREAM_DATA(msg->s);
1501 data = &omsg->data;
1502
1503 /* Determine interface for type9 or area for type10 LSAs. */
1504 switch (data->type) {
1505 case OSPF_OPAQUE_LINK_LSA:
1506 oi = ospf_apiserver_if_lookup_by_addr(omsg->ifaddr);
1507 if (!oi) {
96b663a3
MS
1508 zlog_warn("apiserver_originate: unknown interface %pI4",
1509 &omsg->ifaddr);
d62a17ae 1510 rc = OSPF_API_NOSUCHINTERFACE;
1511 goto out;
1512 }
1513 area = oi->area;
1514 lsdb = area->lsdb;
1515 break;
1516 case OSPF_OPAQUE_AREA_LSA:
1517 area = ospf_area_lookup_by_area_id(ospf, omsg->area_id);
1518 if (!area) {
96b663a3
MS
1519 zlog_warn("apiserver_originate: unknown area %pI4",
1520 &omsg->area_id);
d62a17ae 1521 rc = OSPF_API_NOSUCHAREA;
1522 goto out;
1523 }
1524 lsdb = area->lsdb;
1525 break;
1526 case OSPF_OPAQUE_AS_LSA:
1527 lsdb = ospf->lsdb;
1528 break;
1529 default:
1530 /* We can only handle opaque types here */
1531 zlog_warn(
1532 "apiserver_originate: Cannot originate non-opaque LSA type %d",
1533 data->type);
1534 rc = OSPF_API_ILLEGALLSATYPE;
1535 goto out;
1536 }
1537
1538 /* Check if we registered this opaque type */
1539 lsa_type = data->type;
1540 opaque_type = GET_OPAQUE_TYPE(ntohl(data->id.s_addr));
1541
1542 if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1543 opaque_type)) {
1544 zlog_warn(
1545 "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered",
1546 lsa_type, opaque_type);
1547 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1548 goto out;
1549 }
1550
1551 /* Make sure that the neighbors are ready before we can originate */
1552 switch (data->type) {
1553 case OSPF_OPAQUE_LINK_LSA:
1554 ready = ospf_apiserver_is_ready_type9(oi);
1555 break;
1556 case OSPF_OPAQUE_AREA_LSA:
1557 ready = ospf_apiserver_is_ready_type10(area);
1558 break;
1559 case OSPF_OPAQUE_AS_LSA:
1560 ready = ospf_apiserver_is_ready_type11(ospf);
1561 break;
1562 default:
1563 break;
1564 }
1565
1566 if (!ready) {
1567 zlog_warn("Neighbors not ready to originate type %d",
1568 data->type);
1569 rc = OSPF_API_NOTREADY;
1570 goto out;
1571 }
1572
1573 /* Create OSPF's internal opaque LSA representation */
1574 new = ospf_apiserver_opaque_lsa_new(area, oi, data);
1575 if (!new) {
1576 rc = OSPF_API_NOMEMORY; /* XXX */
1577 goto out;
1578 }
1579
1580 /* Determine if LSA is new or an update for an existing one. */
1581 old = ospf_lsdb_lookup(lsdb, new);
1582
1583 if (!old) {
1584 /* New LSA install in LSDB. */
1585 rc = ospf_apiserver_originate1(new);
1586 } else {
1587 /*
1588 * Keep the new LSA instance in the "waiting place" until the
1589 * next
1590 * refresh timing. If several LSA update requests for the same
1591 * LSID
1592 * have issued by peer, the last one takes effect.
1593 */
1594 new->lsdb = &apiserv->reserve;
1595 ospf_lsdb_add(&apiserv->reserve, new);
1596
1597 /* Kick the scheduler function. */
1598 ospf_opaque_lsa_refresh_schedule(old);
1599 }
2d33f157 1600
1601out:
1602
d62a17ae 1603 /* Send a reply back to client with return code */
1604 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1605 return rc;
2d33f157 1606}
1607
1608
1609/* -----------------------------------------------------------
d62a17ae 1610 * Flood an LSA within its flooding scope.
2d33f157 1611 * -----------------------------------------------------------
1612 */
1613
1614/* XXX We can probably use ospf_flood_through instead of this function
d62a17ae 1615 but then we need the neighbor parameter. If we set nbr to
2d33f157 1616 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1617
d62a17ae 1618void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa)
2d33f157 1619{
d62a17ae 1620 assert(lsa);
1621
1622 switch (lsa->data->type) {
1623 case OSPF_OPAQUE_LINK_LSA:
1624 /* Increment counters? XXX */
1625
1626 /* Flood LSA through local network. */
1627 ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
1628 break;
1629 case OSPF_OPAQUE_AREA_LSA:
1630 /* Update LSA origination count. */
1631 assert(lsa->area);
1632 lsa->area->ospf->lsa_originate_count++;
1633
1634 /* Flood LSA through area. */
1635 ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
1636 break;
1637 case OSPF_OPAQUE_AS_LSA: {
1638 struct ospf *ospf;
1639
b5a8894d 1640 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1641 assert(ospf);
1642
1643 /* Increment counters? XXX */
1644
1645 /* Flood LSA through AS. */
1646 ospf_flood_through_as(ospf, NULL /*nbr */, lsa);
1647 break;
1648 }
1649 }
2d33f157 1650}
1651
d62a17ae 1652int ospf_apiserver_originate1(struct ospf_lsa *lsa)
2d33f157 1653{
d62a17ae 1654 struct ospf *ospf;
99b7c5d6 1655
b5a8894d 1656 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1657 assert(ospf);
99b7c5d6 1658
d62a17ae 1659 /* Install this LSA into LSDB. */
1660 if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
cf444bcf 1661 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
542a208f 1662 "ospf_apiserver_originate1: ospf_lsa_install failed");
d62a17ae 1663 return -1;
1664 }
2d33f157 1665
d62a17ae 1666/* Flood LSA within scope */
2d33f157 1667
1668#ifdef NOTYET
d62a17ae 1669 /*
1670 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1671 * parameter, and thus it does not cause SIGSEGV error.
1672 */
1673 ospf_flood_through(NULL /*nbr */, lsa);
1674#else /* NOTYET */
1675
1676 ospf_apiserver_flood_opaque_lsa(lsa);
2d33f157 1677#endif /* NOTYET */
1678
d62a17ae 1679 return 0;
2d33f157 1680}
1681
1682
1683/* Opaque LSAs of type 9 on a specific interface can now be
1684 originated. Tell clients that registered type 9. */
d62a17ae 1685int ospf_apiserver_lsa9_originator(void *arg)
2d33f157 1686{
d62a17ae 1687 struct ospf_interface *oi;
2d33f157 1688
d62a17ae 1689 oi = (struct ospf_interface *)arg;
1690 if (listcount(apiserver_list) > 0) {
1691 ospf_apiserver_clients_notify_ready_type9(oi);
1692 }
1693 return 0;
2d33f157 1694}
1695
d62a17ae 1696int ospf_apiserver_lsa10_originator(void *arg)
2d33f157 1697{
d62a17ae 1698 struct ospf_area *area;
2d33f157 1699
d62a17ae 1700 area = (struct ospf_area *)arg;
1701 if (listcount(apiserver_list) > 0) {
1702 ospf_apiserver_clients_notify_ready_type10(area);
1703 }
1704 return 0;
2d33f157 1705}
1706
d62a17ae 1707int ospf_apiserver_lsa11_originator(void *arg)
2d33f157 1708{
d62a17ae 1709 struct ospf *ospf;
2d33f157 1710
d62a17ae 1711 ospf = (struct ospf *)arg;
1712 if (listcount(apiserver_list) > 0) {
1713 ospf_apiserver_clients_notify_ready_type11(ospf);
1714 }
1715 return 0;
2d33f157 1716}
1717
1718
1719/* Periodically refresh opaque LSAs so that they do not expire in
1720 other routers. */
d62a17ae 1721struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
2d33f157 1722{
d62a17ae 1723 struct ospf_apiserver *apiserv;
1724 struct ospf_lsa *new = NULL;
1725 struct ospf *ospf;
1726
ed35fc05 1727 assert(lsa);
1728
b5a8894d 1729 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1730 assert(ospf);
1731
1732 apiserv = lookup_apiserver_by_lsa(lsa);
1733 if (!apiserv) {
1734 zlog_warn(
1735 "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
1736 dump_lsa_key(lsa));
1737 lsa->data->ls_age =
1738 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
4adf00f7 1739 goto out;
d62a17ae 1740 }
1741
1742 if (IS_LSA_MAXAGE(lsa)) {
1743 ospf_opaque_lsa_flush_schedule(lsa);
1744 goto out;
1745 }
1746
1747 /* Check if updated version of LSA instance has already prepared. */
1748 new = ospf_lsdb_lookup(&apiserv->reserve, lsa);
1749 if (!new) {
1750 /* This is a periodic refresh, driven by core OSPF mechanism. */
1751 new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi,
1752 lsa->data);
1753 if (!new) {
1754 zlog_warn(
1755 "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1756 goto out;
1757 }
1758 } else {
1759 /* This is a forcible refresh, requested by OSPF-API client. */
1760 ospf_lsdb_delete(&apiserv->reserve, new);
1761 new->lsdb = NULL;
1762 }
1763
1764 /* Increment sequence number */
1765 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1766
1767 /* New LSA is in same area. */
1768 new->area = lsa->area;
1769 SET_FLAG(new->flags, OSPF_LSA_SELF);
1770
1771 /* Install LSA into LSDB. */
1772 if (ospf_lsa_install(ospf, new->oi, new) == NULL) {
542a208f 1773 flog_warn(
cf444bcf 1774 EC_OSPF_LSA_INSTALL_FAILURE,
d62a17ae 1775 "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1776 ospf_lsa_unlock(&new);
1777 goto out;
1778 }
1779
1780/* Flood updated LSA through interface, area or AS */
2d33f157 1781
1782#ifdef NOTYET
d62a17ae 1783 ospf_flood_through(NULL /*nbr */, new);
2d33f157 1784#endif /* NOTYET */
d62a17ae 1785 ospf_apiserver_flood_opaque_lsa(new);
2d33f157 1786
d62a17ae 1787 /* Debug logging. */
1788 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
96b663a3
MS
1789 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
1790 new->data->type, &new->data->id);
d62a17ae 1791 ospf_lsa_header_dump(new->data);
1792 }
2d33f157 1793
1794out:
d62a17ae 1795 return new;
2d33f157 1796}
1797
1798
1799/* -----------------------------------------------------------
1800 * Followings are functions to delete LSAs
1801 * -----------------------------------------------------------
1802 */
1803
d62a17ae 1804int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
1805 struct msg *msg)
2d33f157 1806{
d62a17ae 1807 struct msg_delete_request *dmsg;
1808 struct ospf_lsa *old;
1809 struct ospf_area *area = NULL;
1810 struct in_addr id;
1811 int lsa_type, opaque_type;
1812 int rc = 0;
1813 struct ospf *ospf;
1814
b5a8894d 1815 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1816 assert(ospf);
1817
1818 /* Extract opaque LSA from message */
1819 dmsg = (struct msg_delete_request *)STREAM_DATA(msg->s);
1820
1821 /* Lookup area for link-local and area-local opaque LSAs */
1822 switch (dmsg->lsa_type) {
1823 case OSPF_OPAQUE_LINK_LSA:
1824 case OSPF_OPAQUE_AREA_LSA:
1825 area = ospf_area_lookup_by_area_id(ospf, dmsg->area_id);
1826 if (!area) {
96b663a3
MS
1827 zlog_warn("ospf_apiserver_lsa_delete: unknown area %pI4",
1828 &dmsg->area_id);
d62a17ae 1829 rc = OSPF_API_NOSUCHAREA;
1830 goto out;
1831 }
1832 break;
1833 case OSPF_OPAQUE_AS_LSA:
1834 /* AS-external opaque LSAs have no designated area */
1835 area = NULL;
1836 break;
1837 default:
1838 zlog_warn(
1839 "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1840 dmsg->lsa_type);
1841 rc = OSPF_API_ILLEGALLSATYPE;
1842 goto out;
1843 }
1844
1845 /* Check if we registered this opaque type */
1846 lsa_type = dmsg->lsa_type;
1847 opaque_type = dmsg->opaque_type;
1848
1849 if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1850 opaque_type)) {
1851 zlog_warn(
1852 "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
1853 lsa_type, opaque_type);
1854 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1855 goto out;
1856 }
1857
1858 /* opaque_id is in network byte order */
1859 id.s_addr = htonl(
1860 SET_OPAQUE_LSID(dmsg->opaque_type, ntohl(dmsg->opaque_id)));
1861
1862 /*
1863 * Even if the target LSA has once scheduled to flush, it remains in
1864 * the LSDB until it is finally handled by the maxage remover thread.
1865 * Therefore, the lookup function below may return non-NULL result.
1866 */
b5a8894d 1867 old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id);
d62a17ae 1868 if (!old) {
1869 zlog_warn(
96b663a3
MS
1870 "ospf_apiserver_lsa_delete: LSA[Type%d:%pI4] not in LSDB",
1871 dmsg->lsa_type, &id);
d62a17ae 1872 rc = OSPF_API_NOSUCHLSA;
1873 goto out;
1874 }
1875
1876 /* Schedule flushing of LSA from LSDB */
1877 /* NB: Multiple scheduling will produce a warning message, but harmless.
1878 */
1879 ospf_opaque_lsa_flush_schedule(old);
2d33f157 1880
1881out:
1882
d62a17ae 1883 /* Send reply back to client including return code */
1884 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1885 return rc;
2d33f157 1886}
1887
1888/* Flush self-originated opaque LSA */
d62a17ae 1889static int apiserver_flush_opaque_type_callback(struct ospf_lsa *lsa,
1890 void *p_arg, int int_arg)
2d33f157 1891{
d62a17ae 1892 struct param_t {
1893 struct ospf_apiserver *apiserv;
d7c0a89a
QY
1894 uint8_t lsa_type;
1895 uint8_t opaque_type;
d62a17ae 1896 } * param;
1897
1898 /* Sanity check */
1899 assert(lsa->data);
1900 assert(p_arg);
1901 param = (struct param_t *)p_arg;
1902
1903 /* If LSA matches type and opaque type then delete it */
1904 if (IS_LSA_SELF(lsa) && lsa->data->type == param->lsa_type
1905 && GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1906 == param->opaque_type) {
1907 ospf_opaque_lsa_flush_schedule(lsa);
1908 }
1909 return 0;
2d33f157 1910}
1911
1912/* Delete self-originated opaque LSAs of a given opaque type. This
1913 function is called when an application unregisters a given opaque
1914 type or a connection to an application closes and all those opaque
1915 LSAs need to be flushed the LSDB. */
d62a17ae 1916void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
d7c0a89a 1917 uint8_t lsa_type, uint8_t opaque_type)
2d33f157 1918{
d62a17ae 1919 struct param_t {
1920 struct ospf_apiserver *apiserv;
d7c0a89a
QY
1921 uint8_t lsa_type;
1922 uint8_t opaque_type;
d62a17ae 1923 } param;
1924 struct listnode *node, *nnode;
1925 struct ospf *ospf;
1926 struct ospf_area *area;
1927
b5a8894d 1928 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1929 assert(ospf);
1930
1931 /* Set parameter struct. */
1932 param.apiserv = apiserv;
1933 param.lsa_type = lsa_type;
1934 param.opaque_type = opaque_type;
1935
1936 switch (lsa_type) {
1937 struct route_node *rn;
1938 struct ospf_lsa *lsa;
1939
1940 case OSPF_OPAQUE_LINK_LSA:
1941 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
996c9314 1942 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
044506e7
DS
1943 apiserver_flush_opaque_type_callback(
1944 lsa, (void *)&param, 0);
d62a17ae 1945 break;
1946 case OSPF_OPAQUE_AREA_LSA:
1947 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
996c9314 1948 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
044506e7
DS
1949 apiserver_flush_opaque_type_callback(
1950 lsa, (void *)&param, 0);
d62a17ae 1951 break;
1952 case OSPF_OPAQUE_AS_LSA:
996c9314 1953 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf), rn, lsa)
044506e7
DS
1954 apiserver_flush_opaque_type_callback(lsa,
1955 (void *)&param, 0);
d62a17ae 1956 break;
1957 default:
1958 break;
1959 }
1960 return;
2d33f157 1961}
1962
1963
1964/* -----------------------------------------------------------
d62a17ae 1965 * Followings are callback functions to handle opaque types
2d33f157 1966 * -----------------------------------------------------------
1967 */
1968
d62a17ae 1969int ospf_apiserver_new_if(struct interface *ifp)
2d33f157 1970{
d62a17ae 1971 struct ospf_interface *oi;
1972
1973 /* For some strange reason it seems possible that we are invoked
1974 with an interface that has no name. This seems to happen during
1975 initialization. Return if this happens */
1976
1977 if (ifp->name[0] == '\0') {
1978 /* interface has empty name */
1979 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1980 return 0;
1981 }
1982
1983 /* zlog_warn for debugging */
1984 zlog_warn("ospf_apiserver_new_if");
1985 zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
1986 ifp->ifindex);
1987
1988 if (ifp->name[0] == '\0') {
1989 /* interface has empty name */
1990 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1991 return 0;
1992 }
1993
1994 oi = ospf_apiserver_if_lookup_by_ifp(ifp);
1995
1996 if (!oi) {
1997 /* This interface is known to Zebra but not to OSPF daemon yet.
1998 */
1999 zlog_warn(
2000 "ospf_apiserver_new_if: interface %s not known to OSPFd?",
2001 ifp->name);
2002 return 0;
2003 }
2004
2005 assert(oi);
2006
2007 /* New interface added to OSPF, tell clients about it */
2008 if (listcount(apiserver_list) > 0) {
2009 ospf_apiserver_clients_notify_new_if(oi);
2010 }
2011 return 0;
2d33f157 2012}
2013
d62a17ae 2014int ospf_apiserver_del_if(struct interface *ifp)
2d33f157 2015{
d62a17ae 2016 struct ospf_interface *oi;
2017
2018 /* zlog_warn for debugging */
2019 zlog_warn("ospf_apiserver_del_if");
9165c5f5 2020 zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
d62a17ae 2021 ifp->ifindex);
2022
2023 oi = ospf_apiserver_if_lookup_by_ifp(ifp);
2024
2025 if (!oi) {
2026 /* This interface is known to Zebra but not to OSPF daemon
2027 anymore. No need to tell clients about it */
2028 return 0;
2029 }
2030
2031 /* Interface deleted, tell clients about it */
2032 if (listcount(apiserver_list) > 0) {
2033 ospf_apiserver_clients_notify_del_if(oi);
2034 }
2035 return 0;
2d33f157 2036}
2037
d62a17ae 2038void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state)
2d33f157 2039{
d62a17ae 2040 /* Tell clients about interface change */
2d33f157 2041
d62a17ae 2042 /* zlog_warn for debugging */
2043 zlog_warn("ospf_apiserver_ism_change");
2044 if (listcount(apiserver_list) > 0) {
2045 ospf_apiserver_clients_notify_ism_change(oi);
2046 }
2d33f157 2047
d62a17ae 2048 zlog_warn("oi->ifp->name=%s", oi->ifp->name);
2049 zlog_warn("old_state=%d", old_state);
2050 zlog_warn("oi->state=%d", oi->state);
2d33f157 2051}
2052
d62a17ae 2053void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
2d33f157 2054{
d62a17ae 2055 /* Neighbor status changed, tell clients about it */
2056 zlog_warn("ospf_apiserver_nsm_change");
2057 if (listcount(apiserver_list) > 0) {
2058 ospf_apiserver_clients_notify_nsm_change(nbr);
2059 }
2d33f157 2060}
2061
d62a17ae 2062void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa)
2d33f157 2063{
d62a17ae 2064 struct opaque_lsa {
2065 struct lsa_header header;
d7c0a89a 2066 uint8_t data[1]; /* opaque data have variable length. This is
d62a17ae 2067 start
2068 address */
2069 };
2070 struct opaque_lsa *olsa;
2071 int opaquelen;
2072
2073 olsa = (struct opaque_lsa *)lsa->data;
2074
2075 if (VALID_OPAQUE_INFO_LEN(lsa->data))
2076 opaquelen = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2077 else
2078 opaquelen = 0;
2079
2080 /* Output information about opaque LSAs */
2081 if (vty != NULL) {
2082 int i;
2083 vty_out(vty,
2084 " Added using OSPF API: %u octets of opaque data %s\n",
2085 opaquelen,
2086 VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2087 : "(Invalid length?)");
2088 vty_out(vty, " Opaque data: ");
2089
2090 for (i = 0; i < opaquelen; i++) {
2091 vty_out(vty, "0x%x ", olsa->data[i]);
2092 }
2093 vty_out(vty, "\n");
2094 } else {
2095 int i;
2096 zlog_debug(
2097 " Added using OSPF API: %u octets of opaque data %s",
2098 opaquelen,
2099 VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2100 : "(Invalid length?)");
2101 zlog_debug(" Opaque data: ");
2102
2103 for (i = 0; i < opaquelen; i++) {
2104 zlog_debug("0x%x ", olsa->data[i]);
2105 }
d62a17ae 2106 }
2107 return;
2d33f157 2108}
2109
2110/* -----------------------------------------------------------
2111 * Followings are functions to notify clients about events
2112 * -----------------------------------------------------------
2113 */
2114
2115/* Send a message to all clients. This is useful for messages
2116 that need to be notified to all clients (such as interface
2117 changes) */
2118
d62a17ae 2119void ospf_apiserver_clients_notify_all(struct msg *msg)
2d33f157 2120{
d62a17ae 2121 struct listnode *node, *nnode;
2122 struct ospf_apiserver *apiserv;
2d33f157 2123
d62a17ae 2124 /* Send message to all clients */
2125 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv))
2126 ospf_apiserver_send_msg(apiserv, msg);
2d33f157 2127}
2128
2129/* An interface is now ready to accept opaque LSAs. Notify all
2130 clients that registered to use this opaque type */
d62a17ae 2131void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi)
2d33f157 2132{
d62a17ae 2133 struct listnode *node, *nnode;
2134 struct msg *msg;
2135 struct ospf_apiserver *apiserv;
2136
2137 assert(oi);
2138 if (!oi->address) {
2139 zlog_warn("Interface has no address?");
2140 return;
2141 }
2142
2143 if (!ospf_apiserver_is_ready_type9(oi)) {
2144 zlog_warn("Interface not ready for type 9?");
2145 return;
2146 }
2147
2148 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2149 struct listnode *node2, *nnode2;
2150 struct registered_opaque_type *r;
2151
2152 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2153 r)) {
2154 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
2155 msg = new_msg_ready_notify(
2156 0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
2157 oi->address->u.prefix4);
2158 if (!msg) {
2159 zlog_warn(
2160 "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2d33f157 2161#ifdef NOTYET
d62a17ae 2162 /* Cannot allocate new message. What
2163 * should we do? */
2164 ospf_apiserver_free(apiserv);
2d33f157 2165#endif
d62a17ae 2166 goto out;
2167 }
2d33f157 2168
d62a17ae 2169 ospf_apiserver_send_msg(apiserv, msg);
2170 msg_free(msg);
2171 }
2172 }
2d33f157 2173 }
2d33f157 2174
2175out:
d62a17ae 2176 return;
2d33f157 2177}
2178
d62a17ae 2179void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area)
2d33f157 2180{
d62a17ae 2181 struct listnode *node, *nnode;
2182 struct msg *msg;
2183 struct ospf_apiserver *apiserv;
2184
2185 assert(area);
2186
2187 if (!ospf_apiserver_is_ready_type10(area)) {
2188 zlog_warn("Area not ready for type 10?");
2189 return;
2190 }
2191
2192 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2193 struct listnode *node2, *nnode2;
2194 struct registered_opaque_type *r;
2195
2196 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2197 r)) {
2198 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
2199 msg = new_msg_ready_notify(
2200 0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
2201 area->area_id);
2202 if (!msg) {
2203 zlog_warn(
2204 "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2d33f157 2205#ifdef NOTYET
d62a17ae 2206 /* Cannot allocate new message. What
2207 * should we do? */
2208 ospf_apiserver_free(apiserv);
2d33f157 2209#endif
d62a17ae 2210 goto out;
2211 }
2d33f157 2212
d62a17ae 2213 ospf_apiserver_send_msg(apiserv, msg);
2214 msg_free(msg);
2215 }
2216 }
2d33f157 2217 }
2d33f157 2218
2219out:
d62a17ae 2220 return;
2d33f157 2221}
2222
2223
d62a17ae 2224void ospf_apiserver_clients_notify_ready_type11(struct ospf *top)
2d33f157 2225{
d62a17ae 2226 struct listnode *node, *nnode;
2227 struct msg *msg;
2228 struct in_addr id_null = {.s_addr = 0L};
2229 struct ospf_apiserver *apiserv;
2230
2231 assert(top);
2232
2233 if (!ospf_apiserver_is_ready_type11(top)) {
2234 zlog_warn("AS not ready for type 11?");
2235 return;
2236 }
2237
2238 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2239 struct listnode *node2, *nnode2;
2240 struct registered_opaque_type *r;
2241
2242 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2243 r)) {
2244 if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
2245 msg = new_msg_ready_notify(
2246 0, OSPF_OPAQUE_AS_LSA, r->opaque_type,
2247 id_null);
2248 if (!msg) {
2249 zlog_warn(
2250 "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2d33f157 2251#ifdef NOTYET
d62a17ae 2252 /* Cannot allocate new message. What
2253 * should we do? */
2254 ospf_apiserver_free(apiserv);
2d33f157 2255#endif
d62a17ae 2256 goto out;
2257 }
2d33f157 2258
d62a17ae 2259 ospf_apiserver_send_msg(apiserv, msg);
2260 msg_free(msg);
2261 }
2262 }
2d33f157 2263 }
2d33f157 2264
2265out:
d62a17ae 2266 return;
2d33f157 2267}
2268
d62a17ae 2269void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi)
2d33f157 2270{
d62a17ae 2271 struct msg *msg;
2272
2273 msg = new_msg_new_if(0, oi->address->u.prefix4, oi->area->area_id);
2274 if (msg != NULL) {
2275 ospf_apiserver_clients_notify_all(msg);
2276 msg_free(msg);
2277 }
2d33f157 2278}
2279
d62a17ae 2280void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi)
2d33f157 2281{
d62a17ae 2282 struct msg *msg;
2283
2284 msg = new_msg_del_if(0, oi->address->u.prefix4);
2285 if (msg != NULL) {
2286 ospf_apiserver_clients_notify_all(msg);
2287 msg_free(msg);
2288 }
2d33f157 2289}
2290
d62a17ae 2291void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi)
2d33f157 2292{
d62a17ae 2293 struct msg *msg;
2294 struct in_addr ifaddr = {.s_addr = 0L};
2295 struct in_addr area_id = {.s_addr = 0L};
2296
2297 assert(oi);
2298 assert(oi->ifp);
2299
2300 if (oi->address) {
2301 ifaddr = oi->address->u.prefix4;
2302 }
2303 if (oi->area) {
2304 area_id = oi->area->area_id;
2305 }
2306
2307 msg = new_msg_ism_change(0, ifaddr, area_id, oi->state);
2308 if (!msg) {
2309 zlog_warn(
2310 "apiserver_clients_notify_ism_change: msg_new failed");
2311 return;
2312 }
2313
2314 ospf_apiserver_clients_notify_all(msg);
2315 msg_free(msg);
2d33f157 2316}
2317
d62a17ae 2318void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr)
2d33f157 2319{
d62a17ae 2320 struct msg *msg;
9d162466 2321 struct in_addr ifaddr;
7295876a 2322 struct in_addr nbraddr;
2d33f157 2323
d62a17ae 2324 assert(nbr);
2d33f157 2325
45559c4d 2326 ifaddr = nbr->oi->address->u.prefix4;
2d33f157 2327
d62a17ae 2328 nbraddr = nbr->address.u.prefix4;
2d33f157 2329
d62a17ae 2330 msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id,
2331 nbr->state);
2332 if (!msg) {
2333 zlog_warn(
2334 "apiserver_clients_notify_nsm_change: msg_new failed");
2335 return;
2336 }
2d33f157 2337
d62a17ae 2338 ospf_apiserver_clients_notify_all(msg);
2339 msg_free(msg);
2d33f157 2340}
2341
d7c0a89a 2342static void apiserver_clients_lsa_change_notify(uint8_t msgtype,
d62a17ae 2343 struct ospf_lsa *lsa)
2d33f157 2344{
d62a17ae 2345 struct msg *msg;
2346 struct listnode *node, *nnode;
2347 struct ospf_apiserver *apiserv;
2348
2349 /* Default area for AS-External and Opaque11 LSAs */
2350 struct in_addr area_id = {.s_addr = 0L};
2351
2352 /* Default interface for non Opaque9 LSAs */
2353 struct in_addr ifaddr = {.s_addr = 0L};
2354
2355 if (lsa->area) {
2356 area_id = lsa->area->area_id;
2357 }
2358 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2359 assert(lsa->oi);
2360 ifaddr = lsa->oi->address->u.prefix4;
2361 }
2362
2363 /* Prepare message that can be sent to clients that have a matching
2364 filter */
2365 msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2366 ifaddr, area_id,
2367 lsa->flags & OSPF_LSA_SELF, lsa->data);
2368 if (!msg) {
2369 zlog_warn(
2370 "apiserver_clients_lsa_change_notify: msg_new failed");
2371 return;
2372 }
2373
2374 /* Now send message to all clients with a matching filter */
2375 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2376 struct lsa_filter_type *filter;
d7c0a89a
QY
2377 uint16_t mask;
2378 uint32_t *area;
d62a17ae 2379 int i;
2380
2381 /* Check filter for this client. */
2382 filter = apiserv->filter;
2383
2384 /* Check area IDs in case of non AS-E LSAs.
2385 * If filter has areas (num_areas > 0),
2386 * then one of the areas must match the area ID of this LSA. */
2387
2388 i = filter->num_areas;
2389 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA)
2390 || (lsa->data->type == OSPF_OPAQUE_AS_LSA)) {
2391 i = 0;
2d33f157 2392 }
d62a17ae 2393
2394 if (i > 0) {
d7c0a89a 2395 area = (uint32_t *)(filter + 1);
d62a17ae 2396 while (i) {
2397 if (*area == area_id.s_addr) {
2398 break;
2399 }
2400 i--;
2401 area++;
2402 }
2403 } else {
2404 i = 1;
2405 }
2406
2407 if (i > 0) {
2408 /* Area match. Check LSA type. */
2409 mask = ntohs(filter->typemask);
2410
2411 if (mask & Power2[lsa->data->type]) {
2412 /* Type also matches. Check origin. */
2413 if ((filter->origin == ANY_ORIGIN)
2414 || (filter->origin == IS_LSA_SELF(lsa))) {
2415 ospf_apiserver_send_msg(apiserv, msg);
2416 }
2417 }
2d33f157 2418 }
2d33f157 2419 }
d62a17ae 2420 /* Free message since it is not used anymore */
2421 msg_free(msg);
2d33f157 2422}
2423
2424
2425/* -------------------------------------------------------------
2426 * Followings are hooks invoked when LSAs are updated or deleted
2427 * -------------------------------------------------------------
2428 */
2429
2430
d7c0a89a 2431static int apiserver_notify_clients_lsa(uint8_t msgtype, struct ospf_lsa *lsa)
2d33f157 2432{
d62a17ae 2433 struct msg *msg;
2434 /* default area for AS-External and Opaque11 LSAs */
2435 struct in_addr area_id = {.s_addr = 0L};
2436
2437 /* default interface for non Opaque9 LSAs */
2438 struct in_addr ifaddr = {.s_addr = 0L};
2439
2440 /* Only notify this update if the LSA's age is smaller than
2441 MAXAGE. Otherwise clients would see LSA updates with max age just
2442 before they are deleted from the LSDB. LSA delete messages have
2443 MAXAGE too but should not be filtered. */
2444 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2445 return 0;
2446 }
2447
2448 if (lsa->area) {
2449 area_id = lsa->area->area_id;
2450 }
2451 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2452 ifaddr = lsa->oi->address->u.prefix4;
2453 }
2454 msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2455 ifaddr, area_id,
2456 lsa->flags & OSPF_LSA_SELF, lsa->data);
2457 if (!msg) {
2458 zlog_warn("notify_clients_lsa: msg_new failed");
2459 return -1;
2460 }
2461 /* Notify all clients that new LSA is added/updated */
2462 apiserver_clients_lsa_change_notify(msgtype, lsa);
2463
2464 /* Clients made their own copies of msg so we can free msg here */
2465 msg_free(msg);
2466
2467 return 0;
2d33f157 2468}
2469
d62a17ae 2470int ospf_apiserver_lsa_update(struct ospf_lsa *lsa)
2d33f157 2471{
d62a17ae 2472 return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY, lsa);
2d33f157 2473}
2474
d62a17ae 2475int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa)
2d33f157 2476{
d62a17ae 2477 return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY, lsa);
2d33f157 2478}
2479
2480#endif /* SUPPORT_OSPF_API */