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