2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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
28 #include "distribute.h"
32 #include "lib_errors.h"
35 #include "babel_main.h"
40 #include "babel_interface.h"
41 #include "neighbour.h"
45 #include "babel_filter.h"
46 #include "babel_zebra.h"
47 #include "babel_errors.h"
49 DEFINE_MGROUP(BABELD
, "babeld");
50 DEFINE_MTYPE_STATIC(BABELD
, BABEL
, "Babel Structure");
52 static int babel_init_routing_process(struct thread
*thread
);
53 static void babel_get_myid(void);
54 static void babel_initial_noise(void);
55 static int babel_read_protocol (struct thread
*thread
);
56 static int babel_main_loop(struct thread
*thread
);
57 static void babel_set_timer(struct timeval
*timeout
);
58 static void babel_fill_with_next_timeout(struct timeval
*tv
);
60 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
);
62 /* Informations relative to the babel running daemon. */
63 static struct babel
*babel_routing_process
= NULL
;
64 static unsigned char *receive_buffer
= NULL
;
65 static int receive_buffer_size
= 0;
68 struct timeval check_neighbours_timeout
;
69 static time_t expiry_time
;
70 static time_t source_expiry_time
;
72 /* Babel node structure. */
73 static int babel_config_write (struct vty
*vty
);
74 static struct cmd_node cmd_babel_node
=
78 .parent_node
= CONFIG_NODE
,
79 .prompt
= "%s(config-router)# ",
80 .config_write
= babel_config_write
,
83 /* print current babel configuration on vty */
85 babel_config_write (struct vty
*vty
)
91 /* list enabled debug modes */
92 lines
+= debug_babel_config_write (vty
);
94 if (!babel_routing_process
)
96 vty_out (vty
, "router babel\n");
97 if (diversity_kind
!= DIVERSITY_NONE
)
99 vty_out (vty
, " babel diversity\n");
102 if (diversity_factor
!= BABEL_DEFAULT_DIVERSITY_FACTOR
)
104 vty_out (vty
, " babel diversity-factor %d\n",diversity_factor
);
107 if (resend_delay
!= BABEL_DEFAULT_RESEND_DELAY
)
109 vty_out (vty
, " babel resend-delay %u\n", resend_delay
);
112 if (smoothing_half_life
!= BABEL_DEFAULT_SMOOTHING_HALF_LIFE
)
114 vty_out (vty
, " babel smoothing-half-life %u\n",
115 smoothing_half_life
);
118 /* list enabled interfaces */
119 lines
= 1 + babel_enable_if_config_write (vty
);
120 /* list redistributed protocols */
121 for (afi
= AFI_IP
; afi
<= AFI_IP6
; afi
++) {
122 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
123 if (i
!= zclient
->redist_default
&&
124 vrf_bitmap_check (zclient
->redist
[afi
][i
], VRF_DEFAULT
)) {
125 vty_out (vty
, " redistribute %s %s\n",
126 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
127 zebra_route_string(i
));
133 lines
+= config_write_distribute (vty
, babel_routing_process
->distribute_ctx
);
135 vty_out (vty
, "exit\n");
142 babel_create_routing_process (void)
144 assert (babel_routing_process
== NULL
);
146 /* Allocaste Babel instance. */
147 babel_routing_process
= XCALLOC(MTYPE_BABEL
, sizeof(struct babel
));
149 /* Initialize timeouts */
151 expiry_time
= babel_now
.tv_sec
+ roughly(30);
152 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
154 /* Make socket for Babel protocol. */
155 protocol_socket
= babel_socket(protocol_port
);
156 if (protocol_socket
< 0) {
157 flog_err_sys(EC_LIB_SOCKET
, "Couldn't create link local socket: %s",
158 safe_strerror(errno
));
163 thread_add_read(master
, &babel_read_protocol
, NULL
, protocol_socket
, &babel_routing_process
->t_read
);
164 /* wait a little: zebra will announce interfaces, addresses, routes... */
165 thread_add_timer_msec(master
, babel_init_routing_process
, NULL
, 200L, &babel_routing_process
->t_update
);
167 /* Distribute list install. */
168 babel_routing_process
->distribute_ctx
= distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT
));
169 distribute_list_add_hook (babel_routing_process
->distribute_ctx
, babel_distribute_update
);
170 distribute_list_delete_hook (babel_routing_process
->distribute_ctx
, babel_distribute_update
);
173 XFREE(MTYPE_BABEL
, babel_routing_process
);
177 /* thread reading entries form others babel daemons */
179 babel_read_protocol (struct thread
*thread
)
182 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
183 struct interface
*ifp
= NULL
;
184 struct sockaddr_in6 sin6
;
186 assert(babel_routing_process
!= NULL
);
187 assert(protocol_socket
>= 0);
189 rc
= babel_recv(protocol_socket
,
190 receive_buffer
, receive_buffer_size
,
191 (struct sockaddr
*)&sin6
, sizeof(sin6
));
193 if(errno
!= EAGAIN
&& errno
!= EINTR
) {
194 flog_err_sys(EC_LIB_SOCKET
, "recv: %s", safe_strerror(errno
));
197 FOR_ALL_INTERFACES(vrf
, ifp
) {
200 if(ifp
->ifindex
== (ifindex_t
)sin6
.sin6_scope_id
) {
201 parse_packet((unsigned char*)&sin6
.sin6_addr
, ifp
,
209 thread_add_read(master
, &babel_read_protocol
, NULL
, protocol_socket
, &babel_routing_process
->t_read
);
213 /* Zebra will give some information, especially about interfaces. This function
214 must be call with a litte timeout wich may give zebra the time to do his job,
215 making these inits have sense. */
217 babel_init_routing_process(struct thread
*thread
)
219 myseqno
= (frr_weak_random() & 0xFFFF);
221 babel_load_state_file();
222 debugf(BABEL_DEBUG_COMMON
, "My ID is : %s.", format_eui64(myid
));
223 babel_initial_noise();
224 babel_main_loop(thread
);/* this function self-add to the t_update thread */
228 /* fill "myid" with an unique id (only if myid != {0}). */
232 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
233 struct interface
*ifp
= NULL
;
237 /* if we already have an id (from state file), we return. */
238 if (memcmp(myid
, zeroes
, 8) != 0) {
242 FOR_ALL_INTERFACES(vrf
, ifp
) {
243 /* ifp->ifindex is not necessarily valid at this point */
244 int ifindex
= if_nametoindex(ifp
->name
);
246 unsigned char eui
[8];
247 rc
= if_eui64(ifindex
, eui
);
250 memcpy(myid
, eui
, 8);
255 /* We failed to get a global EUI64 from the interfaces we were given.
256 Let's try to find an interface with a MAC address. */
257 for(i
= 1; i
< 256; i
++) {
258 char buf
[IF_NAMESIZE
], *ifname
;
259 unsigned char eui
[8];
260 ifname
= if_indextoname(i
, buf
);
263 rc
= if_eui64(i
, eui
);
266 memcpy(myid
, eui
, 8);
270 flog_err(EC_BABEL_CONFIG
, "Couldn't find router id -- using random value.");
272 rc
= read_random_bytes(myid
, 8);
274 flog_err(EC_BABEL_CONFIG
, "read(random): %s (cannot assign an ID)",
275 safe_strerror(errno
));
278 /* Clear group and global bits */
282 /* Make some noise so that others notice us, and send retractions in
283 case we were restarted recently */
285 babel_initial_noise(void)
287 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
288 struct interface
*ifp
= NULL
;
290 FOR_ALL_INTERFACES(vrf
, ifp
) {
293 /* Apply jitter before we send the first message. */
294 usleep(roughly(10000));
297 send_wildcard_retraction(ifp
);
300 FOR_ALL_INTERFACES(vrf
, ifp
) {
303 usleep(roughly(10000));
306 send_wildcard_retraction(ifp
);
307 send_self_update(ifp
);
308 send_request(ifp
, NULL
, 0);
314 /* Delete all the added babel routes, make babeld only speak to zebra. */
316 babel_clean_routing_process(void)
319 babel_interface_close_all();
322 thread_cancel(&babel_routing_process
->t_read
);
323 thread_cancel(&babel_routing_process
->t_update
);
325 distribute_list_delete(&babel_routing_process
->distribute_ctx
);
326 XFREE(MTYPE_BABEL
, babel_routing_process
);
329 /* Function used with timeout. */
331 babel_main_loop(struct thread
*thread
)
334 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
335 struct interface
*ifp
= NULL
;
340 /* timeouts --------------------------------------------------------- */
341 /* get the next timeout */
342 babel_fill_with_next_timeout(&tv
);
343 /* if there is no timeout, we must wait. */
344 if(timeval_compare(&tv
, &babel_now
) > 0) {
345 timeval_minus(&tv
, &tv
, &babel_now
);
346 debugf(BABEL_DEBUG_TIMEOUT
, "babel main loop : timeout: %lld msecs",
347 (long long)tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000);
348 /* it happens often to have less than 1 ms, it's bad. */
349 timeval_add_msec(&tv
, &tv
, 300);
350 babel_set_timer(&tv
);
356 /* update database -------------------------------------------------- */
357 if(timeval_compare(&check_neighbours_timeout
, &babel_now
) < 0) {
359 msecs
= check_neighbours();
360 /* Multiply by 3/2 to allow neighbours to expire. */
361 msecs
= MAX(3 * msecs
/ 2, 10);
362 schedule_neighbours_check(msecs
, 1);
365 if(babel_now
.tv_sec
>= expiry_time
) {
368 expiry_time
= babel_now
.tv_sec
+ roughly(30);
371 if(babel_now
.tv_sec
>= source_expiry_time
) {
373 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
376 FOR_ALL_INTERFACES(vrf
, ifp
) {
377 babel_interface_nfo
*babel_ifp
= NULL
;
380 babel_ifp
= babel_get_if_nfo(ifp
);
381 if(timeval_compare(&babel_now
, &babel_ifp
->hello_timeout
) >= 0)
383 if(timeval_compare(&babel_now
, &babel_ifp
->update_timeout
) >= 0)
384 send_update(ifp
, 0, NULL
, 0);
385 if(timeval_compare(&babel_now
,
386 &babel_ifp
->update_flush_timeout
) >= 0)
390 if(resend_time
.tv_sec
!= 0) {
391 if(timeval_compare(&babel_now
, &resend_time
) >= 0)
395 if(unicast_flush_timeout
.tv_sec
!= 0) {
396 if(timeval_compare(&babel_now
, &unicast_flush_timeout
) >= 0)
400 FOR_ALL_INTERFACES(vrf
, ifp
) {
401 babel_interface_nfo
*babel_ifp
= NULL
;
404 babel_ifp
= babel_get_if_nfo(ifp
);
405 if(babel_ifp
->flush_timeout
.tv_sec
!= 0) {
406 if(timeval_compare(&babel_now
, &babel_ifp
->flush_timeout
) >= 0)
412 assert(0); /* this line should never be reach */
417 printIfMin(struct timeval
*tv
, int cmd
, const char *tag
, const char *ifname
)
419 static struct timeval curr_tv
;
420 static char buffer
[200];
421 static const char *curr_tag
= NULL
;
424 case 0: /* reset timeval */
427 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
433 case 1: /* take the min */
434 if (tv
->tv_sec
== 0 && tv
->tv_usec
== 0) { /* if (tv == ∞) */
437 if (tv
->tv_sec
< curr_tv
.tv_sec
||(tv
->tv_sec
== curr_tv
.tv_sec
&&
438 tv
->tv_usec
< curr_tv
.tv_usec
)) {
441 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
448 case 2: /* print message */
449 debugf(BABEL_DEBUG_TIMEOUT
, "next timeout due to: %s", curr_tag
);
457 babel_fill_with_next_timeout(struct timeval
*tv
)
459 #if (defined NO_DEBUG)
460 #define printIfMin(a,b,c,d)
462 #define printIfMin(a,b,c,d) \
463 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
465 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
466 struct interface
*ifp
= NULL
;
468 *tv
= check_neighbours_timeout
;
469 printIfMin(tv
, 0, "check_neighbours_timeout", NULL
);
470 timeval_min_sec(tv
, expiry_time
);
471 printIfMin(tv
, 1, "expiry_time", NULL
);
472 timeval_min_sec(tv
, source_expiry_time
);
473 printIfMin(tv
, 1, "source_expiry_time", NULL
);
474 timeval_min(tv
, &resend_time
);
475 printIfMin(tv
, 1, "resend_time", NULL
);
476 FOR_ALL_INTERFACES(vrf
, ifp
) {
477 babel_interface_nfo
*babel_ifp
= NULL
;
480 babel_ifp
= babel_get_if_nfo(ifp
);
481 timeval_min(tv
, &babel_ifp
->flush_timeout
);
482 printIfMin(tv
, 1, "flush_timeout", ifp
->name
);
483 timeval_min(tv
, &babel_ifp
->hello_timeout
);
484 printIfMin(tv
, 1, "hello_timeout", ifp
->name
);
485 timeval_min(tv
, &babel_ifp
->update_timeout
);
486 printIfMin(tv
, 1, "update_timeout", ifp
->name
);
487 timeval_min(tv
, &babel_ifp
->update_flush_timeout
);
488 printIfMin(tv
, 1, "update_flush_timeout",ifp
->name
);
490 timeval_min(tv
, &unicast_flush_timeout
);
491 printIfMin(tv
, 1, "unicast_flush_timeout", NULL
);
492 printIfMin(tv
, 2, NULL
, NULL
);
497 /* set the t_update thread of the babel routing process to be launch in
498 'timeout' (approximate at the milisecond) */
500 babel_set_timer(struct timeval
*timeout
)
502 long msecs
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
503 thread_cancel(&(babel_routing_process
->t_update
));
504 thread_add_timer_msec(master
, babel_main_loop
, NULL
, msecs
, &babel_routing_process
->t_update
);
508 schedule_neighbours_check(int msecs
, int override
)
510 struct timeval timeout
;
512 timeval_add_msec(&timeout
, &babel_now
, msecs
);
514 check_neighbours_timeout
= timeout
;
516 timeval_min(&check_neighbours_timeout
, &timeout
);
520 resize_receive_buffer(int size
)
522 if(size
<= receive_buffer_size
)
525 if(receive_buffer
== NULL
) {
526 receive_buffer
= malloc(size
);
527 if(receive_buffer
== NULL
) {
528 flog_err(EC_BABEL_MEMORY
, "malloc(receive_buffer): %s",
529 safe_strerror(errno
));
532 receive_buffer_size
= size
;
535 new = realloc(receive_buffer
, size
);
537 flog_err(EC_BABEL_MEMORY
, "realloc(receive_buffer): %s",
538 safe_strerror(errno
));
541 receive_buffer
= new;
542 receive_buffer_size
= size
;
548 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
)
550 struct interface
*ifp
;
551 babel_interface_nfo
*babel_ifp
;
558 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
562 babel_ifp
= babel_get_if_nfo(ifp
);
564 for (type
= 0; type
< DISTRIBUTE_MAX
; type
++) {
565 family
= type
== DISTRIBUTE_V4_IN
|| type
== DISTRIBUTE_V4_OUT
?
567 if (dist
->list
[type
])
568 babel_ifp
->list
[type
] = access_list_lookup (family
,
571 babel_ifp
->list
[type
] = NULL
;
572 if (dist
->prefix
[type
])
573 babel_ifp
->prefix
[type
] = prefix_list_lookup (family
,
576 babel_ifp
->prefix
[type
] = NULL
;
581 babel_distribute_update_interface (struct interface
*ifp
)
583 struct distribute
*dist
= NULL
;
585 if (babel_routing_process
)
586 dist
= distribute_lookup(babel_routing_process
->distribute_ctx
, ifp
->name
);
588 babel_distribute_update (babel_routing_process
->distribute_ctx
, dist
);
591 /* Update all interface's distribute list. */
593 babel_distribute_update_all (struct prefix_list
*notused
)
595 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
596 struct interface
*ifp
;
598 FOR_ALL_INTERFACES (vrf
, ifp
)
599 babel_distribute_update_interface (ifp
);
603 babel_distribute_update_all_wrapper (struct access_list
*notused
)
605 babel_distribute_update_all(NULL
);
610 DEFUN_NOSH (router_babel
,
613 "Enable a routing process\n"
614 "Make Babel instance command\n")
618 vty
->node
= BABEL_NODE
;
620 if (!babel_routing_process
) {
621 ret
= babel_create_routing_process ();
623 /* Notice to user we couldn't create Babel. */
625 zlog_warn ("can't create Babel");
634 DEFUN (no_router_babel
,
638 "Disable a routing process\n"
639 "Remove Babel instance command\n")
641 if(babel_routing_process
)
642 babel_clean_routing_process();
646 /* [Babel Command] */
647 DEFUN (babel_diversity
,
651 "Enable diversity-aware routing.\n")
653 diversity_kind
= DIVERSITY_CHANNEL
;
657 /* [Babel Command] */
658 DEFUN (no_babel_diversity
,
659 no_babel_diversity_cmd
,
660 "no babel diversity",
663 "Disable diversity-aware routing.\n")
665 diversity_kind
= DIVERSITY_NONE
;
669 /* [Babel Command] */
670 DEFUN (babel_diversity_factor
,
671 babel_diversity_factor_cmd
,
672 "babel diversity-factor (1-256)",
674 "Set the diversity factor.\n"
675 "Factor in units of 1/256.\n")
679 factor
= strtoul(argv
[2]->arg
, NULL
, 10);
681 diversity_factor
= factor
;
685 /* [Babel Command] */
686 DEFUN (babel_set_resend_delay
,
687 babel_set_resend_delay_cmd
,
688 "babel resend-delay (20-655340)",
690 "Time before resending a message\n"
695 interval
= strtoul(argv
[2]->arg
, NULL
, 10);
697 resend_delay
= interval
;
701 /* [Babel Command] */
702 DEFUN (babel_set_smoothing_half_life
,
703 babel_set_smoothing_half_life_cmd
,
704 "babel smoothing-half-life (0-65534)",
706 "Smoothing half-life\n"
707 "Seconds (0 to disable)\n")
711 seconds
= strtoul(argv
[2]->arg
, NULL
, 10);
713 change_smoothing_half_life(seconds
);
717 DEFUN (babel_distribute_list
,
718 babel_distribute_list_cmd
,
719 "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
720 "Filter networks in routing updates\n"
723 "Filter incoming routing updates\n"
724 "Filter outgoing routing updates\n"
727 const char *ifname
= NULL
;
728 int prefix
= (argv
[1]->type
== WORD_TKN
) ? 1 : 0;
730 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
731 ifname
= argv
[argc
- 1]->arg
;
733 return distribute_list_parser(prefix
, true, argv
[2 + prefix
]->text
,
734 argv
[1 + prefix
]->arg
, ifname
);
737 DEFUN (babel_no_distribute_list
,
738 babel_no_distribute_list_cmd
,
739 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
741 "Filter networks in routing updates\n"
744 "Filter incoming routing updates\n"
745 "Filter outgoing routing updates\n"
748 const char *ifname
= NULL
;
749 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
751 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
752 ifname
= argv
[argc
- 1]->arg
;
754 return distribute_list_no_parser(vty
, prefix
, true,
755 argv
[3 + prefix
]->text
,
756 argv
[2 + prefix
]->arg
, ifname
);
759 DEFUN (babel_ipv6_distribute_list
,
760 babel_ipv6_distribute_list_cmd
,
761 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
763 "Filter networks in routing updates\n"
766 "Filter incoming routing updates\n"
767 "Filter outgoing routing updates\n"
770 const char *ifname
= NULL
;
771 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
773 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
774 ifname
= argv
[argc
- 1]->arg
;
776 return distribute_list_parser(prefix
, false, argv
[3 + prefix
]->text
,
777 argv
[2 + prefix
]->arg
, ifname
);
780 DEFUN (babel_no_ipv6_distribute_list
,
781 babel_no_ipv6_distribute_list_cmd
,
782 "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
785 "Filter networks in routing updates\n"
788 "Filter incoming routing updates\n"
789 "Filter outgoing routing updates\n"
792 const char *ifname
= NULL
;
793 int prefix
= (argv
[3]->type
== WORD_TKN
) ? 1 : 0;
795 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
796 ifname
= argv
[argc
- 1]->arg
;
798 return distribute_list_no_parser(vty
, prefix
, false,
799 argv
[4 + prefix
]->text
,
800 argv
[3 + prefix
]->arg
, ifname
);
804 babeld_quagga_init(void)
807 install_node(&cmd_babel_node
);
809 install_element(CONFIG_NODE
, &router_babel_cmd
);
810 install_element(CONFIG_NODE
, &no_router_babel_cmd
);
812 install_default(BABEL_NODE
);
813 install_element(BABEL_NODE
, &babel_diversity_cmd
);
814 install_element(BABEL_NODE
, &no_babel_diversity_cmd
);
815 install_element(BABEL_NODE
, &babel_diversity_factor_cmd
);
816 install_element(BABEL_NODE
, &babel_set_resend_delay_cmd
);
817 install_element(BABEL_NODE
, &babel_set_smoothing_half_life_cmd
);
819 install_element(BABEL_NODE
, &babel_distribute_list_cmd
);
820 install_element(BABEL_NODE
, &babel_no_distribute_list_cmd
);
821 install_element(BABEL_NODE
, &babel_ipv6_distribute_list_cmd
);
822 install_element(BABEL_NODE
, &babel_no_ipv6_distribute_list_cmd
);
828 /* Access list install. */
830 access_list_add_hook (babel_distribute_update_all_wrapper
);
831 access_list_delete_hook (babel_distribute_update_all_wrapper
);
833 /* Prefix list initialize.*/
835 prefix_list_add_hook (babel_distribute_update_all
);
836 prefix_list_delete_hook (babel_distribute_update_all
);
839 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
842 input_filter(const unsigned char *id
,
843 const unsigned char *prefix
, unsigned short plen
,
844 const unsigned char *neigh
, unsigned int ifindex
)
846 return babel_filter(0, prefix
, plen
, ifindex
);
850 output_filter(const unsigned char *id
, const unsigned char *prefix
,
851 unsigned short plen
, unsigned int ifindex
)
853 return babel_filter(1, prefix
, plen
, ifindex
);
856 /* There's no redistribute filter in Quagga -- the zebra daemon does its
859 redistribute_filter(const unsigned char *prefix
, unsigned short plen
,
860 unsigned int ifindex
, int proto
)
865 struct babel
*babel_lookup(void)
867 return babel_routing_process
;