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