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 #ifndef VTYSH_EXTRACT_PL
51 #include "babeld/babeld_clippy.c"
54 DEFINE_MGROUP(BABELD
, "babeld");
55 DEFINE_MTYPE_STATIC(BABELD
, BABEL
, "Babel Structure");
57 static void babel_init_routing_process(struct thread
*thread
);
58 static void babel_get_myid(void);
59 static void babel_initial_noise(void);
60 static void babel_read_protocol(struct thread
*thread
);
61 static void babel_main_loop(struct thread
*thread
);
62 static void babel_set_timer(struct timeval
*timeout
);
63 static void babel_fill_with_next_timeout(struct timeval
*tv
);
65 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
);
67 /* Informations relative to the babel running daemon. */
68 static struct babel
*babel_routing_process
= NULL
;
69 static unsigned char *receive_buffer
= NULL
;
70 static int receive_buffer_size
= 0;
73 struct timeval check_neighbours_timeout
;
74 static time_t expiry_time
;
75 static time_t source_expiry_time
;
77 /* Babel node structure. */
78 static int babel_config_write (struct vty
*vty
);
79 static struct cmd_node cmd_babel_node
=
83 .parent_node
= CONFIG_NODE
,
84 .prompt
= "%s(config-router)# ",
85 .config_write
= babel_config_write
,
88 /* print current babel configuration on vty */
90 babel_config_write (struct vty
*vty
)
96 /* list enabled debug modes */
97 lines
+= debug_babel_config_write (vty
);
99 if (!babel_routing_process
)
101 vty_out (vty
, "router babel\n");
102 if (diversity_kind
!= DIVERSITY_NONE
)
104 vty_out (vty
, " babel diversity\n");
107 if (diversity_factor
!= BABEL_DEFAULT_DIVERSITY_FACTOR
)
109 vty_out (vty
, " babel diversity-factor %d\n",diversity_factor
);
112 if (resend_delay
!= BABEL_DEFAULT_RESEND_DELAY
)
114 vty_out (vty
, " babel resend-delay %u\n", resend_delay
);
117 if (smoothing_half_life
!= BABEL_DEFAULT_SMOOTHING_HALF_LIFE
)
119 vty_out (vty
, " babel smoothing-half-life %u\n",
120 smoothing_half_life
);
123 /* list enabled interfaces */
124 lines
= 1 + babel_enable_if_config_write (vty
);
125 /* list redistributed protocols */
126 for (afi
= AFI_IP
; afi
<= AFI_IP6
; afi
++) {
127 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
128 if (i
!= zclient
->redist_default
&&
129 vrf_bitmap_check (zclient
->redist
[afi
][i
], VRF_DEFAULT
)) {
130 vty_out (vty
, " redistribute %s %s\n",
131 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
132 zebra_route_string(i
));
138 lines
+= config_write_distribute (vty
, babel_routing_process
->distribute_ctx
);
140 vty_out (vty
, "exit\n");
147 babel_create_routing_process (void)
149 assert (babel_routing_process
== NULL
);
151 /* Allocaste Babel instance. */
152 babel_routing_process
= XCALLOC(MTYPE_BABEL
, sizeof(struct babel
));
154 /* Initialize timeouts */
156 expiry_time
= babel_now
.tv_sec
+ roughly(30);
157 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
159 /* Make socket for Babel protocol. */
160 protocol_socket
= babel_socket(protocol_port
);
161 if (protocol_socket
< 0) {
162 flog_err_sys(EC_LIB_SOCKET
, "Couldn't create link local socket: %s",
163 safe_strerror(errno
));
168 thread_add_read(master
, babel_read_protocol
, NULL
, protocol_socket
, &babel_routing_process
->t_read
);
169 /* wait a little: zebra will announce interfaces, addresses, routes... */
170 thread_add_timer_msec(master
, babel_init_routing_process
, NULL
, 200L, &babel_routing_process
->t_update
);
172 /* Distribute list install. */
173 babel_routing_process
->distribute_ctx
= distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT
));
174 distribute_list_add_hook (babel_routing_process
->distribute_ctx
, babel_distribute_update
);
175 distribute_list_delete_hook (babel_routing_process
->distribute_ctx
, babel_distribute_update
);
178 XFREE(MTYPE_BABEL
, babel_routing_process
);
182 /* thread reading entries form others babel daemons */
183 static void babel_read_protocol(struct thread
*thread
)
186 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
187 struct interface
*ifp
= NULL
;
188 struct sockaddr_in6 sin6
;
190 assert(babel_routing_process
!= NULL
);
191 assert(protocol_socket
>= 0);
193 rc
= babel_recv(protocol_socket
,
194 receive_buffer
, receive_buffer_size
,
195 (struct sockaddr
*)&sin6
, sizeof(sin6
));
197 if(errno
!= EAGAIN
&& errno
!= EINTR
) {
198 flog_err_sys(EC_LIB_SOCKET
, "recv: %s", safe_strerror(errno
));
201 FOR_ALL_INTERFACES(vrf
, ifp
) {
204 if(ifp
->ifindex
== (ifindex_t
)sin6
.sin6_scope_id
) {
205 parse_packet((unsigned char*)&sin6
.sin6_addr
, ifp
,
213 thread_add_read(master
, &babel_read_protocol
, NULL
, protocol_socket
, &babel_routing_process
->t_read
);
216 /* Zebra will give some information, especially about interfaces. This function
217 must be call with a litte timeout wich may give zebra the time to do his job,
218 making these inits have sense. */
219 static void babel_init_routing_process(struct thread
*thread
)
221 myseqno
= (frr_weak_random() & 0xFFFF);
223 babel_load_state_file();
224 debugf(BABEL_DEBUG_COMMON
, "My ID is : %s.", format_eui64(myid
));
225 babel_initial_noise();
226 babel_main_loop(thread
);/* this function self-add to the t_update thread */
229 /* fill "myid" with an unique id (only if myid != {0}). */
233 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
234 struct interface
*ifp
= NULL
;
238 /* if we already have an id (from state file), we return. */
239 if (memcmp(myid
, zeroes
, 8) != 0) {
243 FOR_ALL_INTERFACES(vrf
, ifp
) {
244 /* ifp->ifindex is not necessarily valid at this point */
245 int ifindex
= if_nametoindex(ifp
->name
);
247 unsigned char eui
[8];
248 rc
= if_eui64(ifindex
, eui
);
251 memcpy(myid
, eui
, 8);
256 /* We failed to get a global EUI64 from the interfaces we were given.
257 Let's try to find an interface with a MAC address. */
258 for(i
= 1; i
< 256; i
++) {
259 char buf
[INTERFACE_NAMSIZ
], *ifname
;
260 unsigned char eui
[8];
261 ifname
= if_indextoname(i
, buf
);
264 rc
= if_eui64(i
, eui
);
267 memcpy(myid
, eui
, 8);
271 flog_err(EC_BABEL_CONFIG
, "Couldn't find router id -- using random value.");
273 rc
= read_random_bytes(myid
, 8);
275 flog_err(EC_BABEL_CONFIG
, "read(random): %s (cannot assign an ID)",
276 safe_strerror(errno
));
279 /* Clear group and global bits */
283 /* Make some noise so that others notice us, and send retractions in
284 case we were restarted recently */
286 babel_initial_noise(void)
288 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
289 struct interface
*ifp
= NULL
;
291 FOR_ALL_INTERFACES(vrf
, ifp
) {
294 /* Apply jitter before we send the first message. */
295 usleep(roughly(10000));
298 send_wildcard_retraction(ifp
);
301 FOR_ALL_INTERFACES(vrf
, ifp
) {
304 usleep(roughly(10000));
307 send_wildcard_retraction(ifp
);
308 send_self_update(ifp
);
309 send_request(ifp
, NULL
, 0);
315 /* Delete all the added babel routes, make babeld only speak to zebra. */
317 babel_clean_routing_process(void)
320 babel_interface_close_all();
323 thread_cancel(&babel_routing_process
->t_read
);
324 thread_cancel(&babel_routing_process
->t_update
);
326 distribute_list_delete(&babel_routing_process
->distribute_ctx
);
327 XFREE(MTYPE_BABEL
, babel_routing_process
);
330 /* Function used with timeout. */
331 static void 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 */
416 printIfMin(struct timeval
*tv
, int cmd
, const char *tag
, const char *ifname
)
418 static struct timeval curr_tv
;
419 static char buffer
[200];
420 static const char *curr_tag
= NULL
;
423 case 0: /* reset timeval */
426 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
432 case 1: /* take the min */
433 if (tv
->tv_sec
== 0 && tv
->tv_usec
== 0) { /* if (tv == ∞) */
436 if (tv
->tv_sec
< curr_tv
.tv_sec
||(tv
->tv_sec
== curr_tv
.tv_sec
&&
437 tv
->tv_usec
< curr_tv
.tv_usec
)) {
440 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
447 case 2: /* print message */
448 debugf(BABEL_DEBUG_TIMEOUT
, "next timeout due to: %s", curr_tag
);
456 babel_fill_with_next_timeout(struct timeval
*tv
)
458 #if (defined NO_DEBUG)
459 #define printIfMin(a,b,c,d)
461 #define printIfMin(a,b,c,d) \
462 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
464 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
465 struct interface
*ifp
= NULL
;
467 *tv
= check_neighbours_timeout
;
468 printIfMin(tv
, 0, "check_neighbours_timeout", NULL
);
469 timeval_min_sec(tv
, expiry_time
);
470 printIfMin(tv
, 1, "expiry_time", NULL
);
471 timeval_min_sec(tv
, source_expiry_time
);
472 printIfMin(tv
, 1, "source_expiry_time", NULL
);
473 timeval_min(tv
, &resend_time
);
474 printIfMin(tv
, 1, "resend_time", NULL
);
475 FOR_ALL_INTERFACES(vrf
, ifp
) {
476 babel_interface_nfo
*babel_ifp
= NULL
;
479 babel_ifp
= babel_get_if_nfo(ifp
);
480 timeval_min(tv
, &babel_ifp
->flush_timeout
);
481 printIfMin(tv
, 1, "flush_timeout", ifp
->name
);
482 timeval_min(tv
, &babel_ifp
->hello_timeout
);
483 printIfMin(tv
, 1, "hello_timeout", ifp
->name
);
484 timeval_min(tv
, &babel_ifp
->update_timeout
);
485 printIfMin(tv
, 1, "update_timeout", ifp
->name
);
486 timeval_min(tv
, &babel_ifp
->update_flush_timeout
);
487 printIfMin(tv
, 1, "update_flush_timeout",ifp
->name
);
489 timeval_min(tv
, &unicast_flush_timeout
);
490 printIfMin(tv
, 1, "unicast_flush_timeout", NULL
);
491 printIfMin(tv
, 2, NULL
, NULL
);
496 /* set the t_update thread of the babel routing process to be launch in
497 'timeout' (approximate at the milisecond) */
499 babel_set_timer(struct timeval
*timeout
)
501 long msecs
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
502 thread_cancel(&(babel_routing_process
->t_update
));
503 thread_add_timer_msec(master
, babel_main_loop
, NULL
, msecs
, &babel_routing_process
->t_update
);
507 schedule_neighbours_check(int msecs
, int override
)
509 struct timeval timeout
;
511 timeval_add_msec(&timeout
, &babel_now
, msecs
);
513 check_neighbours_timeout
= timeout
;
515 timeval_min(&check_neighbours_timeout
, &timeout
);
519 resize_receive_buffer(int size
)
521 if(size
<= receive_buffer_size
)
524 if(receive_buffer
== NULL
) {
525 receive_buffer
= malloc(size
);
526 if(receive_buffer
== NULL
) {
527 flog_err(EC_BABEL_MEMORY
, "malloc(receive_buffer): %s",
528 safe_strerror(errno
));
531 receive_buffer_size
= size
;
534 new = realloc(receive_buffer
, size
);
536 flog_err(EC_BABEL_MEMORY
, "realloc(receive_buffer): %s",
537 safe_strerror(errno
));
540 receive_buffer
= new;
541 receive_buffer_size
= size
;
547 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
)
549 struct interface
*ifp
;
550 babel_interface_nfo
*babel_ifp
;
557 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
561 babel_ifp
= babel_get_if_nfo(ifp
);
563 for (type
= 0; type
< DISTRIBUTE_MAX
; type
++) {
564 family
= type
== DISTRIBUTE_V4_IN
|| type
== DISTRIBUTE_V4_OUT
?
566 if (dist
->list
[type
])
567 babel_ifp
->list
[type
] = access_list_lookup (family
,
570 babel_ifp
->list
[type
] = NULL
;
571 if (dist
->prefix
[type
])
572 babel_ifp
->prefix
[type
] = prefix_list_lookup (family
,
575 babel_ifp
->prefix
[type
] = NULL
;
580 babel_distribute_update_interface (struct interface
*ifp
)
582 struct distribute
*dist
= NULL
;
584 if (babel_routing_process
)
585 dist
= distribute_lookup(babel_routing_process
->distribute_ctx
, ifp
->name
);
587 babel_distribute_update (babel_routing_process
->distribute_ctx
, dist
);
590 /* Update all interface's distribute list. */
592 babel_distribute_update_all (struct prefix_list
*notused
)
594 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
595 struct interface
*ifp
;
597 FOR_ALL_INTERFACES (vrf
, ifp
)
598 babel_distribute_update_interface (ifp
);
602 babel_distribute_update_all_wrapper (struct access_list
*notused
)
604 babel_distribute_update_all(NULL
);
609 DEFUN_NOSH (router_babel
,
612 "Enable a routing process\n"
613 "Make Babel instance command\n")
617 vty
->node
= BABEL_NODE
;
619 if (!babel_routing_process
) {
620 ret
= babel_create_routing_process ();
622 /* Notice to user we couldn't create Babel. */
624 zlog_warn ("can't create Babel");
633 DEFUN (no_router_babel
,
637 "Disable a routing process\n"
638 "Remove Babel instance command\n")
640 if(babel_routing_process
)
641 babel_clean_routing_process();
645 /* [Babel Command] */
646 DEFUN (babel_diversity
,
650 "Enable diversity-aware routing.\n")
652 diversity_kind
= DIVERSITY_CHANNEL
;
656 /* [Babel Command] */
657 DEFUN (no_babel_diversity
,
658 no_babel_diversity_cmd
,
659 "no babel diversity",
662 "Disable diversity-aware routing.\n")
664 diversity_kind
= DIVERSITY_NONE
;
668 /* [Babel Command] */
669 DEFPY (babel_diversity_factor
,
670 babel_diversity_factor_cmd
,
671 "[no] babel diversity-factor (1-256)$factor",
674 "Set the diversity factor.\n"
675 "Factor in units of 1/256.\n")
677 diversity_factor
= no
? BABEL_DEFAULT_DIVERSITY_FACTOR
: factor
;
681 /* [Babel Command] */
682 DEFPY (babel_set_resend_delay
,
683 babel_set_resend_delay_cmd
,
684 "[no] babel resend-delay (20-655340)$delay",
687 "Time before resending a message\n"
690 resend_delay
= no
? BABEL_DEFAULT_RESEND_DELAY
: delay
;
694 /* [Babel Command] */
695 DEFPY (babel_set_smoothing_half_life
,
696 babel_set_smoothing_half_life_cmd
,
697 "[no] babel smoothing-half-life (0-65534)$seconds",
700 "Smoothing half-life\n"
701 "Seconds (0 to disable)\n")
703 change_smoothing_half_life(no
? BABEL_DEFAULT_SMOOTHING_HALF_LIFE
708 DEFUN (babel_distribute_list
,
709 babel_distribute_list_cmd
,
710 "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
711 "Filter networks in routing updates\n"
714 "Filter incoming routing updates\n"
715 "Filter outgoing routing updates\n"
718 const char *ifname
= NULL
;
719 int prefix
= (argv
[1]->type
== WORD_TKN
) ? 1 : 0;
721 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
722 ifname
= argv
[argc
- 1]->arg
;
724 return distribute_list_parser(prefix
, true, argv
[2 + prefix
]->text
,
725 argv
[1 + prefix
]->arg
, ifname
);
728 DEFUN (babel_no_distribute_list
,
729 babel_no_distribute_list_cmd
,
730 "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
732 "Filter networks in routing updates\n"
735 "Filter incoming routing updates\n"
736 "Filter outgoing routing updates\n"
739 const char *ifname
= NULL
;
740 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
742 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
743 ifname
= argv
[argc
- 1]->arg
;
745 return distribute_list_no_parser(vty
, prefix
, true,
746 argv
[3 + prefix
]->text
,
747 argv
[2 + prefix
]->arg
, ifname
);
750 DEFUN (babel_ipv6_distribute_list
,
751 babel_ipv6_distribute_list_cmd
,
752 "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
754 "Filter networks in routing updates\n"
757 "Filter incoming routing updates\n"
758 "Filter outgoing routing updates\n"
761 const char *ifname
= NULL
;
762 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
764 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
765 ifname
= argv
[argc
- 1]->arg
;
767 return distribute_list_parser(prefix
, false, argv
[3 + prefix
]->text
,
768 argv
[2 + prefix
]->arg
, ifname
);
771 DEFUN (babel_no_ipv6_distribute_list
,
772 babel_no_ipv6_distribute_list_cmd
,
773 "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
776 "Filter networks in routing updates\n"
779 "Filter incoming routing updates\n"
780 "Filter outgoing routing updates\n"
783 const char *ifname
= NULL
;
784 int prefix
= (argv
[3]->type
== WORD_TKN
) ? 1 : 0;
786 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
787 ifname
= argv
[argc
- 1]->arg
;
789 return distribute_list_no_parser(vty
, prefix
, false,
790 argv
[4 + prefix
]->text
,
791 argv
[3 + prefix
]->arg
, ifname
);
795 babeld_quagga_init(void)
798 install_node(&cmd_babel_node
);
800 install_element(CONFIG_NODE
, &router_babel_cmd
);
801 install_element(CONFIG_NODE
, &no_router_babel_cmd
);
803 install_default(BABEL_NODE
);
804 install_element(BABEL_NODE
, &babel_diversity_cmd
);
805 install_element(BABEL_NODE
, &no_babel_diversity_cmd
);
806 install_element(BABEL_NODE
, &babel_diversity_factor_cmd
);
807 install_element(BABEL_NODE
, &babel_set_resend_delay_cmd
);
808 install_element(BABEL_NODE
, &babel_set_smoothing_half_life_cmd
);
810 install_element(BABEL_NODE
, &babel_distribute_list_cmd
);
811 install_element(BABEL_NODE
, &babel_no_distribute_list_cmd
);
812 install_element(BABEL_NODE
, &babel_ipv6_distribute_list_cmd
);
813 install_element(BABEL_NODE
, &babel_no_ipv6_distribute_list_cmd
);
819 /* Access list install. */
821 access_list_add_hook (babel_distribute_update_all_wrapper
);
822 access_list_delete_hook (babel_distribute_update_all_wrapper
);
824 /* Prefix list initialize.*/
826 prefix_list_add_hook (babel_distribute_update_all
);
827 prefix_list_delete_hook (babel_distribute_update_all
);
830 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
833 input_filter(const unsigned char *id
,
834 const unsigned char *prefix
, unsigned short plen
,
835 const unsigned char *neigh
, unsigned int ifindex
)
837 return babel_filter(0, prefix
, plen
, ifindex
);
841 output_filter(const unsigned char *id
, const unsigned char *prefix
,
842 unsigned short plen
, unsigned int ifindex
)
844 return babel_filter(1, prefix
, plen
, ifindex
);
847 /* There's no redistribute filter in Quagga -- the zebra daemon does its
850 redistribute_filter(const unsigned char *prefix
, unsigned short plen
,
851 unsigned int ifindex
, int proto
)
856 struct babel
*babel_lookup(void)
858 return babel_routing_process
;