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