]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babeld.c
Merge pull request #754 from qlyoung/fix-argv-arg
[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
33 #include "babel_main.h"
34 #include "babeld.h"
35 #include "util.h"
36 #include "net.h"
37 #include "kernel.h"
38 #include "babel_interface.h"
39 #include "neighbour.h"
40 #include "route.h"
41 #include "message.h"
42 #include "resend.h"
43 #include "babel_filter.h"
44 #include "babel_zebra.h"
45 #include "babel_memory.h"
46
47 static int babel_init_routing_process(struct thread *thread);
48 static void babel_get_myid(void);
49 static void babel_initial_noise(void);
50 static int babel_read_protocol (struct thread *thread);
51 static int babel_main_loop(struct thread *thread);
52 static void babel_set_timer(struct timeval *timeout);
53 static void babel_fill_with_next_timeout(struct timeval *tv);
54
55
56 /* Informations relative to the babel running daemon. */
57 static struct babel *babel_routing_process = NULL;
58 static unsigned char *receive_buffer = NULL;
59 static int receive_buffer_size = 0;
60
61 /* timeouts */
62 struct timeval check_neighbours_timeout;
63 static time_t expiry_time;
64 static time_t source_expiry_time;
65
66 /* Babel node structure. */
67 static struct cmd_node cmd_babel_node =
68 {
69 .node = BABEL_NODE,
70 .prompt = "%s(config-router)# ",
71 .vtysh = 1,
72 };
73
74 /* print current babel configuration on vty */
75 static int
76 babel_config_write (struct vty *vty)
77 {
78 int lines = 0;
79 int i;
80
81 /* list enabled debug modes */
82 lines += debug_babel_config_write (vty);
83
84 if (!babel_routing_process)
85 return lines;
86 vty_out (vty, "router babel%s", VTY_NEWLINE);
87 if (diversity_kind != DIVERSITY_NONE)
88 {
89 vty_out (vty, " babel diversity%s", VTY_NEWLINE);
90 lines++;
91 }
92 if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
93 {
94 vty_out (vty, " babel diversity-factor %d%s", diversity_factor,
95 VTY_NEWLINE);
96 lines++;
97 }
98 if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
99 {
100 vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE);
101 lines++;
102 }
103 if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
104 {
105 vty_out (vty, " babel smoothing-half-life %u%s",
106 smoothing_half_life, VTY_NEWLINE);
107 lines++;
108 }
109 /* list enabled interfaces */
110 lines = 1 + babel_enable_if_config_write (vty);
111 /* list redistributed protocols */
112 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
113 if (i != zclient->redist_default &&
114 vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_DEFAULT))
115 {
116 vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE);
117 lines++;
118 }
119
120 lines += config_write_distribute (vty);
121
122 return lines;
123 }
124
125
126 static int
127 babel_create_routing_process (void)
128 {
129 assert (babel_routing_process == NULL);
130
131 /* Allocaste Babel instance. */
132 babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
133
134 /* Initialize timeouts */
135 gettime(&babel_now);
136 expiry_time = babel_now.tv_sec + roughly(30);
137 source_expiry_time = babel_now.tv_sec + roughly(300);
138
139 /* Make socket for Babel protocol. */
140 protocol_socket = babel_socket(protocol_port);
141 if (protocol_socket < 0) {
142 zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
143 goto fail;
144 }
145
146 /* Threads. */
147 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
148 /* wait a little: zebra will announce interfaces, addresses, routes... */
149 thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L, &babel_routing_process->t_update);
150 return 0;
151
152 fail:
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 */
159 static int
160 babel_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 == (ifindex_t)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 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
191 return 0;
192 }
193
194 /* Zebra will give some information, especially about interfaces. This function
195 must be call with a litte timeout wich may give zebra the time to do his job,
196 making these inits have sense. */
197 static int
198 babel_init_routing_process(struct thread *thread)
199 {
200 myseqno = (random() & 0xFFFF);
201 babel_get_myid();
202 babel_load_state_file();
203 debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
204 babel_initial_noise();
205 babel_main_loop(thread);/* this function self-add to the t_update thread */
206 return 0;
207 }
208
209 /* fill "myid" with an unique id (only if myid != {0}). */
210 static void
211 babel_get_myid(void)
212 {
213 struct interface *ifp = NULL;
214 struct listnode *linklist_node = NULL;
215 int rc;
216 int i;
217
218 /* if we already have an id (from state file), we return. */
219 if (memcmp(myid, zeroes, 8) != 0) {
220 return;
221 }
222
223 FOR_ALL_INTERFACES(ifp, linklist_node) {
224 /* ifp->ifindex is not necessarily valid at this point */
225 int ifindex = if_nametoindex(ifp->name);
226 if(ifindex > 0) {
227 unsigned char eui[8];
228 rc = if_eui64(ifp->name, ifindex, eui);
229 if(rc < 0)
230 continue;
231 memcpy(myid, eui, 8);
232 return;
233 }
234 }
235
236 /* We failed to get a global EUI64 from the interfaces we were given.
237 Let's try to find an interface with a MAC address. */
238 for(i = 1; i < 256; i++) {
239 char buf[IF_NAMESIZE], *ifname;
240 unsigned char eui[8];
241 ifname = if_indextoname(i, buf);
242 if(ifname == NULL)
243 continue;
244 rc = if_eui64(ifname, i, eui);
245 if(rc < 0)
246 continue;
247 memcpy(myid, eui, 8);
248 return;
249 }
250
251 zlog_err("Warning: couldn't find router id -- using random value.");
252
253 rc = read_random_bytes(myid, 8);
254 if(rc < 0) {
255 zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
256 exit(1);
257 }
258 /* Clear group and global bits */
259 myid[0] &= ~3;
260 }
261
262 /* Make some noise so that others notice us, and send retractions in
263 case we were restarted recently */
264 static void
265 babel_initial_noise(void)
266 {
267 struct interface *ifp = NULL;
268 struct listnode *linklist_node = NULL;
269
270 FOR_ALL_INTERFACES(ifp, linklist_node) {
271 if(!if_up(ifp))
272 continue;
273 /* Apply jitter before we send the first message. */
274 usleep(roughly(10000));
275 gettime(&babel_now);
276 send_hello(ifp);
277 send_wildcard_retraction(ifp);
278 }
279
280 FOR_ALL_INTERFACES(ifp, linklist_node) {
281 if(!if_up(ifp))
282 continue;
283 usleep(roughly(10000));
284 gettime(&babel_now);
285 send_hello(ifp);
286 send_wildcard_retraction(ifp);
287 send_self_update(ifp);
288 send_request(ifp, NULL, 0);
289 flushupdates(ifp);
290 flushbuf(ifp);
291 }
292 }
293
294 /* Delete all the added babel routes, make babeld only speak to zebra. */
295 static void
296 babel_clean_routing_process()
297 {
298 flush_all_routes();
299 babel_interface_close_all();
300
301 /* cancel threads */
302 if (babel_routing_process->t_read != NULL) {
303 thread_cancel(babel_routing_process->t_read);
304 }
305 if (babel_routing_process->t_update != NULL) {
306 thread_cancel(babel_routing_process->t_update);
307 }
308
309 XFREE(MTYPE_BABEL, babel_routing_process);
310 babel_routing_process = NULL;
311 }
312
313 /* Function used with timeout. */
314 static int
315 babel_main_loop(struct thread *thread)
316 {
317 struct timeval tv;
318 struct interface *ifp = NULL;
319 struct listnode *linklist_node = NULL;
320
321 while(1) {
322 gettime(&babel_now);
323
324 /* timeouts --------------------------------------------------------- */
325 /* get the next timeout */
326 babel_fill_with_next_timeout(&tv);
327 /* if there is no timeout, we must wait. */
328 if(timeval_compare(&tv, &babel_now) > 0) {
329 timeval_minus(&tv, &tv, &babel_now);
330 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
331 tv.tv_sec * 1000 + tv.tv_usec / 1000);
332 /* it happens often to have less than 1 ms, it's bad. */
333 timeval_add_msec(&tv, &tv, 300);
334 babel_set_timer(&tv);
335 return 0;
336 }
337
338 gettime(&babel_now);
339
340 /* update database -------------------------------------------------- */
341 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
342 int msecs;
343 msecs = check_neighbours();
344 /* Multiply by 3/2 to allow neighbours to expire. */
345 msecs = MAX(3 * msecs / 2, 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
399 static void
400 printIfMin(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
439 static void
440 babel_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) */
482 static void
483 babel_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 thread_add_timer_msec(master, babel_main_loop, NULL, msecs, &babel_routing_process->t_update);
490 }
491
492 void
493 schedule_neighbours_check(int msecs, int override)
494 {
495 struct timeval timeout;
496
497 timeval_add_msec(&timeout, &babel_now, msecs);
498 if(override)
499 check_neighbours_timeout = timeout;
500 else
501 timeval_min(&check_neighbours_timeout, &timeout);
502 }
503
504 int
505 resize_receive_buffer(int size)
506 {
507 if(size <= receive_buffer_size)
508 return 0;
509
510 if(receive_buffer == NULL) {
511 receive_buffer = malloc(size);
512 if(receive_buffer == NULL) {
513 zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
514 return -1;
515 }
516 receive_buffer_size = size;
517 } else {
518 unsigned char *new;
519 new = realloc(receive_buffer, size);
520 if(new == NULL) {
521 zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
522 return -1;
523 }
524 receive_buffer = new;
525 receive_buffer_size = size;
526 }
527 return 1;
528 }
529
530 static void
531 babel_distribute_update (struct distribute *dist)
532 {
533 struct interface *ifp;
534 babel_interface_nfo *babel_ifp;
535 int type;
536 int family;
537
538 if (! dist->ifname)
539 return;
540
541 ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
542 if (ifp == NULL)
543 return;
544
545 babel_ifp = babel_get_if_nfo(ifp);
546
547 for (type = 0; type < DISTRIBUTE_MAX; type++) {
548 family = type == DISTRIBUTE_V4_IN || type == DISTRIBUTE_V4_OUT ?
549 AFI_IP : AFI_IP6;
550 if (dist->list[type])
551 babel_ifp->list[type] = access_list_lookup (family,
552 dist->list[type]);
553 else
554 babel_ifp->list[type] = NULL;
555 if (dist->prefix[type])
556 babel_ifp->prefix[type] = prefix_list_lookup (family,
557 dist->prefix[type]);
558 else
559 babel_ifp->prefix[type] = NULL;
560 }
561 }
562
563 static void
564 babel_distribute_update_interface (struct interface *ifp)
565 {
566 struct distribute *dist;
567
568 dist = distribute_lookup (ifp->name);
569 if (dist)
570 babel_distribute_update (dist);
571 }
572
573 /* Update all interface's distribute list. */
574 static void
575 babel_distribute_update_all (struct prefix_list *notused)
576 {
577 struct interface *ifp;
578 struct listnode *node;
579
580 for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp))
581 babel_distribute_update_interface (ifp);
582 }
583
584 static void
585 babel_distribute_update_all_wrapper (struct access_list *notused)
586 {
587 babel_distribute_update_all(NULL);
588 }
589
590
591 /* [Command] */
592 DEFUN_NOSH (router_babel,
593 router_babel_cmd,
594 "router babel",
595 "Enable a routing process\n"
596 "Make Babel instance command\n")
597 {
598 int ret;
599
600 vty->node = BABEL_NODE;
601
602 if (!babel_routing_process) {
603 ret = babel_create_routing_process ();
604
605 /* Notice to user we couldn't create Babel. */
606 if (ret < 0) {
607 zlog_warn ("can't create Babel");
608 return CMD_WARNING;
609 }
610 }
611
612 return CMD_SUCCESS;
613 }
614
615 /* [Command] */
616 DEFUN (no_router_babel,
617 no_router_babel_cmd,
618 "no router babel",
619 NO_STR
620 "Disable a routing process\n"
621 "Remove Babel instance command\n"
622 "No attributes\n")
623 {
624 if(babel_routing_process)
625 babel_clean_routing_process();
626 return CMD_SUCCESS;
627 }
628
629 /* [Babel Command] */
630 DEFUN (babel_diversity,
631 babel_diversity_cmd,
632 "babel diversity",
633 "Babel commands\n"
634 "Enable diversity-aware routing.\n")
635 {
636 diversity_kind = DIVERSITY_CHANNEL;
637 return CMD_SUCCESS;
638 }
639
640 /* [Babel Command] */
641 DEFUN (no_babel_diversity,
642 no_babel_diversity_cmd,
643 "no babel diversity",
644 NO_STR
645 "Babel commands\n"
646 "Disable diversity-aware routing.\n")
647 {
648 diversity_kind = DIVERSITY_NONE;
649 return CMD_SUCCESS;
650 }
651
652 /* [Babel Command] */
653 DEFUN (babel_diversity_factor,
654 babel_diversity_factor_cmd,
655 "babel diversity-factor (1-256)",
656 "Babel commands\n"
657 "Set the diversity factor.\n"
658 "Factor in units of 1/256.\n")
659 {
660 int factor;
661
662 factor = strtoul(argv[2]->arg, NULL, 10);
663
664 diversity_factor = factor;
665 return CMD_SUCCESS;
666 }
667
668 /* [Babel Command] */
669 DEFUN (babel_set_resend_delay,
670 babel_set_resend_delay_cmd,
671 "babel resend-delay (20-655340)",
672 "Babel commands\n"
673 "Time before resending a message\n"
674 "Milliseconds\n")
675 {
676 int interval;
677
678 interval = strtoul(argv[2]->arg, NULL, 10);
679
680 resend_delay = interval;
681 return CMD_SUCCESS;
682 }
683
684 /* [Babel Command] */
685 DEFUN (babel_set_smoothing_half_life,
686 babel_set_smoothing_half_life_cmd,
687 "babel smoothing-half-life (0-65534)",
688 "Babel commands\n"
689 "Smoothing half-life\n"
690 "Seconds (0 to disable)\n")
691 {
692 int seconds;
693
694 seconds = strtoul(argv[2]->arg, NULL, 10);
695
696 change_smoothing_half_life(seconds);
697 return CMD_SUCCESS;
698 }
699
700 void
701 babeld_quagga_init(void)
702 {
703
704 install_node(&cmd_babel_node, &babel_config_write);
705
706 install_element(CONFIG_NODE, &router_babel_cmd);
707 install_element(CONFIG_NODE, &no_router_babel_cmd);
708
709 install_default(BABEL_NODE);
710 install_element(BABEL_NODE, &babel_diversity_cmd);
711 install_element(BABEL_NODE, &no_babel_diversity_cmd);
712 install_element(BABEL_NODE, &babel_diversity_factor_cmd);
713 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
714 install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
715
716 babel_if_init();
717
718 /* Access list install. */
719 access_list_init ();
720 access_list_add_hook (babel_distribute_update_all_wrapper);
721 access_list_delete_hook (babel_distribute_update_all_wrapper);
722
723 /* Prefix list initialize.*/
724 prefix_list_init ();
725 prefix_list_add_hook (babel_distribute_update_all);
726 prefix_list_delete_hook (babel_distribute_update_all);
727
728 /* Distribute list install. */
729 distribute_list_init (BABEL_NODE);
730 distribute_list_add_hook (babel_distribute_update);
731 distribute_list_delete_hook (babel_distribute_update);
732 }
733
734 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
735
736 int
737 input_filter(const unsigned char *id,
738 const unsigned char *prefix, unsigned short plen,
739 const unsigned char *neigh, unsigned int ifindex)
740 {
741 return babel_filter(0, prefix, plen, ifindex);
742 }
743
744 int
745 output_filter(const unsigned char *id, const unsigned char *prefix,
746 unsigned short plen, unsigned int ifindex)
747 {
748 return babel_filter(1, prefix, plen, ifindex);
749 }
750
751 /* There's no redistribute filter in Quagga -- the zebra daemon does its
752 own filtering. */
753 int
754 redistribute_filter(const unsigned char *prefix, unsigned short plen,
755 unsigned int ifindex, int proto)
756 {
757 return 0;
758 }
759