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