]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babeld.c
Merge pull request #13350 from opensourcerouting/typesafe-fixes-20230421
[mirror_frr.git] / babeld / babeld.c
1 // SPDX-License-Identifier: MIT
2 /*
3 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
4 */
5
6 #include <zebra.h>
7 #include "command.h"
8 #include "prefix.h"
9 #include "memory.h"
10 #include "table.h"
11 #include "distribute.h"
12 #include "prefix.h"
13 #include "filter.h"
14 #include "plist.h"
15 #include "lib_errors.h"
16 #include "network.h"
17 #include "if.h"
18
19 #include "babel_main.h"
20 #include "babeld.h"
21 #include "util.h"
22 #include "net.h"
23 #include "kernel.h"
24 #include "babel_interface.h"
25 #include "neighbour.h"
26 #include "route.h"
27 #include "message.h"
28 #include "resend.h"
29 #include "babel_filter.h"
30 #include "babel_zebra.h"
31 #include "babel_errors.h"
32
33 #ifndef VTYSH_EXTRACT_PL
34 #include "babeld/babeld_clippy.c"
35 #endif
36
37 DEFINE_MGROUP(BABELD, "babeld");
38 DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure");
39
40 static void babel_init_routing_process(struct event *thread);
41 static void babel_get_myid(void);
42 static void babel_initial_noise(void);
43 static void babel_read_protocol(struct event *thread);
44 static void babel_main_loop(struct event *thread);
45 static void babel_set_timer(struct timeval *timeout);
46 static void babel_fill_with_next_timeout(struct timeval *tv);
47 static void
48 babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist);
49
50 /* Informations relative to the babel running daemon. */
51 static struct babel *babel_routing_process = NULL;
52 static unsigned char *receive_buffer = NULL;
53 static int receive_buffer_size = 0;
54
55 /* timeouts */
56 struct timeval check_neighbours_timeout;
57 static time_t expiry_time;
58 static time_t source_expiry_time;
59
60 /* Babel node structure. */
61 static int babel_config_write (struct vty *vty);
62 static struct cmd_node cmd_babel_node =
63 {
64 .name = "babel",
65 .node = BABEL_NODE,
66 .parent_node = CONFIG_NODE,
67 .prompt = "%s(config-router)# ",
68 .config_write = babel_config_write,
69 };
70
71 /* print current babel configuration on vty */
72 static int
73 babel_config_write (struct vty *vty)
74 {
75 int lines = 0;
76 int afi;
77 int i;
78
79 /* list enabled debug modes */
80 lines += debug_babel_config_write (vty);
81
82 if (!babel_routing_process)
83 return lines;
84 vty_out (vty, "router babel\n");
85 if (diversity_kind != DIVERSITY_NONE)
86 {
87 vty_out (vty, " babel diversity\n");
88 lines++;
89 }
90 if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
91 {
92 vty_out (vty, " babel diversity-factor %d\n",diversity_factor);
93 lines++;
94 }
95 if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
96 {
97 vty_out (vty, " babel resend-delay %u\n", resend_delay);
98 lines++;
99 }
100 if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
101 {
102 vty_out (vty, " babel smoothing-half-life %u\n",
103 smoothing_half_life);
104 lines++;
105 }
106 /* list enabled interfaces */
107 lines = 1 + babel_enable_if_config_write (vty);
108 /* list redistributed protocols */
109 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
110 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
111 if (i != zclient->redist_default &&
112 vrf_bitmap_check (zclient->redist[afi][i], VRF_DEFAULT)) {
113 vty_out (vty, " redistribute %s %s\n",
114 (afi == AFI_IP) ? "ipv4" : "ipv6",
115 zebra_route_string(i));
116 lines++;
117 }
118 }
119 }
120
121 lines += config_write_distribute (vty, babel_routing_process->distribute_ctx);
122
123 vty_out (vty, "exit\n");
124
125 return lines;
126 }
127
128
129 static int
130 babel_create_routing_process (void)
131 {
132 assert (babel_routing_process == NULL);
133
134 /* Allocaste Babel instance. */
135 babel_routing_process = XCALLOC(MTYPE_BABEL, sizeof(struct babel));
136
137 /* Initialize timeouts */
138 gettime(&babel_now);
139 expiry_time = babel_now.tv_sec + roughly(30);
140 source_expiry_time = babel_now.tv_sec + roughly(300);
141
142 /* Make socket for Babel protocol. */
143 protocol_socket = babel_socket(protocol_port);
144 if (protocol_socket < 0) {
145 flog_err_sys(EC_LIB_SOCKET, "Couldn't create link local socket: %s",
146 safe_strerror(errno));
147 goto fail;
148 }
149
150 /* Threads. */
151 event_add_read(master, babel_read_protocol, NULL, protocol_socket,
152 &babel_routing_process->t_read);
153 /* wait a little: zebra will announce interfaces, addresses, routes... */
154 event_add_timer_msec(master, babel_init_routing_process, NULL, 200L,
155 &babel_routing_process->t_update);
156
157 /* Distribute list install. */
158 babel_routing_process->distribute_ctx = distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT));
159 distribute_list_add_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
160 distribute_list_delete_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
161 return 0;
162 fail:
163 XFREE(MTYPE_BABEL, babel_routing_process);
164 return -1;
165 }
166
167 /* thread reading entries form others babel daemons */
168 static void babel_read_protocol(struct event *thread)
169 {
170 int rc;
171 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
172 struct interface *ifp = NULL;
173 struct sockaddr_in6 sin6;
174
175 assert(babel_routing_process != NULL);
176 assert(protocol_socket >= 0);
177
178 rc = babel_recv(protocol_socket,
179 receive_buffer, receive_buffer_size,
180 (struct sockaddr*)&sin6, sizeof(sin6));
181 if(rc < 0) {
182 if(errno != EAGAIN && errno != EINTR) {
183 flog_err_sys(EC_LIB_SOCKET, "recv: %s", safe_strerror(errno));
184 }
185 } else {
186 FOR_ALL_INTERFACES(vrf, ifp) {
187 if(!if_up(ifp))
188 continue;
189 if(ifp->ifindex == (ifindex_t)sin6.sin6_scope_id) {
190 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
191 receive_buffer, rc);
192 break;
193 }
194 }
195 }
196
197 /* re-add thread */
198 event_add_read(master, &babel_read_protocol, NULL, protocol_socket,
199 &babel_routing_process->t_read);
200 }
201
202 /* Zebra will give some information, especially about interfaces. This function
203 must be call with a litte timeout wich may give zebra the time to do his job,
204 making these inits have sense. */
205 static void babel_init_routing_process(struct event *thread)
206 {
207 myseqno = (frr_weak_random() & 0xFFFF);
208 babel_get_myid();
209 babel_load_state_file();
210 debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
211 babel_initial_noise();
212 babel_main_loop(thread);/* this function self-add to the t_update thread */
213 }
214
215 /* fill "myid" with an unique id (only if myid != {0}). */
216 static void
217 babel_get_myid(void)
218 {
219 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
220 struct interface *ifp = NULL;
221 int rc;
222 int i;
223
224 /* if we already have an id (from state file), we return. */
225 if (memcmp(myid, zeroes, 8) != 0) {
226 return;
227 }
228
229 FOR_ALL_INTERFACES(vrf, ifp) {
230 /* ifp->ifindex is not necessarily valid at this point */
231 int ifindex = if_nametoindex(ifp->name);
232 if(ifindex > 0) {
233 unsigned char eui[8];
234 rc = if_eui64(ifindex, eui);
235 if(rc < 0)
236 continue;
237 memcpy(myid, eui, 8);
238 return;
239 }
240 }
241
242 /* We failed to get a global EUI64 from the interfaces we were given.
243 Let's try to find an interface with a MAC address. */
244 for(i = 1; i < 256; i++) {
245 char buf[INTERFACE_NAMSIZ], *ifname;
246 unsigned char eui[8];
247 ifname = if_indextoname(i, buf);
248 if(ifname == NULL)
249 continue;
250 rc = if_eui64(i, eui);
251 if(rc < 0)
252 continue;
253 memcpy(myid, eui, 8);
254 return;
255 }
256
257 flog_err(EC_BABEL_CONFIG, "Couldn't find router id -- using random value.");
258
259 rc = read_random_bytes(myid, 8);
260 if(rc < 0) {
261 flog_err(EC_BABEL_CONFIG, "read(random): %s (cannot assign an ID)",
262 safe_strerror(errno));
263 exit(1);
264 }
265 /* Clear group and global bits */
266 UNSET_FLAG (myid[0], 3);
267 }
268
269 /* Make some noise so that others notice us, and send retractions in
270 case we were restarted recently */
271 static void
272 babel_initial_noise(void)
273 {
274 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
275 struct interface *ifp = NULL;
276
277 FOR_ALL_INTERFACES(vrf, ifp) {
278 if(!if_up(ifp))
279 continue;
280 /* Apply jitter before we send the first message. */
281 usleep(roughly(10000));
282 gettime(&babel_now);
283 send_hello(ifp);
284 send_wildcard_retraction(ifp);
285 }
286
287 FOR_ALL_INTERFACES(vrf, ifp) {
288 if(!if_up(ifp))
289 continue;
290 usleep(roughly(10000));
291 gettime(&babel_now);
292 send_hello(ifp);
293 send_wildcard_retraction(ifp);
294 send_self_update(ifp);
295 send_request(ifp, NULL, 0);
296 flushupdates(ifp);
297 flushbuf(ifp);
298 }
299 }
300
301 /* Delete all the added babel routes, make babeld only speak to zebra. */
302 static void
303 babel_clean_routing_process(void)
304 {
305 flush_all_routes();
306 babel_interface_close_all();
307
308 /* cancel events */
309 event_cancel(&babel_routing_process->t_read);
310 event_cancel(&babel_routing_process->t_update);
311
312 distribute_list_delete(&babel_routing_process->distribute_ctx);
313 XFREE(MTYPE_BABEL, babel_routing_process);
314 }
315
316 /* Function used with timeout. */
317 static void babel_main_loop(struct event *thread)
318 {
319 struct timeval tv;
320 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
321 struct interface *ifp = NULL;
322
323 while(1) {
324 gettime(&babel_now);
325
326 /* timeouts --------------------------------------------------------- */
327 /* get the next timeout */
328 babel_fill_with_next_timeout(&tv);
329 /* if there is no timeout, we must wait. */
330 if(timeval_compare(&tv, &babel_now) > 0) {
331 timeval_minus(&tv, &tv, &babel_now);
332 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
333 (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
334 /* it happens often to have less than 1 ms, it's bad. */
335 timeval_add_msec(&tv, &tv, 300);
336 babel_set_timer(&tv);
337 return;
338 }
339
340 gettime(&babel_now);
341
342 /* update database -------------------------------------------------- */
343 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
344 int msecs;
345 msecs = check_neighbours();
346 /* Multiply by 3/2 to allow neighbours to expire. */
347 msecs = MAX(3 * msecs / 2, 10);
348 schedule_neighbours_check(msecs, 1);
349 }
350
351 if(babel_now.tv_sec >= expiry_time) {
352 expire_routes();
353 expire_resend();
354 expiry_time = babel_now.tv_sec + roughly(30);
355 }
356
357 if(babel_now.tv_sec >= source_expiry_time) {
358 expire_sources();
359 source_expiry_time = babel_now.tv_sec + roughly(300);
360 }
361
362 FOR_ALL_INTERFACES(vrf, ifp) {
363 babel_interface_nfo *babel_ifp = NULL;
364 if(!if_up(ifp))
365 continue;
366 babel_ifp = babel_get_if_nfo(ifp);
367 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
368 send_hello(ifp);
369 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
370 send_update(ifp, 0, NULL, 0);
371 if(timeval_compare(&babel_now,
372 &babel_ifp->update_flush_timeout) >= 0)
373 flushupdates(ifp);
374 }
375
376 if(resend_time.tv_sec != 0) {
377 if(timeval_compare(&babel_now, &resend_time) >= 0)
378 do_resend();
379 }
380
381 if(unicast_flush_timeout.tv_sec != 0) {
382 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
383 flush_unicast(1);
384 }
385
386 FOR_ALL_INTERFACES(vrf, ifp) {
387 babel_interface_nfo *babel_ifp = NULL;
388 if(!if_up(ifp))
389 continue;
390 babel_ifp = babel_get_if_nfo(ifp);
391 if(babel_ifp->flush_timeout.tv_sec != 0) {
392 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
393 flushbuf(ifp);
394 }
395 }
396 }
397
398 assert(0); /* this line should never be reach */
399 }
400
401 static void
402 printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
403 {
404 static struct timeval curr_tv;
405 static char buffer[200];
406 static const char *curr_tag = NULL;
407
408 switch (cmd) {
409 case 0: /* reset timeval */
410 curr_tv = *tv;
411 if(ifname != NULL) {
412 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
413 curr_tag = buffer;
414 } else {
415 curr_tag = tag;
416 }
417 break;
418 case 1: /* take the min */
419 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
420 break;
421 }
422 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
423 tv->tv_usec < curr_tv.tv_usec)) {
424 curr_tv = *tv;
425 if(ifname != NULL) {
426 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
427 curr_tag = buffer;
428 } else {
429 curr_tag = tag;
430 }
431 }
432 break;
433 case 2: /* print message */
434 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
435 break;
436 default:
437 break;
438 }
439 }
440
441 static void
442 babel_fill_with_next_timeout(struct timeval *tv)
443 {
444 #if (defined NO_DEBUG)
445 #define printIfMin(a,b,c,d)
446 #else
447 #define printIfMin(a, b, c, d) \
448 if (unlikely(debug & BABEL_DEBUG_TIMEOUT)) { \
449 printIfMin(a, b, c, d); \
450 }
451
452 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
453 struct interface *ifp = NULL;
454
455 *tv = check_neighbours_timeout;
456 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
457 timeval_min_sec(tv, expiry_time);
458 printIfMin(tv, 1, "expiry_time", NULL);
459 timeval_min_sec(tv, source_expiry_time);
460 printIfMin(tv, 1, "source_expiry_time", NULL);
461 timeval_min(tv, &resend_time);
462 printIfMin(tv, 1, "resend_time", NULL);
463 FOR_ALL_INTERFACES (vrf, ifp) {
464 babel_interface_nfo *babel_ifp = NULL;
465 if (!if_up(ifp))
466 continue;
467 babel_ifp = babel_get_if_nfo(ifp);
468 timeval_min(tv, &babel_ifp->flush_timeout);
469 printIfMin(tv, 1, "flush_timeout", ifp->name);
470 timeval_min(tv, &babel_ifp->hello_timeout);
471 printIfMin(tv, 1, "hello_timeout", ifp->name);
472 timeval_min(tv, &babel_ifp->update_timeout);
473 printIfMin(tv, 1, "update_timeout", ifp->name);
474 timeval_min(tv, &babel_ifp->update_flush_timeout);
475 printIfMin(tv, 1, "update_flush_timeout", ifp->name);
476 }
477 timeval_min(tv, &unicast_flush_timeout);
478 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
479 printIfMin(tv, 2, NULL, NULL);
480 #undef printIfMin
481 #endif
482 }
483
484 /* set the t_update thread of the babel routing process to be launch in
485 'timeout' (approximate at the milisecond) */
486 static void
487 babel_set_timer(struct timeval *timeout)
488 {
489 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
490 event_cancel(&(babel_routing_process->t_update));
491 event_add_timer_msec(master, babel_main_loop, NULL, msecs,
492 &babel_routing_process->t_update);
493 }
494
495 void
496 schedule_neighbours_check(int msecs, int override)
497 {
498 struct timeval timeout;
499
500 timeval_add_msec(&timeout, &babel_now, msecs);
501 if(override)
502 check_neighbours_timeout = timeout;
503 else
504 timeval_min(&check_neighbours_timeout, &timeout);
505 }
506
507 int
508 resize_receive_buffer(int size)
509 {
510 if(size <= receive_buffer_size)
511 return 0;
512
513 if(receive_buffer == NULL) {
514 receive_buffer = malloc(size);
515 if(receive_buffer == NULL) {
516 flog_err(EC_BABEL_MEMORY, "malloc(receive_buffer): %s",
517 safe_strerror(errno));
518 return -1;
519 }
520 receive_buffer_size = size;
521 } else {
522 unsigned char *new;
523 new = realloc(receive_buffer, size);
524 if(new == NULL) {
525 flog_err(EC_BABEL_MEMORY, "realloc(receive_buffer): %s",
526 safe_strerror(errno));
527 return -1;
528 }
529 receive_buffer = new;
530 receive_buffer_size = size;
531 }
532 return 1;
533 }
534
535 static void
536 babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist)
537 {
538 struct interface *ifp;
539 babel_interface_nfo *babel_ifp;
540 int type;
541 int family;
542
543 if (! dist->ifname)
544 return;
545
546 ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
547 if (ifp == NULL)
548 return;
549
550 babel_ifp = babel_get_if_nfo(ifp);
551
552 for (type = 0; type < DISTRIBUTE_MAX; type++) {
553 family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
554 AFI_IP : AFI_IP6;
555 if (dist->list[type])
556 babel_ifp->list[type] = access_list_lookup (family,
557 dist->list[type]);
558 else
559 babel_ifp->list[type] = NULL;
560 if (dist->prefix[type])
561 babel_ifp->prefix[type] = prefix_list_lookup (family,
562 dist->prefix[type]);
563 else
564 babel_ifp->prefix[type] = NULL;
565 }
566 }
567
568 static void
569 babel_distribute_update_interface (struct interface *ifp)
570 {
571 struct distribute *dist = NULL;
572
573 if (babel_routing_process)
574 dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
575 if (dist)
576 babel_distribute_update (babel_routing_process->distribute_ctx, dist);
577 }
578
579 /* Update all interface's distribute list. */
580 static void
581 babel_distribute_update_all (struct prefix_list *notused)
582 {
583 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
584 struct interface *ifp;
585
586 FOR_ALL_INTERFACES (vrf, ifp)
587 babel_distribute_update_interface (ifp);
588 }
589
590 static void
591 babel_distribute_update_all_wrapper (struct access_list *notused)
592 {
593 babel_distribute_update_all(NULL);
594 }
595
596
597 /* [Command] */
598 DEFUN_NOSH (router_babel,
599 router_babel_cmd,
600 "router babel",
601 "Enable a routing process\n"
602 "Make Babel instance command\n")
603 {
604 int ret;
605
606 vty->node = BABEL_NODE;
607
608 if (!babel_routing_process) {
609 ret = babel_create_routing_process ();
610
611 /* Notice to user we couldn't create Babel. */
612 if (ret < 0) {
613 zlog_warn ("can't create Babel");
614 return CMD_WARNING;
615 }
616 }
617
618 return CMD_SUCCESS;
619 }
620
621 /* [Command] */
622 DEFUN (no_router_babel,
623 no_router_babel_cmd,
624 "no router babel",
625 NO_STR
626 "Disable a routing process\n"
627 "Remove Babel instance command\n")
628 {
629 if(babel_routing_process)
630 babel_clean_routing_process();
631 return CMD_SUCCESS;
632 }
633
634 /* [Babel Command] */
635 DEFUN (babel_diversity,
636 babel_diversity_cmd,
637 "babel diversity",
638 "Babel commands\n"
639 "Enable diversity-aware routing.\n")
640 {
641 diversity_kind = DIVERSITY_CHANNEL;
642 return CMD_SUCCESS;
643 }
644
645 /* [Babel Command] */
646 DEFUN (no_babel_diversity,
647 no_babel_diversity_cmd,
648 "no babel diversity",
649 NO_STR
650 "Babel commands\n"
651 "Disable diversity-aware routing.\n")
652 {
653 diversity_kind = DIVERSITY_NONE;
654 return CMD_SUCCESS;
655 }
656
657 /* [Babel Command] */
658 DEFPY (babel_diversity_factor,
659 babel_diversity_factor_cmd,
660 "[no] babel diversity-factor (1-256)$factor",
661 NO_STR
662 "Babel commands\n"
663 "Set the diversity factor.\n"
664 "Factor in units of 1/256.\n")
665 {
666 diversity_factor = no ? BABEL_DEFAULT_DIVERSITY_FACTOR : factor;
667 return CMD_SUCCESS;
668 }
669
670 /* [Babel Command] */
671 DEFPY (babel_set_resend_delay,
672 babel_set_resend_delay_cmd,
673 "[no] babel resend-delay (20-655340)$delay",
674 NO_STR
675 "Babel commands\n"
676 "Time before resending a message\n"
677 "Milliseconds\n")
678 {
679 resend_delay = no ? BABEL_DEFAULT_RESEND_DELAY : delay;
680 return CMD_SUCCESS;
681 }
682
683 /* [Babel Command] */
684 DEFPY (babel_set_smoothing_half_life,
685 babel_set_smoothing_half_life_cmd,
686 "[no] babel smoothing-half-life (0-65534)$seconds",
687 NO_STR
688 "Babel commands\n"
689 "Smoothing half-life\n"
690 "Seconds (0 to disable)\n")
691 {
692 change_smoothing_half_life(no ? BABEL_DEFAULT_SMOOTHING_HALF_LIFE
693 : seconds);
694 return CMD_SUCCESS;
695 }
696
697 DEFUN (babel_distribute_list,
698 babel_distribute_list_cmd,
699 "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
700 "Filter networks in routing updates\n"
701 "Specify a prefix\n"
702 "Access-list name\n"
703 "Filter incoming routing updates\n"
704 "Filter outgoing routing updates\n"
705 "Interface name\n")
706 {
707 const char *ifname = NULL;
708 int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
709
710 if (argv[argc - 1]->type == VARIABLE_TKN)
711 ifname = argv[argc - 1]->arg;
712
713 return distribute_list_parser(prefix, true, argv[2 + prefix]->text,
714 argv[1 + prefix]->arg, ifname);
715 }
716
717 DEFUN (babel_no_distribute_list,
718 babel_no_distribute_list_cmd,
719 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
720 NO_STR
721 "Filter networks in routing updates\n"
722 "Specify a prefix\n"
723 "Access-list name\n"
724 "Filter incoming routing updates\n"
725 "Filter outgoing routing updates\n"
726 "Interface name\n")
727 {
728 const char *ifname = NULL;
729 int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
730
731 if (argv[argc - 1]->type == VARIABLE_TKN)
732 ifname = argv[argc - 1]->arg;
733
734 return distribute_list_no_parser(vty, prefix, true,
735 argv[3 + prefix]->text,
736 argv[2 + prefix]->arg, ifname);
737 }
738
739 DEFUN (babel_ipv6_distribute_list,
740 babel_ipv6_distribute_list_cmd,
741 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
742 "IPv6\n"
743 "Filter networks in routing updates\n"
744 "Specify a prefix\n"
745 "Access-list name\n"
746 "Filter incoming routing updates\n"
747 "Filter outgoing routing updates\n"
748 "Interface name\n")
749 {
750 const char *ifname = NULL;
751 int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
752
753 if (argv[argc - 1]->type == VARIABLE_TKN)
754 ifname = argv[argc - 1]->arg;
755
756 return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
757 argv[2 + prefix]->arg, ifname);
758 }
759
760 DEFUN (babel_no_ipv6_distribute_list,
761 babel_no_ipv6_distribute_list_cmd,
762 "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
763 NO_STR
764 "IPv6\n"
765 "Filter networks in routing updates\n"
766 "Specify a prefix\n"
767 "Access-list name\n"
768 "Filter incoming routing updates\n"
769 "Filter outgoing routing updates\n"
770 "Interface name\n")
771 {
772 const char *ifname = NULL;
773 int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
774
775 if (argv[argc - 1]->type == VARIABLE_TKN)
776 ifname = argv[argc - 1]->arg;
777
778 return distribute_list_no_parser(vty, prefix, false,
779 argv[4 + prefix]->text,
780 argv[3 + prefix]->arg, ifname);
781 }
782
783 void
784 babeld_quagga_init(void)
785 {
786
787 install_node(&cmd_babel_node);
788
789 install_element(CONFIG_NODE, &router_babel_cmd);
790 install_element(CONFIG_NODE, &no_router_babel_cmd);
791
792 install_default(BABEL_NODE);
793 install_element(BABEL_NODE, &babel_diversity_cmd);
794 install_element(BABEL_NODE, &no_babel_diversity_cmd);
795 install_element(BABEL_NODE, &babel_diversity_factor_cmd);
796 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
797 install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
798
799 install_element(BABEL_NODE, &babel_distribute_list_cmd);
800 install_element(BABEL_NODE, &babel_no_distribute_list_cmd);
801 install_element(BABEL_NODE, &babel_ipv6_distribute_list_cmd);
802 install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_cmd);
803
804 vrf_cmd_init(NULL);
805
806 babel_if_init();
807
808 /* Access list install. */
809 access_list_init ();
810 access_list_add_hook (babel_distribute_update_all_wrapper);
811 access_list_delete_hook (babel_distribute_update_all_wrapper);
812
813 /* Prefix list initialize.*/
814 prefix_list_init ();
815 prefix_list_add_hook (babel_distribute_update_all);
816 prefix_list_delete_hook (babel_distribute_update_all);
817 }
818
819 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
820
821 int
822 input_filter(const unsigned char *id,
823 const unsigned char *prefix, unsigned short plen,
824 const unsigned char *neigh, unsigned int ifindex)
825 {
826 return babel_filter(0, prefix, plen, ifindex);
827 }
828
829 int
830 output_filter(const unsigned char *id, const unsigned char *prefix,
831 unsigned short plen, unsigned int ifindex)
832 {
833 return babel_filter(1, prefix, plen, ifindex);
834 }
835
836 /* There's no redistribute filter in Quagga -- the zebra daemon does its
837 own filtering. */
838 int
839 redistribute_filter(const unsigned char *prefix, unsigned short plen,
840 unsigned int ifindex, int proto)
841 {
842 return 0;
843 }
844
845 struct babel *babel_lookup(void)
846 {
847 return babel_routing_process;
848 }