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