blob: eaa91b74cf172e899e421af904d9aa68f54dd936 [file] [log] [blame]
Paul Jakma57345092011-12-25 17:52:09 +01001/*
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18
19Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20
21Permission is hereby granted, free of charge, to any person obtaining a copy
22of this software and associated documentation files (the "Software"), to deal
23in the Software without restriction, including without limitation the rights
24to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25copies of the Software, and to permit persons to whom the Software is
26furnished to do so, subject to the following conditions:
27
28The above copyright notice and this permission notice shall be included in
29all copies or substantial portions of the Software.
30
31THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37THE SOFTWARE.
38*/
39
40#include <zebra.h>
41#include "command.h"
42#include "prefix.h"
43#include "memory.h"
44#include "memtypes.h"
45#include "table.h"
46#include "distribute.h"
47#include "prefix.h"
48#include "filter.h"
49#include "plist.h"
50
51#include "babel_main.h"
52#include "babeld.h"
53#include "util.h"
54#include "net.h"
55#include "kernel.h"
56#include "babel_interface.h"
57#include "neighbour.h"
58#include "route.h"
59#include "message.h"
60#include "resend.h"
61#include "babel_filter.h"
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +040062#include "babel_zebra.h"
Paul Jakma57345092011-12-25 17:52:09 +010063
64
65static int babel_init_routing_process(struct thread *thread);
66static void babel_get_myid(void);
67static void babel_initial_noise(void);
68static int babel_read_protocol (struct thread *thread);
69static int babel_main_loop(struct thread *thread);
70static void babel_set_timer(struct timeval *timeout);
71static void babel_fill_with_next_timeout(struct timeval *tv);
72
73
74/* Informations relative to the babel running daemon. */
75static struct babel *babel_routing_process = NULL;
76static unsigned char *receive_buffer = NULL;
77static int receive_buffer_size = 0;
78
79/* timeouts */
80struct timeval check_neighbours_timeout;
81static time_t expiry_time;
82static time_t source_expiry_time;
83
84/* Babel node structure. */
85static struct cmd_node cmd_babel_node =
86{
87 .node = BABEL_NODE,
88 .prompt = "%s(config-router)# ",
89 .vtysh = 1,
90};
91
92/* print current babel configuration on vty */
93static int
94babel_config_write (struct vty *vty)
95{
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +040096 int lines = 0;
97 int i;
98
99 /* list enabled debug modes */
100 lines += debug_babel_config_write (vty);
101
102 if (!babel_routing_process)
103 return lines;
104 vty_out (vty, "router babel%s", VTY_NEWLINE);
Denis Ovsienkocbde1552012-02-14 15:12:03 +0400105 if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
106 {
107 vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE);
108 lines++;
109 }
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +0400110 /* list enabled interfaces */
111 lines = 1 + babel_enable_if_config_write (vty);
112 /* list redistributed protocols */
113 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
114 if (i != zclient->redist_default && zclient->redist[i])
115 {
116 vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE);
117 lines++;
118 }
119
120 return lines;
Paul Jakma57345092011-12-25 17:52:09 +0100121}
122
123
124static int
125babel_create_routing_process (void)
126{
127 assert (babel_routing_process == NULL);
128
129 /* Allocaste Babel instance. */
130 babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
131
132 /* Initialize timeouts */
133 gettime(&babel_now);
134 expiry_time = babel_now.tv_sec + roughly(30);
135 source_expiry_time = babel_now.tv_sec + roughly(300);
136
137 /* Make socket for Babel protocol. */
138 protocol_socket = babel_socket(protocol_port);
139 if (protocol_socket < 0) {
140 zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
141 goto fail;
142 }
143
144 /* Threads. */
145 babel_routing_process->t_read =
146 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
147 /* wait a little: zebra will announce interfaces, addresses, routes... */
148 babel_routing_process->t_update =
149 thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
150 return 0;
151
152fail:
153 XFREE(MTYPE_BABEL, babel_routing_process);
154 babel_routing_process = NULL;
155 return -1;
156}
157
158/* thread reading entries form others babel daemons */
159static int
160babel_read_protocol (struct thread *thread)
161{
162 int rc;
163 struct interface *ifp = NULL;
164 struct sockaddr_in6 sin6;
165 struct listnode *linklist_node = NULL;
166
167 assert(babel_routing_process != NULL);
168 assert(protocol_socket >= 0);
169
170 rc = babel_recv(protocol_socket,
171 receive_buffer, receive_buffer_size,
172 (struct sockaddr*)&sin6, sizeof(sin6));
173 if(rc < 0) {
174 if(errno != EAGAIN && errno != EINTR) {
175 zlog_err("recv: %s", safe_strerror(errno));
176 }
177 } else {
178 FOR_ALL_INTERFACES(ifp, linklist_node) {
179 if(!if_up(ifp))
180 continue;
181 if(ifp->ifindex == sin6.sin6_scope_id) {
182 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
183 receive_buffer, rc);
184 break;
185 }
186 }
187 }
188
189 /* re-add thread */
190 babel_routing_process->t_read =
191 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
192 return 0;
193}
194
195/* Zebra will give some information, especially about interfaces. This function
196 must be call with a litte timeout wich may give zebra the time to do his job,
197 making these inits have sense. */
198static int
199babel_init_routing_process(struct thread *thread)
200{
Matthieu Boutier69394542012-01-28 10:35:12 +0100201 myseqno = (random() & 0xFFFF);
Paul Jakma57345092011-12-25 17:52:09 +0100202 babel_get_myid();
Matthieu Boutier69394542012-01-28 10:35:12 +0100203 babel_load_state_file();
Paul Jakma57345092011-12-25 17:52:09 +0100204 debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
205 babel_initial_noise();
206 babel_main_loop(thread);/* this function self-add to the t_update thread */
207 return 0;
208}
209
210/* fill "myid" with an unique id (only if myid != {0}). */
211static void
212babel_get_myid(void)
213{
214 struct interface *ifp = NULL;
215 struct listnode *linklist_node = NULL;
216 int rc;
217 int i;
218
219 /* if we already have an id (from state file), we return. */
220 if (memcmp(myid, zeroes, 8) != 0) {
221 return;
222 }
223
224 FOR_ALL_INTERFACES(ifp, linklist_node) {
225 /* ifp->ifindex is not necessarily valid at this point */
226 int ifindex = if_nametoindex(ifp->name);
227 if(ifindex > 0) {
228 unsigned char eui[8];
229 rc = if_eui64(ifp->name, ifindex, eui);
230 if(rc < 0)
231 continue;
232 memcpy(myid, eui, 8);
233 return;
234 }
235 }
236
237 /* We failed to get a global EUI64 from the interfaces we were given.
238 Let's try to find an interface with a MAC address. */
239 for(i = 1; i < 256; i++) {
240 char buf[IF_NAMESIZE], *ifname;
241 unsigned char eui[8];
242 ifname = if_indextoname(i, buf);
243 if(ifname == NULL)
244 continue;
245 rc = if_eui64(ifname, i, eui);
246 if(rc < 0)
247 continue;
248 memcpy(myid, eui, 8);
249 return;
250 }
251
252 zlog_err("Warning: couldn't find router id -- using random value.");
253
254 rc = read_random_bytes(myid, 8);
255 if(rc < 0) {
256 zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
257 exit(1);
258 }
259 /* Clear group and global bits */
260 myid[0] &= ~3;
261}
262
263/* Make some noise so that others notice us, and send retractions in
264 case we were restarted recently */
265static void
266babel_initial_noise(void)
267{
268 struct interface *ifp = NULL;
269 struct listnode *linklist_node = NULL;
270
271 FOR_ALL_INTERFACES(ifp, linklist_node) {
272 if(!if_up(ifp))
273 continue;
274 /* Apply jitter before we send the first message. */
275 usleep(roughly(10000));
276 gettime(&babel_now);
277 send_hello(ifp);
278 send_wildcard_retraction(ifp);
279 }
280
281 FOR_ALL_INTERFACES(ifp, linklist_node) {
282 if(!if_up(ifp))
283 continue;
284 usleep(roughly(10000));
285 gettime(&babel_now);
286 send_hello(ifp);
287 send_wildcard_retraction(ifp);
288 send_self_update(ifp);
289 send_request(ifp, NULL, 0);
290 flushupdates(ifp);
291 flushbuf(ifp);
292 }
293}
294
295/* Delete all the added babel routes, make babeld only speak to zebra. */
296static void
297babel_clean_routing_process()
298{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100299 flush_all_routes();
Paul Jakma57345092011-12-25 17:52:09 +0100300 babel_interface_close_all();
301
302 /* cancel threads */
303 if (babel_routing_process->t_read != NULL) {
304 thread_cancel(babel_routing_process->t_read);
305 }
306 if (babel_routing_process->t_update != NULL) {
307 thread_cancel(babel_routing_process->t_update);
308 }
309
310 XFREE(MTYPE_BABEL, babel_routing_process);
311 babel_routing_process = NULL;
312}
313
314/* Function used with timeout. */
315static int
316babel_main_loop(struct thread *thread)
317{
318 struct timeval tv;
319 struct interface *ifp = NULL;
320 struct listnode *linklist_node = NULL;
321
322 while(1) {
323 gettime(&babel_now);
324
325 /* timeouts --------------------------------------------------------- */
326 /* get the next timeout */
327 babel_fill_with_next_timeout(&tv);
328 /* if there is no timeout, we must wait. */
329 if(timeval_compare(&tv, &babel_now) > 0) {
330 timeval_minus(&tv, &tv, &babel_now);
David Lamparteref008d22015-03-03 08:48:11 +0100331 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
332 tv.tv_sec * 1000LL + tv.tv_usec / 1000LL);
Paul Jakma57345092011-12-25 17:52:09 +0100333 /* it happens often to have less than 1 ms, it's bad. */
334 timeval_add_msec(&tv, &tv, 300);
335 babel_set_timer(&tv);
336 return 0;
337 }
338
339 gettime(&babel_now);
340
341 /* update database -------------------------------------------------- */
342 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
343 int msecs;
344 msecs = check_neighbours();
345 msecs = MAX(msecs, 10);
346 schedule_neighbours_check(msecs, 1);
347 }
348
349 if(babel_now.tv_sec >= expiry_time) {
350 expire_routes();
351 expire_resend();
352 expiry_time = babel_now.tv_sec + roughly(30);
353 }
354
355 if(babel_now.tv_sec >= source_expiry_time) {
356 expire_sources();
357 source_expiry_time = babel_now.tv_sec + roughly(300);
358 }
359
360 FOR_ALL_INTERFACES(ifp, linklist_node) {
361 babel_interface_nfo *babel_ifp = NULL;
362 if(!if_up(ifp))
363 continue;
364 babel_ifp = babel_get_if_nfo(ifp);
365 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
366 send_hello(ifp);
367 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
368 send_update(ifp, 0, NULL, 0);
369 if(timeval_compare(&babel_now,
370 &babel_ifp->update_flush_timeout) >= 0)
371 flushupdates(ifp);
372 }
373
374 if(resend_time.tv_sec != 0) {
375 if(timeval_compare(&babel_now, &resend_time) >= 0)
376 do_resend();
377 }
378
379 if(unicast_flush_timeout.tv_sec != 0) {
380 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
381 flush_unicast(1);
382 }
383
384 FOR_ALL_INTERFACES(ifp, linklist_node) {
385 babel_interface_nfo *babel_ifp = NULL;
386 if(!if_up(ifp))
387 continue;
388 babel_ifp = babel_get_if_nfo(ifp);
389 if(babel_ifp->flush_timeout.tv_sec != 0) {
390 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
391 flushbuf(ifp);
392 }
393 }
394 }
395
396 assert(0); /* this line should never be reach */
397}
398
399static void
400printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
401{
402 static struct timeval curr_tv;
403 static char buffer[200];
404 static const char *curr_tag = NULL;
405
406 switch (cmd) {
407 case 0: /* reset timeval */
408 curr_tv = *tv;
409 if(ifname != NULL) {
410 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
411 curr_tag = buffer;
412 } else {
413 curr_tag = tag;
414 }
415 break;
416 case 1: /* take the min */
417 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
418 break;
419 }
420 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
421 tv->tv_usec < curr_tv.tv_usec)) {
422 curr_tv = *tv;
423 if(ifname != NULL) {
424 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
425 curr_tag = buffer;
426 } else {
427 curr_tag = tag;
428 }
429 }
430 break;
431 case 2: /* print message */
432 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
433 break;
434 default:
435 break;
436 }
437}
438
439static void
440babel_fill_with_next_timeout(struct timeval *tv)
441{
442#if (defined NO_DEBUG)
443#define printIfMin(a,b,c,d)
444#else
445#define printIfMin(a,b,c,d) \
446 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
447
448 struct interface *ifp = NULL;
449 struct listnode *linklist_node = NULL;
450
451 *tv = check_neighbours_timeout;
452 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
453 timeval_min_sec(tv, expiry_time);
454 printIfMin(tv, 1, "expiry_time", NULL);
455 timeval_min_sec(tv, source_expiry_time);
456 printIfMin(tv, 1, "source_expiry_time", NULL);
457 timeval_min(tv, &resend_time);
458 printIfMin(tv, 1, "resend_time", NULL);
459 FOR_ALL_INTERFACES(ifp, linklist_node) {
460 babel_interface_nfo *babel_ifp = NULL;
461 if(!if_up(ifp))
462 continue;
463 babel_ifp = babel_get_if_nfo(ifp);
464 timeval_min(tv, &babel_ifp->flush_timeout);
465 printIfMin(tv, 1, "flush_timeout", ifp->name);
466 timeval_min(tv, &babel_ifp->hello_timeout);
467 printIfMin(tv, 1, "hello_timeout", ifp->name);
468 timeval_min(tv, &babel_ifp->update_timeout);
469 printIfMin(tv, 1, "update_timeout", ifp->name);
470 timeval_min(tv, &babel_ifp->update_flush_timeout);
471 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
472 }
473 timeval_min(tv, &unicast_flush_timeout);
474 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
475 printIfMin(tv, 2, NULL, NULL);
476#undef printIfMin
477#endif
478}
479
480/* set the t_update thread of the babel routing process to be launch in
481 'timeout' (approximate at the milisecond) */
482static void
483babel_set_timer(struct timeval *timeout)
484{
485 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
486 if (babel_routing_process->t_update != NULL) {
487 thread_cancel(babel_routing_process->t_update);
488 }
489 babel_routing_process->t_update =
490 thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
491}
492
493/* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
494void
495schedule_neighbours_check(int msecs, int override)
496{
497 struct timeval timeout;
498
499 timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
500 if(override)
501 check_neighbours_timeout = timeout;
502 else
503 timeval_min(&check_neighbours_timeout, &timeout);
504}
505
506int
507resize_receive_buffer(int size)
508{
509 if(size <= receive_buffer_size)
510 return 0;
511
512 if(receive_buffer == NULL) {
513 receive_buffer = malloc(size);
514 if(receive_buffer == NULL) {
515 zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
516 return -1;
517 }
518 receive_buffer_size = size;
519 } else {
520 unsigned char *new;
521 new = realloc(receive_buffer, size);
522 if(new == NULL) {
523 zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
524 return -1;
525 }
526 receive_buffer = new;
527 receive_buffer_size = size;
528 }
529 return 1;
530}
531
532static void
533babel_distribute_update (struct distribute *dist)
534{
535 struct interface *ifp;
536 babel_interface_nfo *babel_ifp;
537 struct access_list *alist;
538 struct prefix_list *plist;
539
540 if (! dist->ifname)
541 return;
542
543 ifp = if_lookup_by_name (dist->ifname);
544 if (ifp == NULL)
545 return;
546
547 babel_ifp = babel_get_if_nfo(ifp);
548
549 if (dist->list[DISTRIBUTE_IN]) {
550 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
551 if (alist)
552 babel_ifp->list[BABEL_FILTER_IN] = alist;
553 else
554 babel_ifp->list[BABEL_FILTER_IN] = NULL;
555 } else {
556 babel_ifp->list[BABEL_FILTER_IN] = NULL;
557 }
558
559 if (dist->list[DISTRIBUTE_OUT]) {
560 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
561 if (alist)
562 babel_ifp->list[BABEL_FILTER_OUT] = alist;
563 else
564 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
565 } else {
566 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
567 }
568
569 if (dist->prefix[DISTRIBUTE_IN]) {
570 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
571 if (plist)
572 babel_ifp->prefix[BABEL_FILTER_IN] = plist;
573 else
574 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
575 } else {
576 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
577 }
578
579 if (dist->prefix[DISTRIBUTE_OUT]) {
580 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
581 if (plist)
582 babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
583 else
584 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
585 } else {
586 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
587 }
588}
589
Denis Ovsienko3dbda0c2012-01-08 16:52:36 +0400590static void
Paul Jakma57345092011-12-25 17:52:09 +0100591babel_distribute_update_interface (struct interface *ifp)
592{
593 struct distribute *dist;
594
595 dist = distribute_lookup (ifp->name);
596 if (dist)
597 babel_distribute_update (dist);
598}
599
600/* Update all interface's distribute list. */
601static void
602babel_distribute_update_all (struct prefix_list *notused)
603{
604 struct interface *ifp;
605 struct listnode *node;
606
607 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
608 babel_distribute_update_interface (ifp);
609}
610
611static void
612babel_distribute_update_all_wrapper (struct access_list *notused)
613{
614 babel_distribute_update_all(NULL);
615}
616
617
618/* [Command] */
619DEFUN (router_babel,
620 router_babel_cmd,
621 "router babel",
622 "Enable a routing process\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100623 "Make Babel instance command\n"
624 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100625{
626 int ret;
627
628 vty->node = BABEL_NODE;
629
630 if (!babel_routing_process) {
631 ret = babel_create_routing_process ();
632
633 /* Notice to user we couldn't create Babel. */
634 if (ret < 0) {
635 zlog_warn ("can't create Babel");
Juliusz Chroboczek38846de2012-02-07 05:43:36 +0100636 return CMD_WARNING;
Paul Jakma57345092011-12-25 17:52:09 +0100637 }
638 }
639
640 return CMD_SUCCESS;
641}
642
643/* [Command] */
644DEFUN (no_router_babel,
645 no_router_babel_cmd,
646 "no router babel",
647 NO_STR
648 "Disable a routing process\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100649 "Remove Babel instance command\n"
650 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100651{
652 if(babel_routing_process)
653 babel_clean_routing_process();
654 return CMD_SUCCESS;
655}
656
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100657/* [Babel Command] */
658DEFUN (babel_set_resend_delay,
659 babel_set_resend_delay_cmd,
660 "babel resend-delay <20-655340>",
661 "Babel commands\n"
662 "Time before resending a message\n"
663 "Milliseconds\n")
664{
665 int interval;
666
667 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
668
669 resend_delay = interval;
670 return CMD_SUCCESS;
671}
672
Paul Jakma57345092011-12-25 17:52:09 +0100673void
674babeld_quagga_init(void)
675{
676
677 install_node(&cmd_babel_node, &babel_config_write);
678
679 install_element(CONFIG_NODE, &router_babel_cmd);
680 install_element(CONFIG_NODE, &no_router_babel_cmd);
681
682 install_default(BABEL_NODE);
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100683 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
Paul Jakma57345092011-12-25 17:52:09 +0100684
685 babel_if_init();
686
687 /* Access list install. */
688 access_list_init ();
689 access_list_add_hook (babel_distribute_update_all_wrapper);
690 access_list_delete_hook (babel_distribute_update_all_wrapper);
691
692 /* Prefix list initialize.*/
693 prefix_list_init ();
694 prefix_list_add_hook (babel_distribute_update_all);
695 prefix_list_delete_hook (babel_distribute_update_all);
696
697 /* Distribute list install. */
698 distribute_list_init (BABEL_NODE);
699 distribute_list_add_hook (babel_distribute_update);
700 distribute_list_delete_hook (babel_distribute_update);
701}
702
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100703/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
704
705int
Paul Jakma57345092011-12-25 17:52:09 +0100706input_filter(const unsigned char *id,
707 const unsigned char *prefix, unsigned short plen,
708 const unsigned char *neigh, unsigned int ifindex)
709{
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100710 return babel_filter(0, prefix, plen, ifindex);
Paul Jakma57345092011-12-25 17:52:09 +0100711}
712
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100713int
Paul Jakma57345092011-12-25 17:52:09 +0100714output_filter(const unsigned char *id, const unsigned char *prefix,
715 unsigned short plen, unsigned int ifindex)
716{
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100717 return babel_filter(1, prefix, plen, ifindex);
Paul Jakma57345092011-12-25 17:52:09 +0100718}
719
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100720/* There's no redistribute filter in Quagga -- the zebra daemon does its
721 own filtering. */
722int
Paul Jakma57345092011-12-25 17:52:09 +0100723redistribute_filter(const unsigned char *prefix, unsigned short plen,
724 unsigned int ifindex, int proto)
725{
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100726 return 0;
Paul Jakma57345092011-12-25 17:52:09 +0100727}
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100728