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