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