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