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 void babel_init_routing_process(struct thread
*thread
);
53 static void babel_get_myid(void);
54 static void babel_initial_noise(void);
55 static void babel_read_protocol(struct thread
*thread
);
56 static void 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 */
178 static void babel_read_protocol(struct thread
*thread
)
181 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
182 struct interface
*ifp
= NULL
;
183 struct sockaddr_in6 sin6
;
185 assert(babel_routing_process
!= NULL
);
186 assert(protocol_socket
>= 0);
188 rc
= babel_recv(protocol_socket
,
189 receive_buffer
, receive_buffer_size
,
190 (struct sockaddr
*)&sin6
, sizeof(sin6
));
192 if(errno
!= EAGAIN
&& errno
!= EINTR
) {
193 flog_err_sys(EC_LIB_SOCKET
, "recv: %s", safe_strerror(errno
));
196 FOR_ALL_INTERFACES(vrf
, ifp
) {
199 if(ifp
->ifindex
== (ifindex_t
)sin6
.sin6_scope_id
) {
200 parse_packet((unsigned char*)&sin6
.sin6_addr
, ifp
,
208 thread_add_read(master
, &babel_read_protocol
, NULL
, protocol_socket
, &babel_routing_process
->t_read
);
211 /* Zebra will give some information, especially about interfaces. This function
212 must be call with a litte timeout wich may give zebra the time to do his job,
213 making these inits have sense. */
214 static void babel_init_routing_process(struct thread
*thread
)
216 myseqno
= (frr_weak_random() & 0xFFFF);
218 babel_load_state_file();
219 debugf(BABEL_DEBUG_COMMON
, "My ID is : %s.", format_eui64(myid
));
220 babel_initial_noise();
221 babel_main_loop(thread
);/* this function self-add to the t_update thread */
224 /* fill "myid" with an unique id (only if myid != {0}). */
228 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
229 struct interface
*ifp
= NULL
;
233 /* if we already have an id (from state file), we return. */
234 if (memcmp(myid
, zeroes
, 8) != 0) {
238 FOR_ALL_INTERFACES(vrf
, ifp
) {
239 /* ifp->ifindex is not necessarily valid at this point */
240 int ifindex
= if_nametoindex(ifp
->name
);
242 unsigned char eui
[8];
243 rc
= if_eui64(ifindex
, eui
);
246 memcpy(myid
, eui
, 8);
251 /* We failed to get a global EUI64 from the interfaces we were given.
252 Let's try to find an interface with a MAC address. */
253 for(i
= 1; i
< 256; i
++) {
254 char buf
[IF_NAMESIZE
], *ifname
;
255 unsigned char eui
[8];
256 ifname
= if_indextoname(i
, buf
);
259 rc
= if_eui64(i
, eui
);
262 memcpy(myid
, eui
, 8);
266 flog_err(EC_BABEL_CONFIG
, "Couldn't find router id -- using random value.");
268 rc
= read_random_bytes(myid
, 8);
270 flog_err(EC_BABEL_CONFIG
, "read(random): %s (cannot assign an ID)",
271 safe_strerror(errno
));
274 /* Clear group and global bits */
278 /* Make some noise so that others notice us, and send retractions in
279 case we were restarted recently */
281 babel_initial_noise(void)
283 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
284 struct interface
*ifp
= NULL
;
286 FOR_ALL_INTERFACES(vrf
, ifp
) {
289 /* Apply jitter before we send the first message. */
290 usleep(roughly(10000));
293 send_wildcard_retraction(ifp
);
296 FOR_ALL_INTERFACES(vrf
, ifp
) {
299 usleep(roughly(10000));
302 send_wildcard_retraction(ifp
);
303 send_self_update(ifp
);
304 send_request(ifp
, NULL
, 0);
310 /* Delete all the added babel routes, make babeld only speak to zebra. */
312 babel_clean_routing_process(void)
315 babel_interface_close_all();
318 thread_cancel(&babel_routing_process
->t_read
);
319 thread_cancel(&babel_routing_process
->t_update
);
321 distribute_list_delete(&babel_routing_process
->distribute_ctx
);
322 XFREE(MTYPE_BABEL
, babel_routing_process
);
325 /* Function used with timeout. */
326 static void babel_main_loop(struct thread
*thread
)
329 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
330 struct interface
*ifp
= NULL
;
335 /* timeouts --------------------------------------------------------- */
336 /* get the next timeout */
337 babel_fill_with_next_timeout(&tv
);
338 /* if there is no timeout, we must wait. */
339 if(timeval_compare(&tv
, &babel_now
) > 0) {
340 timeval_minus(&tv
, &tv
, &babel_now
);
341 debugf(BABEL_DEBUG_TIMEOUT
, "babel main loop : timeout: %lld msecs",
342 (long long)tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000);
343 /* it happens often to have less than 1 ms, it's bad. */
344 timeval_add_msec(&tv
, &tv
, 300);
345 babel_set_timer(&tv
);
351 /* update database -------------------------------------------------- */
352 if(timeval_compare(&check_neighbours_timeout
, &babel_now
) < 0) {
354 msecs
= check_neighbours();
355 /* Multiply by 3/2 to allow neighbours to expire. */
356 msecs
= MAX(3 * msecs
/ 2, 10);
357 schedule_neighbours_check(msecs
, 1);
360 if(babel_now
.tv_sec
>= expiry_time
) {
363 expiry_time
= babel_now
.tv_sec
+ roughly(30);
366 if(babel_now
.tv_sec
>= source_expiry_time
) {
368 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
371 FOR_ALL_INTERFACES(vrf
, ifp
) {
372 babel_interface_nfo
*babel_ifp
= NULL
;
375 babel_ifp
= babel_get_if_nfo(ifp
);
376 if(timeval_compare(&babel_now
, &babel_ifp
->hello_timeout
) >= 0)
378 if(timeval_compare(&babel_now
, &babel_ifp
->update_timeout
) >= 0)
379 send_update(ifp
, 0, NULL
, 0);
380 if(timeval_compare(&babel_now
,
381 &babel_ifp
->update_flush_timeout
) >= 0)
385 if(resend_time
.tv_sec
!= 0) {
386 if(timeval_compare(&babel_now
, &resend_time
) >= 0)
390 if(unicast_flush_timeout
.tv_sec
!= 0) {
391 if(timeval_compare(&babel_now
, &unicast_flush_timeout
) >= 0)
395 FOR_ALL_INTERFACES(vrf
, ifp
) {
396 babel_interface_nfo
*babel_ifp
= NULL
;
399 babel_ifp
= babel_get_if_nfo(ifp
);
400 if(babel_ifp
->flush_timeout
.tv_sec
!= 0) {
401 if(timeval_compare(&babel_now
, &babel_ifp
->flush_timeout
) >= 0)
407 assert(0); /* this line should never be reach */
411 printIfMin(struct timeval
*tv
, int cmd
, const char *tag
, const char *ifname
)
413 static struct timeval curr_tv
;
414 static char buffer
[200];
415 static const char *curr_tag
= NULL
;
418 case 0: /* reset timeval */
421 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
427 case 1: /* take the min */
428 if (tv
->tv_sec
== 0 && tv
->tv_usec
== 0) { /* if (tv == ∞) */
431 if (tv
->tv_sec
< curr_tv
.tv_sec
||(tv
->tv_sec
== curr_tv
.tv_sec
&&
432 tv
->tv_usec
< curr_tv
.tv_usec
)) {
435 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
442 case 2: /* print message */
443 debugf(BABEL_DEBUG_TIMEOUT
, "next timeout due to: %s", curr_tag
);
451 babel_fill_with_next_timeout(struct timeval
*tv
)
453 #if (defined NO_DEBUG)
454 #define printIfMin(a,b,c,d)
456 #define printIfMin(a,b,c,d) \
457 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
459 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
460 struct interface
*ifp
= NULL
;
462 *tv
= check_neighbours_timeout
;
463 printIfMin(tv
, 0, "check_neighbours_timeout", NULL
);
464 timeval_min_sec(tv
, expiry_time
);
465 printIfMin(tv
, 1, "expiry_time", NULL
);
466 timeval_min_sec(tv
, source_expiry_time
);
467 printIfMin(tv
, 1, "source_expiry_time", NULL
);
468 timeval_min(tv
, &resend_time
);
469 printIfMin(tv
, 1, "resend_time", NULL
);
470 FOR_ALL_INTERFACES(vrf
, ifp
) {
471 babel_interface_nfo
*babel_ifp
= NULL
;
474 babel_ifp
= babel_get_if_nfo(ifp
);
475 timeval_min(tv
, &babel_ifp
->flush_timeout
);
476 printIfMin(tv
, 1, "flush_timeout", ifp
->name
);
477 timeval_min(tv
, &babel_ifp
->hello_timeout
);
478 printIfMin(tv
, 1, "hello_timeout", ifp
->name
);
479 timeval_min(tv
, &babel_ifp
->update_timeout
);
480 printIfMin(tv
, 1, "update_timeout", ifp
->name
);
481 timeval_min(tv
, &babel_ifp
->update_flush_timeout
);
482 printIfMin(tv
, 1, "update_flush_timeout",ifp
->name
);
484 timeval_min(tv
, &unicast_flush_timeout
);
485 printIfMin(tv
, 1, "unicast_flush_timeout", NULL
);
486 printIfMin(tv
, 2, NULL
, NULL
);
491 /* set the t_update thread of the babel routing process to be launch in
492 'timeout' (approximate at the milisecond) */
494 babel_set_timer(struct timeval
*timeout
)
496 long msecs
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
497 thread_cancel(&(babel_routing_process
->t_update
));
498 thread_add_timer_msec(master
, babel_main_loop
, NULL
, msecs
, &babel_routing_process
->t_update
);
502 schedule_neighbours_check(int msecs
, int override
)
504 struct timeval timeout
;
506 timeval_add_msec(&timeout
, &babel_now
, msecs
);
508 check_neighbours_timeout
= timeout
;
510 timeval_min(&check_neighbours_timeout
, &timeout
);
514 resize_receive_buffer(int size
)
516 if(size
<= receive_buffer_size
)
519 if(receive_buffer
== NULL
) {
520 receive_buffer
= malloc(size
);
521 if(receive_buffer
== NULL
) {
522 flog_err(EC_BABEL_MEMORY
, "malloc(receive_buffer): %s",
523 safe_strerror(errno
));
526 receive_buffer_size
= size
;
529 new = realloc(receive_buffer
, size
);
531 flog_err(EC_BABEL_MEMORY
, "realloc(receive_buffer): %s",
532 safe_strerror(errno
));
535 receive_buffer
= new;
536 receive_buffer_size
= size
;
542 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
)
544 struct interface
*ifp
;
545 babel_interface_nfo
*babel_ifp
;
552 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
556 babel_ifp
= babel_get_if_nfo(ifp
);
558 for (type
= 0; type
< DISTRIBUTE_MAX
; type
++) {
559 family
= type
== DISTRIBUTE_V4_IN
|| type
== DISTRIBUTE_V4_OUT
?
561 if (dist
->list
[type
])
562 babel_ifp
->list
[type
] = access_list_lookup (family
,
565 babel_ifp
->list
[type
] = NULL
;
566 if (dist
->prefix
[type
])
567 babel_ifp
->prefix
[type
] = prefix_list_lookup (family
,
570 babel_ifp
->prefix
[type
] = NULL
;
575 babel_distribute_update_interface (struct interface
*ifp
)
577 struct distribute
*dist
= NULL
;
579 if (babel_routing_process
)
580 dist
= distribute_lookup(babel_routing_process
->distribute_ctx
, ifp
->name
);
582 babel_distribute_update (babel_routing_process
->distribute_ctx
, dist
);
585 /* Update all interface's distribute list. */
587 babel_distribute_update_all (struct prefix_list
*notused
)
589 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
590 struct interface
*ifp
;
592 FOR_ALL_INTERFACES (vrf
, ifp
)
593 babel_distribute_update_interface (ifp
);
597 babel_distribute_update_all_wrapper (struct access_list
*notused
)
599 babel_distribute_update_all(NULL
);
604 DEFUN_NOSH (router_babel
,
607 "Enable a routing process\n"
608 "Make Babel instance command\n")
612 vty
->node
= BABEL_NODE
;
614 if (!babel_routing_process
) {
615 ret
= babel_create_routing_process ();
617 /* Notice to user we couldn't create Babel. */
619 zlog_warn ("can't create Babel");
628 DEFUN (no_router_babel
,
632 "Disable a routing process\n"
633 "Remove Babel instance command\n")
635 if(babel_routing_process
)
636 babel_clean_routing_process();
640 /* [Babel Command] */
641 DEFUN (babel_diversity
,
645 "Enable diversity-aware routing.\n")
647 diversity_kind
= DIVERSITY_CHANNEL
;
651 /* [Babel Command] */
652 DEFUN (no_babel_diversity
,
653 no_babel_diversity_cmd
,
654 "no babel diversity",
657 "Disable diversity-aware routing.\n")
659 diversity_kind
= DIVERSITY_NONE
;
663 /* [Babel Command] */
664 DEFUN (babel_diversity_factor
,
665 babel_diversity_factor_cmd
,
666 "babel diversity-factor (1-256)",
668 "Set the diversity factor.\n"
669 "Factor in units of 1/256.\n")
673 factor
= strtoul(argv
[2]->arg
, NULL
, 10);
675 diversity_factor
= factor
;
679 /* [Babel Command] */
680 DEFUN (babel_set_resend_delay
,
681 babel_set_resend_delay_cmd
,
682 "babel resend-delay (20-655340)",
684 "Time before resending a message\n"
689 interval
= strtoul(argv
[2]->arg
, NULL
, 10);
691 resend_delay
= interval
;
695 /* [Babel Command] */
696 DEFUN (babel_set_smoothing_half_life
,
697 babel_set_smoothing_half_life_cmd
,
698 "babel smoothing-half-life (0-65534)",
700 "Smoothing half-life\n"
701 "Seconds (0 to disable)\n")
705 seconds
= strtoul(argv
[2]->arg
, NULL
, 10);
707 change_smoothing_half_life(seconds
);
711 DEFUN (babel_distribute_list
,
712 babel_distribute_list_cmd
,
713 "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
714 "Filter networks in routing updates\n"
717 "Filter incoming routing updates\n"
718 "Filter outgoing routing updates\n"
721 const char *ifname
= NULL
;
722 int prefix
= (argv
[1]->type
== WORD_TKN
) ? 1 : 0;
724 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
725 ifname
= argv
[argc
- 1]->arg
;
727 return distribute_list_parser(prefix
, true, argv
[2 + prefix
]->text
,
728 argv
[1 + prefix
]->arg
, ifname
);
731 DEFUN (babel_no_distribute_list
,
732 babel_no_distribute_list_cmd
,
733 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
735 "Filter networks in routing updates\n"
738 "Filter incoming routing updates\n"
739 "Filter outgoing routing updates\n"
742 const char *ifname
= NULL
;
743 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
745 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
746 ifname
= argv
[argc
- 1]->arg
;
748 return distribute_list_no_parser(vty
, prefix
, true,
749 argv
[3 + prefix
]->text
,
750 argv
[2 + prefix
]->arg
, ifname
);
753 DEFUN (babel_ipv6_distribute_list
,
754 babel_ipv6_distribute_list_cmd
,
755 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
757 "Filter networks in routing updates\n"
760 "Filter incoming routing updates\n"
761 "Filter outgoing routing updates\n"
764 const char *ifname
= NULL
;
765 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
767 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
768 ifname
= argv
[argc
- 1]->arg
;
770 return distribute_list_parser(prefix
, false, argv
[3 + prefix
]->text
,
771 argv
[2 + prefix
]->arg
, ifname
);
774 DEFUN (babel_no_ipv6_distribute_list
,
775 babel_no_ipv6_distribute_list_cmd
,
776 "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
779 "Filter networks in routing updates\n"
782 "Filter incoming routing updates\n"
783 "Filter outgoing routing updates\n"
786 const char *ifname
= NULL
;
787 int prefix
= (argv
[3]->type
== WORD_TKN
) ? 1 : 0;
789 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
790 ifname
= argv
[argc
- 1]->arg
;
792 return distribute_list_no_parser(vty
, prefix
, false,
793 argv
[4 + prefix
]->text
,
794 argv
[3 + prefix
]->arg
, ifname
);
798 babeld_quagga_init(void)
801 install_node(&cmd_babel_node
);
803 install_element(CONFIG_NODE
, &router_babel_cmd
);
804 install_element(CONFIG_NODE
, &no_router_babel_cmd
);
806 install_default(BABEL_NODE
);
807 install_element(BABEL_NODE
, &babel_diversity_cmd
);
808 install_element(BABEL_NODE
, &no_babel_diversity_cmd
);
809 install_element(BABEL_NODE
, &babel_diversity_factor_cmd
);
810 install_element(BABEL_NODE
, &babel_set_resend_delay_cmd
);
811 install_element(BABEL_NODE
, &babel_set_smoothing_half_life_cmd
);
813 install_element(BABEL_NODE
, &babel_distribute_list_cmd
);
814 install_element(BABEL_NODE
, &babel_no_distribute_list_cmd
);
815 install_element(BABEL_NODE
, &babel_ipv6_distribute_list_cmd
);
816 install_element(BABEL_NODE
, &babel_no_ipv6_distribute_list_cmd
);
822 /* Access list install. */
824 access_list_add_hook (babel_distribute_update_all_wrapper
);
825 access_list_delete_hook (babel_distribute_update_all_wrapper
);
827 /* Prefix list initialize.*/
829 prefix_list_add_hook (babel_distribute_update_all
);
830 prefix_list_delete_hook (babel_distribute_update_all
);
833 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
836 input_filter(const unsigned char *id
,
837 const unsigned char *prefix
, unsigned short plen
,
838 const unsigned char *neigh
, unsigned int ifindex
)
840 return babel_filter(0, prefix
, plen
, ifindex
);
844 output_filter(const unsigned char *id
, const unsigned char *prefix
,
845 unsigned short plen
, unsigned int ifindex
)
847 return babel_filter(1, prefix
, plen
, ifindex
);
850 /* There's no redistribute filter in Quagga -- the zebra daemon does its
853 redistribute_filter(const unsigned char *prefix
, unsigned short plen
,
854 unsigned int ifindex
, int proto
)
859 struct babel
*babel_lookup(void)
861 return babel_routing_process
;