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