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