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