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"
36 #include "babel_main.h"
41 #include "babel_interface.h"
42 #include "neighbour.h"
46 #include "babel_filter.h"
47 #include "babel_zebra.h"
48 #include "babel_errors.h"
50 DEFINE_MGROUP(BABELD
, "babeld");
51 DEFINE_MTYPE_STATIC(BABELD
, BABEL
, "Babel Structure");
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
);
61 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
);
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;
69 struct timeval check_neighbours_timeout
;
70 static time_t expiry_time
;
71 static time_t source_expiry_time
;
73 /* Babel node structure. */
74 static int babel_config_write (struct vty
*vty
);
75 static struct cmd_node cmd_babel_node
=
79 .parent_node
= CONFIG_NODE
,
80 .prompt
= "%s(config-router)# ",
81 .config_write
= babel_config_write
,
84 /* print current babel configuration on vty */
86 babel_config_write (struct vty
*vty
)
92 /* list enabled debug modes */
93 lines
+= debug_babel_config_write (vty
);
95 if (!babel_routing_process
)
97 vty_out (vty
, "router babel\n");
98 if (diversity_kind
!= DIVERSITY_NONE
)
100 vty_out (vty
, " babel diversity\n");
103 if (diversity_factor
!= BABEL_DEFAULT_DIVERSITY_FACTOR
)
105 vty_out (vty
, " babel diversity-factor %d\n",diversity_factor
);
108 if (resend_delay
!= BABEL_DEFAULT_RESEND_DELAY
)
110 vty_out (vty
, " babel resend-delay %u\n", resend_delay
);
113 if (smoothing_half_life
!= BABEL_DEFAULT_SMOOTHING_HALF_LIFE
)
115 vty_out (vty
, " babel smoothing-half-life %u\n",
116 smoothing_half_life
);
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
));
134 lines
+= config_write_distribute (vty
, babel_routing_process
->distribute_ctx
);
136 vty_out (vty
, "exit\n");
143 babel_create_routing_process (void)
145 assert (babel_routing_process
== NULL
);
147 /* Allocaste Babel instance. */
148 babel_routing_process
= XCALLOC(MTYPE_BABEL
, sizeof(struct babel
));
150 /* Initialize timeouts */
152 expiry_time
= babel_now
.tv_sec
+ roughly(30);
153 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
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
));
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
);
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
);
174 XFREE(MTYPE_BABEL
, babel_routing_process
);
178 /* thread reading entries form others babel daemons */
179 static void 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
);
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
)
217 myseqno
= (frr_weak_random() & 0xFFFF);
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 */
225 /* fill "myid" with an unique id (only if myid != {0}). */
229 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
230 struct interface
*ifp
= NULL
;
234 /* if we already have an id (from state file), we return. */
235 if (memcmp(myid
, zeroes
, 8) != 0) {
239 FOR_ALL_INTERFACES(vrf
, ifp
) {
240 /* ifp->ifindex is not necessarily valid at this point */
241 int ifindex
= if_nametoindex(ifp
->name
);
243 unsigned char eui
[8];
244 rc
= if_eui64(ifindex
, eui
);
247 memcpy(myid
, eui
, 8);
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
);
260 rc
= if_eui64(i
, eui
);
263 memcpy(myid
, eui
, 8);
267 flog_err(EC_BABEL_CONFIG
, "Couldn't find router id -- using random value.");
269 rc
= read_random_bytes(myid
, 8);
271 flog_err(EC_BABEL_CONFIG
, "read(random): %s (cannot assign an ID)",
272 safe_strerror(errno
));
275 /* Clear group and global bits */
279 /* Make some noise so that others notice us, and send retractions in
280 case we were restarted recently */
282 babel_initial_noise(void)
284 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
285 struct interface
*ifp
= NULL
;
287 FOR_ALL_INTERFACES(vrf
, ifp
) {
290 /* Apply jitter before we send the first message. */
291 usleep(roughly(10000));
294 send_wildcard_retraction(ifp
);
297 FOR_ALL_INTERFACES(vrf
, ifp
) {
300 usleep(roughly(10000));
303 send_wildcard_retraction(ifp
);
304 send_self_update(ifp
);
305 send_request(ifp
, NULL
, 0);
311 /* Delete all the added babel routes, make babeld only speak to zebra. */
313 babel_clean_routing_process(void)
316 babel_interface_close_all();
319 thread_cancel(&babel_routing_process
->t_read
);
320 thread_cancel(&babel_routing_process
->t_update
);
322 distribute_list_delete(&babel_routing_process
->distribute_ctx
);
323 XFREE(MTYPE_BABEL
, babel_routing_process
);
326 /* Function used with timeout. */
327 static void babel_main_loop(struct thread
*thread
)
330 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
331 struct interface
*ifp
= NULL
;
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
);
352 /* update database -------------------------------------------------- */
353 if(timeval_compare(&check_neighbours_timeout
, &babel_now
) < 0) {
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);
361 if(babel_now
.tv_sec
>= expiry_time
) {
364 expiry_time
= babel_now
.tv_sec
+ roughly(30);
367 if(babel_now
.tv_sec
>= source_expiry_time
) {
369 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
372 FOR_ALL_INTERFACES(vrf
, ifp
) {
373 babel_interface_nfo
*babel_ifp
= NULL
;
376 babel_ifp
= babel_get_if_nfo(ifp
);
377 if(timeval_compare(&babel_now
, &babel_ifp
->hello_timeout
) >= 0)
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)
386 if(resend_time
.tv_sec
!= 0) {
387 if(timeval_compare(&babel_now
, &resend_time
) >= 0)
391 if(unicast_flush_timeout
.tv_sec
!= 0) {
392 if(timeval_compare(&babel_now
, &unicast_flush_timeout
) >= 0)
396 FOR_ALL_INTERFACES(vrf
, ifp
) {
397 babel_interface_nfo
*babel_ifp
= NULL
;
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)
408 assert(0); /* this line should never be reach */
412 printIfMin(struct timeval
*tv
, int cmd
, const char *tag
, const char *ifname
)
414 static struct timeval curr_tv
;
415 static char buffer
[200];
416 static const char *curr_tag
= NULL
;
419 case 0: /* reset timeval */
422 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
428 case 1: /* take the min */
429 if (tv
->tv_sec
== 0 && tv
->tv_usec
== 0) { /* if (tv == ∞) */
432 if (tv
->tv_sec
< curr_tv
.tv_sec
||(tv
->tv_sec
== curr_tv
.tv_sec
&&
433 tv
->tv_usec
< curr_tv
.tv_usec
)) {
436 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
443 case 2: /* print message */
444 debugf(BABEL_DEBUG_TIMEOUT
, "next timeout due to: %s", curr_tag
);
452 babel_fill_with_next_timeout(struct timeval
*tv
)
454 #if (defined NO_DEBUG)
455 #define printIfMin(a,b,c,d)
457 #define printIfMin(a,b,c,d) \
458 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
460 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
461 struct interface
*ifp
= NULL
;
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
;
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
);
485 timeval_min(tv
, &unicast_flush_timeout
);
486 printIfMin(tv
, 1, "unicast_flush_timeout", NULL
);
487 printIfMin(tv
, 2, NULL
, NULL
);
492 /* set the t_update thread of the babel routing process to be launch in
493 'timeout' (approximate at the milisecond) */
495 babel_set_timer(struct timeval
*timeout
)
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
);
503 schedule_neighbours_check(int msecs
, int override
)
505 struct timeval timeout
;
507 timeval_add_msec(&timeout
, &babel_now
, msecs
);
509 check_neighbours_timeout
= timeout
;
511 timeval_min(&check_neighbours_timeout
, &timeout
);
515 resize_receive_buffer(int size
)
517 if(size
<= receive_buffer_size
)
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
));
527 receive_buffer_size
= size
;
530 new = realloc(receive_buffer
, size
);
532 flog_err(EC_BABEL_MEMORY
, "realloc(receive_buffer): %s",
533 safe_strerror(errno
));
536 receive_buffer
= new;
537 receive_buffer_size
= size
;
543 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
)
545 struct interface
*ifp
;
546 babel_interface_nfo
*babel_ifp
;
553 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
557 babel_ifp
= babel_get_if_nfo(ifp
);
559 for (type
= 0; type
< DISTRIBUTE_MAX
; type
++) {
560 family
= type
== DISTRIBUTE_V4_IN
|| type
== DISTRIBUTE_V4_OUT
?
562 if (dist
->list
[type
])
563 babel_ifp
->list
[type
] = access_list_lookup (family
,
566 babel_ifp
->list
[type
] = NULL
;
567 if (dist
->prefix
[type
])
568 babel_ifp
->prefix
[type
] = prefix_list_lookup (family
,
571 babel_ifp
->prefix
[type
] = NULL
;
576 babel_distribute_update_interface (struct interface
*ifp
)
578 struct distribute
*dist
= NULL
;
580 if (babel_routing_process
)
581 dist
= distribute_lookup(babel_routing_process
->distribute_ctx
, ifp
->name
);
583 babel_distribute_update (babel_routing_process
->distribute_ctx
, dist
);
586 /* Update all interface's distribute list. */
588 babel_distribute_update_all (struct prefix_list
*notused
)
590 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
591 struct interface
*ifp
;
593 FOR_ALL_INTERFACES (vrf
, ifp
)
594 babel_distribute_update_interface (ifp
);
598 babel_distribute_update_all_wrapper (struct access_list
*notused
)
600 babel_distribute_update_all(NULL
);
605 DEFUN_NOSH (router_babel
,
608 "Enable a routing process\n"
609 "Make Babel instance command\n")
613 vty
->node
= BABEL_NODE
;
615 if (!babel_routing_process
) {
616 ret
= babel_create_routing_process ();
618 /* Notice to user we couldn't create Babel. */
620 zlog_warn ("can't create Babel");
629 DEFUN (no_router_babel
,
633 "Disable a routing process\n"
634 "Remove Babel instance command\n")
636 if(babel_routing_process
)
637 babel_clean_routing_process();
641 /* [Babel Command] */
642 DEFUN (babel_diversity
,
646 "Enable diversity-aware routing.\n")
648 diversity_kind
= DIVERSITY_CHANNEL
;
652 /* [Babel Command] */
653 DEFUN (no_babel_diversity
,
654 no_babel_diversity_cmd
,
655 "no babel diversity",
658 "Disable diversity-aware routing.\n")
660 diversity_kind
= DIVERSITY_NONE
;
664 /* [Babel Command] */
665 DEFUN (babel_diversity_factor
,
666 babel_diversity_factor_cmd
,
667 "babel diversity-factor (1-256)",
669 "Set the diversity factor.\n"
670 "Factor in units of 1/256.\n")
674 factor
= strtoul(argv
[2]->arg
, NULL
, 10);
676 diversity_factor
= factor
;
680 /* [Babel Command] */
681 DEFUN (babel_set_resend_delay
,
682 babel_set_resend_delay_cmd
,
683 "babel resend-delay (20-655340)",
685 "Time before resending a message\n"
690 interval
= strtoul(argv
[2]->arg
, NULL
, 10);
692 resend_delay
= interval
;
696 /* [Babel Command] */
697 DEFUN (babel_set_smoothing_half_life
,
698 babel_set_smoothing_half_life_cmd
,
699 "babel smoothing-half-life (0-65534)",
701 "Smoothing half-life\n"
702 "Seconds (0 to disable)\n")
706 seconds
= strtoul(argv
[2]->arg
, NULL
, 10);
708 change_smoothing_half_life(seconds
);
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"
718 "Filter incoming routing updates\n"
719 "Filter outgoing routing updates\n"
722 const char *ifname
= NULL
;
723 int prefix
= (argv
[1]->type
== WORD_TKN
) ? 1 : 0;
725 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
726 ifname
= argv
[argc
- 1]->arg
;
728 return distribute_list_parser(prefix
, true, argv
[2 + prefix
]->text
,
729 argv
[1 + prefix
]->arg
, ifname
);
732 DEFUN (babel_no_distribute_list
,
733 babel_no_distribute_list_cmd
,
734 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
736 "Filter networks in routing updates\n"
739 "Filter incoming routing updates\n"
740 "Filter outgoing routing updates\n"
743 const char *ifname
= NULL
;
744 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
746 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
747 ifname
= argv
[argc
- 1]->arg
;
749 return distribute_list_no_parser(vty
, prefix
, true,
750 argv
[3 + prefix
]->text
,
751 argv
[2 + prefix
]->arg
, ifname
);
754 DEFUN (babel_ipv6_distribute_list
,
755 babel_ipv6_distribute_list_cmd
,
756 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
758 "Filter networks in routing updates\n"
761 "Filter incoming routing updates\n"
762 "Filter outgoing routing updates\n"
765 const char *ifname
= NULL
;
766 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
768 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
769 ifname
= argv
[argc
- 1]->arg
;
771 return distribute_list_parser(prefix
, false, argv
[3 + prefix
]->text
,
772 argv
[2 + prefix
]->arg
, ifname
);
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]",
780 "Filter networks in routing updates\n"
783 "Filter incoming routing updates\n"
784 "Filter outgoing routing updates\n"
787 const char *ifname
= NULL
;
788 int prefix
= (argv
[3]->type
== WORD_TKN
) ? 1 : 0;
790 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
791 ifname
= argv
[argc
- 1]->arg
;
793 return distribute_list_no_parser(vty
, prefix
, false,
794 argv
[4 + prefix
]->text
,
795 argv
[3 + prefix
]->arg
, ifname
);
799 babeld_quagga_init(void)
802 install_node(&cmd_babel_node
);
804 install_element(CONFIG_NODE
, &router_babel_cmd
);
805 install_element(CONFIG_NODE
, &no_router_babel_cmd
);
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
);
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
);
823 /* Access list install. */
825 access_list_add_hook (babel_distribute_update_all_wrapper
);
826 access_list_delete_hook (babel_distribute_update_all_wrapper
);
828 /* Prefix list initialize.*/
830 prefix_list_add_hook (babel_distribute_update_all
);
831 prefix_list_delete_hook (babel_distribute_update_all
);
834 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
837 input_filter(const unsigned char *id
,
838 const unsigned char *prefix
, unsigned short plen
,
839 const unsigned char *neigh
, unsigned int ifindex
)
841 return babel_filter(0, prefix
, plen
, ifindex
);
845 output_filter(const unsigned char *id
, const unsigned char *prefix
,
846 unsigned short plen
, unsigned int ifindex
)
848 return babel_filter(1, prefix
, plen
, ifindex
);
851 /* There's no redistribute filter in Quagga -- the zebra daemon does its
854 redistribute_filter(const unsigned char *prefix
, unsigned short plen
,
855 unsigned int ifindex
, int proto
)
860 struct babel
*babel_lookup(void)
862 return babel_routing_process
;