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