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