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