]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_apiserver.c
Merge pull request #8106 from donaldsharp/fix_bad_interaction
[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
1160 rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
1161
1162 /* Get request sequence number */
1163 seqnum = msg_get_seq(msg);
1164
1165 /* Free existing filter in apiserv. */
1166 XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
1167 /* Alloc new space for filter. */
1168
1169 apiserv->filter =
1170 XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen));
1171
1172 /* copy it over. */
1173 memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen));
1174 rc = OSPF_API_OK;
1175
1176 /* Send a reply back to client with return code */
1177 rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1178 return rc;
1179 }
1180
1181
1182 /* -----------------------------------------------------------
1183 * Followings are functions for LSDB synchronization.
1184 * -----------------------------------------------------------
1185 */
1186
1187 static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg,
1188 int int_arg)
1189 {
1190 struct ospf_apiserver *apiserv;
1191 int seqnum;
1192 struct msg *msg;
1193 struct param_t {
1194 struct ospf_apiserver *apiserv;
1195 struct lsa_filter_type *filter;
1196 } * param;
1197 int rc = -1;
1198
1199 /* Sanity check */
1200 assert(lsa->data);
1201 assert(p_arg);
1202
1203 param = (struct param_t *)p_arg;
1204 apiserv = param->apiserv;
1205 seqnum = (uint32_t)int_arg;
1206
1207 /* Check origin in filter. */
1208 if ((param->filter->origin == ANY_ORIGIN)
1209 || (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) {
1210
1211 /* Default area for AS-External and Opaque11 LSAs */
1212 struct in_addr area_id = {.s_addr = 0L};
1213
1214 /* Default interface for non Opaque9 LSAs */
1215 struct in_addr ifaddr = {.s_addr = 0L};
1216
1217 if (lsa->area) {
1218 area_id = lsa->area->area_id;
1219 }
1220 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
1221 ifaddr = lsa->oi->address->u.prefix4;
1222 }
1223
1224 msg = new_msg_lsa_change_notify(
1225 MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id,
1226 lsa->flags & OSPF_LSA_SELF, lsa->data);
1227 if (!msg) {
1228 zlog_warn(
1229 "apiserver_sync_callback: new_msg_update failed");
1230 #ifdef NOTYET
1231 /* Cannot allocate new message. What should we do? */
1232 /* ospf_apiserver_free (apiserv);*/ /* Do nothing
1233 here XXX
1234 */
1235 #endif
1236 goto out;
1237 }
1238
1239 /* Send LSA */
1240 ospf_apiserver_send_msg(apiserv, msg);
1241 msg_free(msg);
1242 }
1243 rc = 0;
1244
1245 out:
1246 return rc;
1247 }
1248
1249 int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
1250 struct msg *msg)
1251 {
1252 struct listnode *node, *nnode;
1253 uint32_t seqnum;
1254 int rc = 0;
1255 struct msg_sync_lsdb *smsg;
1256 struct ospf_apiserver_param_t {
1257 struct ospf_apiserver *apiserv;
1258 struct lsa_filter_type *filter;
1259 } param;
1260 uint16_t mask;
1261 struct route_node *rn;
1262 struct ospf_lsa *lsa;
1263 struct ospf *ospf;
1264 struct ospf_area *area;
1265
1266 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1267
1268 /* Get request sequence number */
1269 seqnum = msg_get_seq(msg);
1270 /* Set sync msg. */
1271 smsg = (struct msg_sync_lsdb *)STREAM_DATA(msg->s);
1272
1273 /* Set parameter struct. */
1274 param.apiserv = apiserv;
1275 param.filter = &smsg->filter;
1276
1277 /* Remember mask. */
1278 mask = ntohs(smsg->filter.typemask);
1279
1280 /* Iterate over all areas. */
1281 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1282 int i;
1283 uint32_t *area_id = NULL;
1284
1285 /* Compare area_id with area_ids in sync request. */
1286 if ((i = smsg->filter.num_areas) > 0) {
1287 /* Let area_id point to the list of area IDs,
1288 * which is at the end of smsg->filter. */
1289 area_id = (uint32_t *)(&smsg->filter + 1);
1290 while (i) {
1291 if (*area_id == area->area_id.s_addr) {
1292 break;
1293 }
1294 i--;
1295 area_id++;
1296 }
1297 } else {
1298 i = 1;
1299 }
1300
1301 /* If area was found, then i>0 here. */
1302 if (i) {
1303 /* Check msg type. */
1304 if (mask & Power2[OSPF_ROUTER_LSA])
1305 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
1306 apiserver_sync_callback(
1307 lsa, (void *)&param, seqnum);
1308 if (mask & Power2[OSPF_NETWORK_LSA])
1309 LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
1310 apiserver_sync_callback(
1311 lsa, (void *)&param, seqnum);
1312 if (mask & Power2[OSPF_SUMMARY_LSA])
1313 LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
1314 apiserver_sync_callback(
1315 lsa, (void *)&param, seqnum);
1316 if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
1317 LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
1318 apiserver_sync_callback(
1319 lsa, (void *)&param, seqnum);
1320 if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
1321 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
1322 apiserver_sync_callback(
1323 lsa, (void *)&param, seqnum);
1324 if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
1325 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
1326 apiserver_sync_callback(
1327 lsa, (void *)&param, seqnum);
1328 }
1329 }
1330
1331 /* For AS-external LSAs */
1332 if (ospf->lsdb) {
1333 if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
1334 LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
1335 apiserver_sync_callback(lsa, (void *)&param,
1336 seqnum);
1337 }
1338
1339 /* For AS-external opaque LSAs */
1340 if (ospf->lsdb) {
1341 if (mask & Power2[OSPF_OPAQUE_AS_LSA])
1342 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
1343 apiserver_sync_callback(lsa, (void *)&param,
1344 seqnum);
1345 }
1346
1347 /* Send a reply back to client with return code */
1348 rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1349 return rc;
1350 }
1351
1352
1353 /* -----------------------------------------------------------
1354 * Followings are functions to originate or update LSA
1355 * from an application.
1356 * -----------------------------------------------------------
1357 */
1358
1359 /* Create a new internal opaque LSA by taking prototype and filling in
1360 missing fields such as age, sequence number, advertising router,
1361 checksum and so on. The interface parameter is used for type 9
1362 LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1363 nor interface. */
1364
1365 struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
1366 struct ospf_interface *oi,
1367 struct lsa_header *protolsa)
1368 {
1369 struct stream *s;
1370 struct lsa_header *newlsa;
1371 struct ospf_lsa *new = NULL;
1372 uint8_t options = 0x0;
1373 uint16_t length;
1374
1375 struct ospf *ospf;
1376
1377 if (oi && oi->ospf)
1378 ospf = oi->ospf;
1379 else
1380 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1381
1382 assert(ospf);
1383
1384 /* Create a stream for internal opaque LSA */
1385 if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
1386 zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
1387 return NULL;
1388 }
1389
1390 newlsa = (struct lsa_header *)STREAM_DATA(s);
1391
1392 /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1393 have to set options? */
1394
1395 if (area) {
1396 options = LSA_OPTIONS_GET(area);
1397 options |= LSA_OPTIONS_NSSA_GET(area);
1398 }
1399
1400 options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1401
1402 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1403 zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
1404 protolsa->type, &protolsa->id);
1405 }
1406
1407 /* Set opaque-LSA header fields. */
1408 lsa_header_set(s, options, protolsa->type, protolsa->id,
1409 ospf->router_id);
1410
1411 /* Set opaque-LSA body fields. */
1412 stream_put(s, ((uint8_t *)protolsa) + sizeof(struct lsa_header),
1413 ntohs(protolsa->length) - sizeof(struct lsa_header));
1414
1415 /* Determine length of LSA. */
1416 length = stream_get_endp(s);
1417 newlsa->length = htons(length);
1418
1419 /* Create OSPF LSA. */
1420 new = ospf_lsa_new_and_data(length);
1421
1422 new->area = area;
1423 new->oi = oi;
1424 new->vrf_id = ospf->vrf_id;
1425
1426 SET_FLAG(new->flags, OSPF_LSA_SELF);
1427 memcpy(new->data, newlsa, length);
1428 stream_free(s);
1429
1430 return new;
1431 }
1432
1433
1434 int ospf_apiserver_is_ready_type9(struct ospf_interface *oi)
1435 {
1436 /* Type 9 opaque LSA can be originated if there is at least one
1437 active opaque-capable neighbor attached to the outgoing
1438 interface. */
1439
1440 return (ospf_nbr_count_opaque_capable(oi) > 0);
1441 }
1442
1443 int ospf_apiserver_is_ready_type10(struct ospf_area *area)
1444 {
1445 /* Type 10 opaque LSA can be originated if there is at least one
1446 interface belonging to the area that has an active opaque-capable
1447 neighbor. */
1448 struct listnode *node, *nnode;
1449 struct ospf_interface *oi;
1450
1451 for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi))
1452 /* Is there an active neighbor attached to this interface? */
1453 if (ospf_apiserver_is_ready_type9(oi))
1454 return 1;
1455
1456 /* No active neighbor in area */
1457 return 0;
1458 }
1459
1460 int ospf_apiserver_is_ready_type11(struct ospf *ospf)
1461 {
1462 /* Type 11 opaque LSA can be originated if there is at least one
1463 interface
1464 that has an active opaque-capable neighbor. */
1465 struct listnode *node, *nnode;
1466 struct ospf_interface *oi;
1467
1468 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
1469 /* Is there an active neighbor attached to this interface? */
1470 if (ospf_apiserver_is_ready_type9(oi))
1471 return 1;
1472
1473 /* No active neighbor at all */
1474 return 0;
1475 }
1476
1477
1478 int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
1479 struct msg *msg)
1480 {
1481 struct msg_originate_request *omsg;
1482 struct lsa_header *data;
1483 struct ospf_lsa *new;
1484 struct ospf_lsa *old;
1485 struct ospf_area *area = NULL;
1486 struct ospf_interface *oi = NULL;
1487 struct ospf_lsdb *lsdb = NULL;
1488 struct ospf *ospf;
1489 int lsa_type, opaque_type;
1490 int ready = 0;
1491 int rc = 0;
1492
1493 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1494
1495 /* Extract opaque LSA data from message */
1496 omsg = (struct msg_originate_request *)STREAM_DATA(msg->s);
1497 data = &omsg->data;
1498
1499 /* Determine interface for type9 or area for type10 LSAs. */
1500 switch (data->type) {
1501 case OSPF_OPAQUE_LINK_LSA:
1502 oi = ospf_apiserver_if_lookup_by_addr(omsg->ifaddr);
1503 if (!oi) {
1504 zlog_warn("apiserver_originate: unknown interface %pI4",
1505 &omsg->ifaddr);
1506 rc = OSPF_API_NOSUCHINTERFACE;
1507 goto out;
1508 }
1509 area = oi->area;
1510 lsdb = area->lsdb;
1511 break;
1512 case OSPF_OPAQUE_AREA_LSA:
1513 area = ospf_area_lookup_by_area_id(ospf, omsg->area_id);
1514 if (!area) {
1515 zlog_warn("apiserver_originate: unknown area %pI4",
1516 &omsg->area_id);
1517 rc = OSPF_API_NOSUCHAREA;
1518 goto out;
1519 }
1520 lsdb = area->lsdb;
1521 break;
1522 case OSPF_OPAQUE_AS_LSA:
1523 lsdb = ospf->lsdb;
1524 break;
1525 default:
1526 /* We can only handle opaque types here */
1527 zlog_warn(
1528 "apiserver_originate: Cannot originate non-opaque LSA type %d",
1529 data->type);
1530 rc = OSPF_API_ILLEGALLSATYPE;
1531 goto out;
1532 }
1533
1534 /* Check if we registered this opaque type */
1535 lsa_type = data->type;
1536 opaque_type = GET_OPAQUE_TYPE(ntohl(data->id.s_addr));
1537
1538 if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1539 opaque_type)) {
1540 zlog_warn(
1541 "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered",
1542 lsa_type, opaque_type);
1543 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1544 goto out;
1545 }
1546
1547 /* Make sure that the neighbors are ready before we can originate */
1548 switch (data->type) {
1549 case OSPF_OPAQUE_LINK_LSA:
1550 ready = ospf_apiserver_is_ready_type9(oi);
1551 break;
1552 case OSPF_OPAQUE_AREA_LSA:
1553 ready = ospf_apiserver_is_ready_type10(area);
1554 break;
1555 case OSPF_OPAQUE_AS_LSA:
1556 ready = ospf_apiserver_is_ready_type11(ospf);
1557 break;
1558 default:
1559 break;
1560 }
1561
1562 if (!ready) {
1563 zlog_warn("Neighbors not ready to originate type %d",
1564 data->type);
1565 rc = OSPF_API_NOTREADY;
1566 goto out;
1567 }
1568
1569 /* Create OSPF's internal opaque LSA representation */
1570 new = ospf_apiserver_opaque_lsa_new(area, oi, data);
1571 if (!new) {
1572 rc = OSPF_API_NOMEMORY; /* XXX */
1573 goto out;
1574 }
1575
1576 /* Determine if LSA is new or an update for an existing one. */
1577 old = ospf_lsdb_lookup(lsdb, new);
1578
1579 if (!old) {
1580 /* New LSA install in LSDB. */
1581 rc = ospf_apiserver_originate1(new);
1582 } else {
1583 /*
1584 * Keep the new LSA instance in the "waiting place" until the
1585 * next
1586 * refresh timing. If several LSA update requests for the same
1587 * LSID
1588 * have issued by peer, the last one takes effect.
1589 */
1590 new->lsdb = &apiserv->reserve;
1591 ospf_lsdb_add(&apiserv->reserve, new);
1592
1593 /* Kick the scheduler function. */
1594 ospf_opaque_lsa_refresh_schedule(old);
1595 }
1596
1597 out:
1598
1599 /* Send a reply back to client with return code */
1600 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1601 return rc;
1602 }
1603
1604
1605 /* -----------------------------------------------------------
1606 * Flood an LSA within its flooding scope.
1607 * -----------------------------------------------------------
1608 */
1609
1610 /* XXX We can probably use ospf_flood_through instead of this function
1611 but then we need the neighbor parameter. If we set nbr to
1612 NULL then ospf_flood_through crashes due to dereferencing NULL. */
1613
1614 void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa)
1615 {
1616 assert(lsa);
1617
1618 switch (lsa->data->type) {
1619 case OSPF_OPAQUE_LINK_LSA:
1620 /* Increment counters? XXX */
1621
1622 /* Flood LSA through local network. */
1623 ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
1624 break;
1625 case OSPF_OPAQUE_AREA_LSA:
1626 /* Update LSA origination count. */
1627 assert(lsa->area);
1628 lsa->area->ospf->lsa_originate_count++;
1629
1630 /* Flood LSA through area. */
1631 ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
1632 break;
1633 case OSPF_OPAQUE_AS_LSA: {
1634 struct ospf *ospf;
1635
1636 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1637 assert(ospf);
1638
1639 /* Increment counters? XXX */
1640
1641 /* Flood LSA through AS. */
1642 ospf_flood_through_as(ospf, NULL /*nbr */, lsa);
1643 break;
1644 }
1645 }
1646 }
1647
1648 int ospf_apiserver_originate1(struct ospf_lsa *lsa)
1649 {
1650 struct ospf *ospf;
1651
1652 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1653 assert(ospf);
1654
1655 /* Install this LSA into LSDB. */
1656 if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
1657 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1658 "ospf_apiserver_originate1: ospf_lsa_install failed");
1659 return -1;
1660 }
1661
1662 /* Flood LSA within scope */
1663
1664 #ifdef NOTYET
1665 /*
1666 * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1667 * parameter, and thus it does not cause SIGSEGV error.
1668 */
1669 ospf_flood_through(NULL /*nbr */, lsa);
1670 #else /* NOTYET */
1671
1672 ospf_apiserver_flood_opaque_lsa(lsa);
1673 #endif /* NOTYET */
1674
1675 return 0;
1676 }
1677
1678
1679 /* Opaque LSAs of type 9 on a specific interface can now be
1680 originated. Tell clients that registered type 9. */
1681 int ospf_apiserver_lsa9_originator(void *arg)
1682 {
1683 struct ospf_interface *oi;
1684
1685 oi = (struct ospf_interface *)arg;
1686 if (listcount(apiserver_list) > 0) {
1687 ospf_apiserver_clients_notify_ready_type9(oi);
1688 }
1689 return 0;
1690 }
1691
1692 int ospf_apiserver_lsa10_originator(void *arg)
1693 {
1694 struct ospf_area *area;
1695
1696 area = (struct ospf_area *)arg;
1697 if (listcount(apiserver_list) > 0) {
1698 ospf_apiserver_clients_notify_ready_type10(area);
1699 }
1700 return 0;
1701 }
1702
1703 int ospf_apiserver_lsa11_originator(void *arg)
1704 {
1705 struct ospf *ospf;
1706
1707 ospf = (struct ospf *)arg;
1708 if (listcount(apiserver_list) > 0) {
1709 ospf_apiserver_clients_notify_ready_type11(ospf);
1710 }
1711 return 0;
1712 }
1713
1714
1715 /* Periodically refresh opaque LSAs so that they do not expire in
1716 other routers. */
1717 struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
1718 {
1719 struct ospf_apiserver *apiserv;
1720 struct ospf_lsa *new = NULL;
1721 struct ospf *ospf;
1722
1723 assert(lsa);
1724
1725 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1726 assert(ospf);
1727
1728 apiserv = lookup_apiserver_by_lsa(lsa);
1729 if (!apiserv) {
1730 zlog_warn(
1731 "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
1732 dump_lsa_key(lsa));
1733 lsa->data->ls_age =
1734 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1735 goto out;
1736 }
1737
1738 if (IS_LSA_MAXAGE(lsa)) {
1739 ospf_opaque_lsa_flush_schedule(lsa);
1740 goto out;
1741 }
1742
1743 /* Check if updated version of LSA instance has already prepared. */
1744 new = ospf_lsdb_lookup(&apiserv->reserve, lsa);
1745 if (!new) {
1746 /* This is a periodic refresh, driven by core OSPF mechanism. */
1747 new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi,
1748 lsa->data);
1749 if (!new) {
1750 zlog_warn(
1751 "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
1752 goto out;
1753 }
1754 } else {
1755 /* This is a forcible refresh, requested by OSPF-API client. */
1756 ospf_lsdb_delete(&apiserv->reserve, new);
1757 new->lsdb = NULL;
1758 }
1759
1760 /* Increment sequence number */
1761 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1762
1763 /* New LSA is in same area. */
1764 new->area = lsa->area;
1765 SET_FLAG(new->flags, OSPF_LSA_SELF);
1766
1767 /* Install LSA into LSDB. */
1768 if (ospf_lsa_install(ospf, new->oi, new) == NULL) {
1769 flog_warn(
1770 EC_OSPF_LSA_INSTALL_FAILURE,
1771 "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
1772 ospf_lsa_unlock(&new);
1773 goto out;
1774 }
1775
1776 /* Flood updated LSA through interface, area or AS */
1777
1778 #ifdef NOTYET
1779 ospf_flood_through(NULL /*nbr */, new);
1780 #endif /* NOTYET */
1781 ospf_apiserver_flood_opaque_lsa(new);
1782
1783 /* Debug logging. */
1784 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1785 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
1786 new->data->type, &new->data->id);
1787 ospf_lsa_header_dump(new->data);
1788 }
1789
1790 out:
1791 return new;
1792 }
1793
1794
1795 /* -----------------------------------------------------------
1796 * Followings are functions to delete LSAs
1797 * -----------------------------------------------------------
1798 */
1799
1800 int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
1801 struct msg *msg)
1802 {
1803 struct msg_delete_request *dmsg;
1804 struct ospf_lsa *old;
1805 struct ospf_area *area = NULL;
1806 struct in_addr id;
1807 int lsa_type, opaque_type;
1808 int rc = 0;
1809 struct ospf *ospf;
1810
1811 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1812 assert(ospf);
1813
1814 /* Extract opaque LSA from message */
1815 dmsg = (struct msg_delete_request *)STREAM_DATA(msg->s);
1816
1817 /* Lookup area for link-local and area-local opaque LSAs */
1818 switch (dmsg->lsa_type) {
1819 case OSPF_OPAQUE_LINK_LSA:
1820 case OSPF_OPAQUE_AREA_LSA:
1821 area = ospf_area_lookup_by_area_id(ospf, dmsg->area_id);
1822 if (!area) {
1823 zlog_warn("ospf_apiserver_lsa_delete: unknown area %pI4",
1824 &dmsg->area_id);
1825 rc = OSPF_API_NOSUCHAREA;
1826 goto out;
1827 }
1828 break;
1829 case OSPF_OPAQUE_AS_LSA:
1830 /* AS-external opaque LSAs have no designated area */
1831 area = NULL;
1832 break;
1833 default:
1834 zlog_warn(
1835 "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
1836 dmsg->lsa_type);
1837 rc = OSPF_API_ILLEGALLSATYPE;
1838 goto out;
1839 }
1840
1841 /* Check if we registered this opaque type */
1842 lsa_type = dmsg->lsa_type;
1843 opaque_type = dmsg->opaque_type;
1844
1845 if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1846 opaque_type)) {
1847 zlog_warn(
1848 "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
1849 lsa_type, opaque_type);
1850 rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1851 goto out;
1852 }
1853
1854 /* opaque_id is in network byte order */
1855 id.s_addr = htonl(
1856 SET_OPAQUE_LSID(dmsg->opaque_type, ntohl(dmsg->opaque_id)));
1857
1858 /*
1859 * Even if the target LSA has once scheduled to flush, it remains in
1860 * the LSDB until it is finally handled by the maxage remover thread.
1861 * Therefore, the lookup function below may return non-NULL result.
1862 */
1863 old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id);
1864 if (!old) {
1865 zlog_warn(
1866 "ospf_apiserver_lsa_delete: LSA[Type%d:%pI4] not in LSDB",
1867 dmsg->lsa_type, &id);
1868 rc = OSPF_API_NOSUCHLSA;
1869 goto out;
1870 }
1871
1872 /* Schedule flushing of LSA from LSDB */
1873 /* NB: Multiple scheduling will produce a warning message, but harmless.
1874 */
1875 ospf_opaque_lsa_flush_schedule(old);
1876
1877 out:
1878
1879 /* Send reply back to client including return code */
1880 rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1881 return rc;
1882 }
1883
1884 /* Flush self-originated opaque LSA */
1885 static int apiserver_flush_opaque_type_callback(struct ospf_lsa *lsa,
1886 void *p_arg, int int_arg)
1887 {
1888 struct param_t {
1889 struct ospf_apiserver *apiserv;
1890 uint8_t lsa_type;
1891 uint8_t opaque_type;
1892 } * param;
1893
1894 /* Sanity check */
1895 assert(lsa->data);
1896 assert(p_arg);
1897 param = (struct param_t *)p_arg;
1898
1899 /* If LSA matches type and opaque type then delete it */
1900 if (IS_LSA_SELF(lsa) && lsa->data->type == param->lsa_type
1901 && GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1902 == param->opaque_type) {
1903 ospf_opaque_lsa_flush_schedule(lsa);
1904 }
1905 return 0;
1906 }
1907
1908 /* Delete self-originated opaque LSAs of a given opaque type. This
1909 function is called when an application unregisters a given opaque
1910 type or a connection to an application closes and all those opaque
1911 LSAs need to be flushed the LSDB. */
1912 void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
1913 uint8_t lsa_type, uint8_t opaque_type)
1914 {
1915 struct param_t {
1916 struct ospf_apiserver *apiserv;
1917 uint8_t lsa_type;
1918 uint8_t opaque_type;
1919 } param;
1920 struct listnode *node, *nnode;
1921 struct ospf *ospf;
1922 struct ospf_area *area;
1923
1924 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1925 assert(ospf);
1926
1927 /* Set parameter struct. */
1928 param.apiserv = apiserv;
1929 param.lsa_type = lsa_type;
1930 param.opaque_type = opaque_type;
1931
1932 switch (lsa_type) {
1933 struct route_node *rn;
1934 struct ospf_lsa *lsa;
1935
1936 case OSPF_OPAQUE_LINK_LSA:
1937 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
1938 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
1939 apiserver_flush_opaque_type_callback(
1940 lsa, (void *)&param, 0);
1941 break;
1942 case OSPF_OPAQUE_AREA_LSA:
1943 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
1944 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
1945 apiserver_flush_opaque_type_callback(
1946 lsa, (void *)&param, 0);
1947 break;
1948 case OSPF_OPAQUE_AS_LSA:
1949 LSDB_LOOP (OPAQUE_LINK_LSDB(ospf), rn, lsa)
1950 apiserver_flush_opaque_type_callback(lsa,
1951 (void *)&param, 0);
1952 break;
1953 default:
1954 break;
1955 }
1956 return;
1957 }
1958
1959
1960 /* -----------------------------------------------------------
1961 * Followings are callback functions to handle opaque types
1962 * -----------------------------------------------------------
1963 */
1964
1965 int ospf_apiserver_new_if(struct interface *ifp)
1966 {
1967 struct ospf_interface *oi;
1968
1969 /* For some strange reason it seems possible that we are invoked
1970 with an interface that has no name. This seems to happen during
1971 initialization. Return if this happens */
1972
1973 if (ifp->name[0] == '\0') {
1974 /* interface has empty name */
1975 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1976 return 0;
1977 }
1978
1979 /* zlog_warn for debugging */
1980 zlog_warn("ospf_apiserver_new_if");
1981 zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
1982 ifp->ifindex);
1983
1984 if (ifp->name[0] == '\0') {
1985 /* interface has empty name */
1986 zlog_warn("ospf_apiserver_new_if: interface has no name?");
1987 return 0;
1988 }
1989
1990 oi = ospf_apiserver_if_lookup_by_ifp(ifp);
1991
1992 if (!oi) {
1993 /* This interface is known to Zebra but not to OSPF daemon yet.
1994 */
1995 zlog_warn(
1996 "ospf_apiserver_new_if: interface %s not known to OSPFd?",
1997 ifp->name);
1998 return 0;
1999 }
2000
2001 assert(oi);
2002
2003 /* New interface added to OSPF, tell clients about it */
2004 if (listcount(apiserver_list) > 0) {
2005 ospf_apiserver_clients_notify_new_if(oi);
2006 }
2007 return 0;
2008 }
2009
2010 int ospf_apiserver_del_if(struct interface *ifp)
2011 {
2012 struct ospf_interface *oi;
2013
2014 /* zlog_warn for debugging */
2015 zlog_warn("ospf_apiserver_del_if");
2016 zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2017 ifp->ifindex);
2018
2019 oi = ospf_apiserver_if_lookup_by_ifp(ifp);
2020
2021 if (!oi) {
2022 /* This interface is known to Zebra but not to OSPF daemon
2023 anymore. No need to tell clients about it */
2024 return 0;
2025 }
2026
2027 /* Interface deleted, tell clients about it */
2028 if (listcount(apiserver_list) > 0) {
2029 ospf_apiserver_clients_notify_del_if(oi);
2030 }
2031 return 0;
2032 }
2033
2034 void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state)
2035 {
2036 /* Tell clients about interface change */
2037
2038 /* zlog_warn for debugging */
2039 zlog_warn("ospf_apiserver_ism_change");
2040 if (listcount(apiserver_list) > 0) {
2041 ospf_apiserver_clients_notify_ism_change(oi);
2042 }
2043
2044 zlog_warn("oi->ifp->name=%s", oi->ifp->name);
2045 zlog_warn("old_state=%d", old_state);
2046 zlog_warn("oi->state=%d", oi->state);
2047 }
2048
2049 void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
2050 {
2051 /* Neighbor status changed, tell clients about it */
2052 zlog_warn("ospf_apiserver_nsm_change");
2053 if (listcount(apiserver_list) > 0) {
2054 ospf_apiserver_clients_notify_nsm_change(nbr);
2055 }
2056 }
2057
2058 void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa)
2059 {
2060 struct opaque_lsa {
2061 struct lsa_header header;
2062 uint8_t data[1]; /* opaque data have variable length. This is
2063 start
2064 address */
2065 };
2066 struct opaque_lsa *olsa;
2067 int opaquelen;
2068
2069 olsa = (struct opaque_lsa *)lsa->data;
2070
2071 if (VALID_OPAQUE_INFO_LEN(lsa->data))
2072 opaquelen = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2073 else
2074 opaquelen = 0;
2075
2076 /* Output information about opaque LSAs */
2077 if (vty != NULL) {
2078 int i;
2079 vty_out(vty,
2080 " Added using OSPF API: %u octets of opaque data %s\n",
2081 opaquelen,
2082 VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2083 : "(Invalid length?)");
2084 vty_out(vty, " Opaque data: ");
2085
2086 for (i = 0; i < opaquelen; i++) {
2087 vty_out(vty, "0x%x ", olsa->data[i]);
2088 }
2089 vty_out(vty, "\n");
2090 } else {
2091 int i;
2092 zlog_debug(
2093 " Added using OSPF API: %u octets of opaque data %s",
2094 opaquelen,
2095 VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2096 : "(Invalid length?)");
2097 zlog_debug(" Opaque data: ");
2098
2099 for (i = 0; i < opaquelen; i++) {
2100 zlog_debug("0x%x ", olsa->data[i]);
2101 }
2102 }
2103 return;
2104 }
2105
2106 /* -----------------------------------------------------------
2107 * Followings are functions to notify clients about events
2108 * -----------------------------------------------------------
2109 */
2110
2111 /* Send a message to all clients. This is useful for messages
2112 that need to be notified to all clients (such as interface
2113 changes) */
2114
2115 void ospf_apiserver_clients_notify_all(struct msg *msg)
2116 {
2117 struct listnode *node, *nnode;
2118 struct ospf_apiserver *apiserv;
2119
2120 /* Send message to all clients */
2121 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv))
2122 ospf_apiserver_send_msg(apiserv, msg);
2123 }
2124
2125 /* An interface is now ready to accept opaque LSAs. Notify all
2126 clients that registered to use this opaque type */
2127 void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi)
2128 {
2129 struct listnode *node, *nnode;
2130 struct msg *msg;
2131 struct ospf_apiserver *apiserv;
2132
2133 assert(oi);
2134 if (!oi->address) {
2135 zlog_warn("Interface has no address?");
2136 return;
2137 }
2138
2139 if (!ospf_apiserver_is_ready_type9(oi)) {
2140 zlog_warn("Interface not ready for type 9?");
2141 return;
2142 }
2143
2144 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2145 struct listnode *node2, *nnode2;
2146 struct registered_opaque_type *r;
2147
2148 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2149 r)) {
2150 if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
2151 msg = new_msg_ready_notify(
2152 0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
2153 oi->address->u.prefix4);
2154 if (!msg) {
2155 zlog_warn(
2156 "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
2157 #ifdef NOTYET
2158 /* Cannot allocate new message. What
2159 * should we do? */
2160 ospf_apiserver_free(apiserv);
2161 #endif
2162 goto out;
2163 }
2164
2165 ospf_apiserver_send_msg(apiserv, msg);
2166 msg_free(msg);
2167 }
2168 }
2169 }
2170
2171 out:
2172 return;
2173 }
2174
2175 void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area)
2176 {
2177 struct listnode *node, *nnode;
2178 struct msg *msg;
2179 struct ospf_apiserver *apiserv;
2180
2181 assert(area);
2182
2183 if (!ospf_apiserver_is_ready_type10(area)) {
2184 zlog_warn("Area not ready for type 10?");
2185 return;
2186 }
2187
2188 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2189 struct listnode *node2, *nnode2;
2190 struct registered_opaque_type *r;
2191
2192 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2193 r)) {
2194 if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
2195 msg = new_msg_ready_notify(
2196 0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
2197 area->area_id);
2198 if (!msg) {
2199 zlog_warn(
2200 "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
2201 #ifdef NOTYET
2202 /* Cannot allocate new message. What
2203 * should we do? */
2204 ospf_apiserver_free(apiserv);
2205 #endif
2206 goto out;
2207 }
2208
2209 ospf_apiserver_send_msg(apiserv, msg);
2210 msg_free(msg);
2211 }
2212 }
2213 }
2214
2215 out:
2216 return;
2217 }
2218
2219
2220 void ospf_apiserver_clients_notify_ready_type11(struct ospf *top)
2221 {
2222 struct listnode *node, *nnode;
2223 struct msg *msg;
2224 struct in_addr id_null = {.s_addr = 0L};
2225 struct ospf_apiserver *apiserv;
2226
2227 assert(top);
2228
2229 if (!ospf_apiserver_is_ready_type11(top)) {
2230 zlog_warn("AS not ready for type 11?");
2231 return;
2232 }
2233
2234 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2235 struct listnode *node2, *nnode2;
2236 struct registered_opaque_type *r;
2237
2238 for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2239 r)) {
2240 if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
2241 msg = new_msg_ready_notify(
2242 0, OSPF_OPAQUE_AS_LSA, r->opaque_type,
2243 id_null);
2244 if (!msg) {
2245 zlog_warn(
2246 "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
2247 #ifdef NOTYET
2248 /* Cannot allocate new message. What
2249 * should we do? */
2250 ospf_apiserver_free(apiserv);
2251 #endif
2252 goto out;
2253 }
2254
2255 ospf_apiserver_send_msg(apiserv, msg);
2256 msg_free(msg);
2257 }
2258 }
2259 }
2260
2261 out:
2262 return;
2263 }
2264
2265 void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi)
2266 {
2267 struct msg *msg;
2268
2269 msg = new_msg_new_if(0, oi->address->u.prefix4, oi->area->area_id);
2270 if (msg != NULL) {
2271 ospf_apiserver_clients_notify_all(msg);
2272 msg_free(msg);
2273 }
2274 }
2275
2276 void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi)
2277 {
2278 struct msg *msg;
2279
2280 msg = new_msg_del_if(0, oi->address->u.prefix4);
2281 if (msg != NULL) {
2282 ospf_apiserver_clients_notify_all(msg);
2283 msg_free(msg);
2284 }
2285 }
2286
2287 void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi)
2288 {
2289 struct msg *msg;
2290 struct in_addr ifaddr = {.s_addr = 0L};
2291 struct in_addr area_id = {.s_addr = 0L};
2292
2293 assert(oi);
2294 assert(oi->ifp);
2295
2296 if (oi->address) {
2297 ifaddr = oi->address->u.prefix4;
2298 }
2299 if (oi->area) {
2300 area_id = oi->area->area_id;
2301 }
2302
2303 msg = new_msg_ism_change(0, ifaddr, area_id, oi->state);
2304 if (!msg) {
2305 zlog_warn(
2306 "apiserver_clients_notify_ism_change: msg_new failed");
2307 return;
2308 }
2309
2310 ospf_apiserver_clients_notify_all(msg);
2311 msg_free(msg);
2312 }
2313
2314 void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr)
2315 {
2316 struct msg *msg;
2317 struct in_addr ifaddr;
2318 struct in_addr nbraddr;
2319
2320 assert(nbr);
2321
2322 ifaddr = nbr->oi->address->u.prefix4;
2323
2324 nbraddr = nbr->address.u.prefix4;
2325
2326 msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id,
2327 nbr->state);
2328 if (!msg) {
2329 zlog_warn(
2330 "apiserver_clients_notify_nsm_change: msg_new failed");
2331 return;
2332 }
2333
2334 ospf_apiserver_clients_notify_all(msg);
2335 msg_free(msg);
2336 }
2337
2338 static void apiserver_clients_lsa_change_notify(uint8_t msgtype,
2339 struct ospf_lsa *lsa)
2340 {
2341 struct msg *msg;
2342 struct listnode *node, *nnode;
2343 struct ospf_apiserver *apiserv;
2344
2345 /* Default area for AS-External and Opaque11 LSAs */
2346 struct in_addr area_id = {.s_addr = 0L};
2347
2348 /* Default interface for non Opaque9 LSAs */
2349 struct in_addr ifaddr = {.s_addr = 0L};
2350
2351 if (lsa->area) {
2352 area_id = lsa->area->area_id;
2353 }
2354 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2355 assert(lsa->oi);
2356 ifaddr = lsa->oi->address->u.prefix4;
2357 }
2358
2359 /* Prepare message that can be sent to clients that have a matching
2360 filter */
2361 msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2362 ifaddr, area_id,
2363 lsa->flags & OSPF_LSA_SELF, lsa->data);
2364 if (!msg) {
2365 zlog_warn(
2366 "apiserver_clients_lsa_change_notify: msg_new failed");
2367 return;
2368 }
2369
2370 /* Now send message to all clients with a matching filter */
2371 for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2372 struct lsa_filter_type *filter;
2373 uint16_t mask;
2374 uint32_t *area;
2375 int i;
2376
2377 /* Check filter for this client. */
2378 filter = apiserv->filter;
2379
2380 /* Check area IDs in case of non AS-E LSAs.
2381 * If filter has areas (num_areas > 0),
2382 * then one of the areas must match the area ID of this LSA. */
2383
2384 i = filter->num_areas;
2385 if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA)
2386 || (lsa->data->type == OSPF_OPAQUE_AS_LSA)) {
2387 i = 0;
2388 }
2389
2390 if (i > 0) {
2391 area = (uint32_t *)(filter + 1);
2392 while (i) {
2393 if (*area == area_id.s_addr) {
2394 break;
2395 }
2396 i--;
2397 area++;
2398 }
2399 } else {
2400 i = 1;
2401 }
2402
2403 if (i > 0) {
2404 /* Area match. Check LSA type. */
2405 mask = ntohs(filter->typemask);
2406
2407 if (mask & Power2[lsa->data->type]) {
2408 /* Type also matches. Check origin. */
2409 if ((filter->origin == ANY_ORIGIN)
2410 || (filter->origin == IS_LSA_SELF(lsa))) {
2411 ospf_apiserver_send_msg(apiserv, msg);
2412 }
2413 }
2414 }
2415 }
2416 /* Free message since it is not used anymore */
2417 msg_free(msg);
2418 }
2419
2420
2421 /* -------------------------------------------------------------
2422 * Followings are hooks invoked when LSAs are updated or deleted
2423 * -------------------------------------------------------------
2424 */
2425
2426
2427 static int apiserver_notify_clients_lsa(uint8_t msgtype, struct ospf_lsa *lsa)
2428 {
2429 struct msg *msg;
2430 /* default area for AS-External and Opaque11 LSAs */
2431 struct in_addr area_id = {.s_addr = 0L};
2432
2433 /* default interface for non Opaque9 LSAs */
2434 struct in_addr ifaddr = {.s_addr = 0L};
2435
2436 /* Only notify this update if the LSA's age is smaller than
2437 MAXAGE. Otherwise clients would see LSA updates with max age just
2438 before they are deleted from the LSDB. LSA delete messages have
2439 MAXAGE too but should not be filtered. */
2440 if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
2441 return 0;
2442 }
2443
2444 if (lsa->area) {
2445 area_id = lsa->area->area_id;
2446 }
2447 if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2448 ifaddr = lsa->oi->address->u.prefix4;
2449 }
2450 msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2451 ifaddr, area_id,
2452 lsa->flags & OSPF_LSA_SELF, lsa->data);
2453 if (!msg) {
2454 zlog_warn("notify_clients_lsa: msg_new failed");
2455 return -1;
2456 }
2457 /* Notify all clients that new LSA is added/updated */
2458 apiserver_clients_lsa_change_notify(msgtype, lsa);
2459
2460 /* Clients made their own copies of msg so we can free msg here */
2461 msg_free(msg);
2462
2463 return 0;
2464 }
2465
2466 int ospf_apiserver_lsa_update(struct ospf_lsa *lsa)
2467 {
2468 return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY, lsa);
2469 }
2470
2471 int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa)
2472 {
2473 return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY, lsa);
2474 }
2475
2476 #endif /* SUPPORT_OSPF_API */