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
);
140 babel_create_routing_process (void)
142 assert (babel_routing_process
== NULL
);
144 /* Allocaste Babel instance. */
145 babel_routing_process
= XCALLOC(MTYPE_BABEL
, sizeof(struct babel
));
147 /* Initialize timeouts */
149 expiry_time
= babel_now
.tv_sec
+ roughly(30);
150 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
152 /* Make socket for Babel protocol. */
153 protocol_socket
= babel_socket(protocol_port
);
154 if (protocol_socket
< 0) {
155 flog_err_sys(EC_LIB_SOCKET
, "Couldn't create link local socket: %s",
156 safe_strerror(errno
));
161 thread_add_read(master
, &babel_read_protocol
, NULL
, protocol_socket
, &babel_routing_process
->t_read
);
162 /* wait a little: zebra will announce interfaces, addresses, routes... */
163 thread_add_timer_msec(master
, babel_init_routing_process
, NULL
, 200L, &babel_routing_process
->t_update
);
165 /* Distribute list install. */
166 babel_routing_process
->distribute_ctx
= distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT
));
167 distribute_list_add_hook (babel_routing_process
->distribute_ctx
, babel_distribute_update
);
168 distribute_list_delete_hook (babel_routing_process
->distribute_ctx
, babel_distribute_update
);
171 XFREE(MTYPE_BABEL
, babel_routing_process
);
175 /* thread reading entries form others babel daemons */
177 babel_read_protocol (struct thread
*thread
)
180 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
181 struct interface
*ifp
= NULL
;
182 struct sockaddr_in6 sin6
;
184 assert(babel_routing_process
!= NULL
);
185 assert(protocol_socket
>= 0);
187 rc
= babel_recv(protocol_socket
,
188 receive_buffer
, receive_buffer_size
,
189 (struct sockaddr
*)&sin6
, sizeof(sin6
));
191 if(errno
!= EAGAIN
&& errno
!= EINTR
) {
192 flog_err_sys(EC_LIB_SOCKET
, "recv: %s", safe_strerror(errno
));
195 FOR_ALL_INTERFACES(vrf
, ifp
) {
198 if(ifp
->ifindex
== (ifindex_t
)sin6
.sin6_scope_id
) {
199 parse_packet((unsigned char*)&sin6
.sin6_addr
, ifp
,
207 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. */
215 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 */
226 /* fill "myid" with an unique id (only if myid != {0}). */
230 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
231 struct interface
*ifp
= NULL
;
235 /* if we already have an id (from state file), we return. */
236 if (memcmp(myid
, zeroes
, 8) != 0) {
240 FOR_ALL_INTERFACES(vrf
, ifp
) {
241 /* ifp->ifindex is not necessarily valid at this point */
242 int ifindex
= if_nametoindex(ifp
->name
);
244 unsigned char eui
[8];
245 rc
= if_eui64(ifindex
, eui
);
248 memcpy(myid
, eui
, 8);
253 /* We failed to get a global EUI64 from the interfaces we were given.
254 Let's try to find an interface with a MAC address. */
255 for(i
= 1; i
< 256; i
++) {
256 char buf
[IF_NAMESIZE
], *ifname
;
257 unsigned char eui
[8];
258 ifname
= if_indextoname(i
, buf
);
261 rc
= if_eui64(i
, eui
);
264 memcpy(myid
, eui
, 8);
268 flog_err(EC_BABEL_CONFIG
, "Couldn't find router id -- using random value.");
270 rc
= read_random_bytes(myid
, 8);
272 flog_err(EC_BABEL_CONFIG
, "read(random): %s (cannot assign an ID)",
273 safe_strerror(errno
));
276 /* Clear group and global bits */
280 /* Make some noise so that others notice us, and send retractions in
281 case we were restarted recently */
283 babel_initial_noise(void)
285 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
286 struct interface
*ifp
= NULL
;
288 FOR_ALL_INTERFACES(vrf
, ifp
) {
291 /* Apply jitter before we send the first message. */
292 usleep(roughly(10000));
295 send_wildcard_retraction(ifp
);
298 FOR_ALL_INTERFACES(vrf
, ifp
) {
301 usleep(roughly(10000));
304 send_wildcard_retraction(ifp
);
305 send_self_update(ifp
);
306 send_request(ifp
, NULL
, 0);
312 /* Delete all the added babel routes, make babeld only speak to zebra. */
314 babel_clean_routing_process(void)
317 babel_interface_close_all();
320 thread_cancel(&babel_routing_process
->t_read
);
321 thread_cancel(&babel_routing_process
->t_update
);
323 distribute_list_delete(&babel_routing_process
->distribute_ctx
);
324 XFREE(MTYPE_BABEL
, babel_routing_process
);
327 /* Function used with timeout. */
329 babel_main_loop(struct thread
*thread
)
332 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
333 struct interface
*ifp
= NULL
;
338 /* timeouts --------------------------------------------------------- */
339 /* get the next timeout */
340 babel_fill_with_next_timeout(&tv
);
341 /* if there is no timeout, we must wait. */
342 if(timeval_compare(&tv
, &babel_now
) > 0) {
343 timeval_minus(&tv
, &tv
, &babel_now
);
344 debugf(BABEL_DEBUG_TIMEOUT
, "babel main loop : timeout: %lld msecs",
345 (long long)tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000);
346 /* it happens often to have less than 1 ms, it's bad. */
347 timeval_add_msec(&tv
, &tv
, 300);
348 babel_set_timer(&tv
);
354 /* update database -------------------------------------------------- */
355 if(timeval_compare(&check_neighbours_timeout
, &babel_now
) < 0) {
357 msecs
= check_neighbours();
358 /* Multiply by 3/2 to allow neighbours to expire. */
359 msecs
= MAX(3 * msecs
/ 2, 10);
360 schedule_neighbours_check(msecs
, 1);
363 if(babel_now
.tv_sec
>= expiry_time
) {
366 expiry_time
= babel_now
.tv_sec
+ roughly(30);
369 if(babel_now
.tv_sec
>= source_expiry_time
) {
371 source_expiry_time
= babel_now
.tv_sec
+ roughly(300);
374 FOR_ALL_INTERFACES(vrf
, ifp
) {
375 babel_interface_nfo
*babel_ifp
= NULL
;
378 babel_ifp
= babel_get_if_nfo(ifp
);
379 if(timeval_compare(&babel_now
, &babel_ifp
->hello_timeout
) >= 0)
381 if(timeval_compare(&babel_now
, &babel_ifp
->update_timeout
) >= 0)
382 send_update(ifp
, 0, NULL
, 0);
383 if(timeval_compare(&babel_now
,
384 &babel_ifp
->update_flush_timeout
) >= 0)
388 if(resend_time
.tv_sec
!= 0) {
389 if(timeval_compare(&babel_now
, &resend_time
) >= 0)
393 if(unicast_flush_timeout
.tv_sec
!= 0) {
394 if(timeval_compare(&babel_now
, &unicast_flush_timeout
) >= 0)
398 FOR_ALL_INTERFACES(vrf
, ifp
) {
399 babel_interface_nfo
*babel_ifp
= NULL
;
402 babel_ifp
= babel_get_if_nfo(ifp
);
403 if(babel_ifp
->flush_timeout
.tv_sec
!= 0) {
404 if(timeval_compare(&babel_now
, &babel_ifp
->flush_timeout
) >= 0)
410 assert(0); /* this line should never be reach */
415 printIfMin(struct timeval
*tv
, int cmd
, const char *tag
, const char *ifname
)
417 static struct timeval curr_tv
;
418 static char buffer
[200];
419 static const char *curr_tag
= NULL
;
422 case 0: /* reset timeval */
425 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
431 case 1: /* take the min */
432 if (tv
->tv_sec
== 0 && tv
->tv_usec
== 0) { /* if (tv == ∞) */
435 if (tv
->tv_sec
< curr_tv
.tv_sec
||(tv
->tv_sec
== curr_tv
.tv_sec
&&
436 tv
->tv_usec
< curr_tv
.tv_usec
)) {
439 snprintf(buffer
, 200L, "interface: %s; %s", ifname
, tag
);
446 case 2: /* print message */
447 debugf(BABEL_DEBUG_TIMEOUT
, "next timeout due to: %s", curr_tag
);
455 babel_fill_with_next_timeout(struct timeval
*tv
)
457 #if (defined NO_DEBUG)
458 #define printIfMin(a,b,c,d)
460 #define printIfMin(a,b,c,d) \
461 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
463 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
464 struct interface
*ifp
= NULL
;
466 *tv
= check_neighbours_timeout
;
467 printIfMin(tv
, 0, "check_neighbours_timeout", NULL
);
468 timeval_min_sec(tv
, expiry_time
);
469 printIfMin(tv
, 1, "expiry_time", NULL
);
470 timeval_min_sec(tv
, source_expiry_time
);
471 printIfMin(tv
, 1, "source_expiry_time", NULL
);
472 timeval_min(tv
, &resend_time
);
473 printIfMin(tv
, 1, "resend_time", NULL
);
474 FOR_ALL_INTERFACES(vrf
, ifp
) {
475 babel_interface_nfo
*babel_ifp
= NULL
;
478 babel_ifp
= babel_get_if_nfo(ifp
);
479 timeval_min(tv
, &babel_ifp
->flush_timeout
);
480 printIfMin(tv
, 1, "flush_timeout", ifp
->name
);
481 timeval_min(tv
, &babel_ifp
->hello_timeout
);
482 printIfMin(tv
, 1, "hello_timeout", ifp
->name
);
483 timeval_min(tv
, &babel_ifp
->update_timeout
);
484 printIfMin(tv
, 1, "update_timeout", ifp
->name
);
485 timeval_min(tv
, &babel_ifp
->update_flush_timeout
);
486 printIfMin(tv
, 1, "update_flush_timeout",ifp
->name
);
488 timeval_min(tv
, &unicast_flush_timeout
);
489 printIfMin(tv
, 1, "unicast_flush_timeout", NULL
);
490 printIfMin(tv
, 2, NULL
, NULL
);
495 /* set the t_update thread of the babel routing process to be launch in
496 'timeout' (approximate at the milisecond) */
498 babel_set_timer(struct timeval
*timeout
)
500 long msecs
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
501 thread_cancel(&(babel_routing_process
->t_update
));
502 thread_add_timer_msec(master
, babel_main_loop
, NULL
, msecs
, &babel_routing_process
->t_update
);
506 schedule_neighbours_check(int msecs
, int override
)
508 struct timeval timeout
;
510 timeval_add_msec(&timeout
, &babel_now
, msecs
);
512 check_neighbours_timeout
= timeout
;
514 timeval_min(&check_neighbours_timeout
, &timeout
);
518 resize_receive_buffer(int size
)
520 if(size
<= receive_buffer_size
)
523 if(receive_buffer
== NULL
) {
524 receive_buffer
= malloc(size
);
525 if(receive_buffer
== NULL
) {
526 flog_err(EC_BABEL_MEMORY
, "malloc(receive_buffer): %s",
527 safe_strerror(errno
));
530 receive_buffer_size
= size
;
533 new = realloc(receive_buffer
, size
);
535 flog_err(EC_BABEL_MEMORY
, "realloc(receive_buffer): %s",
536 safe_strerror(errno
));
539 receive_buffer
= new;
540 receive_buffer_size
= size
;
546 babel_distribute_update (struct distribute_ctx
*ctx
, struct distribute
*dist
)
548 struct interface
*ifp
;
549 babel_interface_nfo
*babel_ifp
;
556 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
560 babel_ifp
= babel_get_if_nfo(ifp
);
562 for (type
= 0; type
< DISTRIBUTE_MAX
; type
++) {
563 family
= type
== DISTRIBUTE_V4_IN
|| type
== DISTRIBUTE_V4_OUT
?
565 if (dist
->list
[type
])
566 babel_ifp
->list
[type
] = access_list_lookup (family
,
569 babel_ifp
->list
[type
] = NULL
;
570 if (dist
->prefix
[type
])
571 babel_ifp
->prefix
[type
] = prefix_list_lookup (family
,
574 babel_ifp
->prefix
[type
] = NULL
;
579 babel_distribute_update_interface (struct interface
*ifp
)
581 struct distribute
*dist
= NULL
;
583 if (babel_routing_process
)
584 dist
= distribute_lookup(babel_routing_process
->distribute_ctx
, ifp
->name
);
586 babel_distribute_update (babel_routing_process
->distribute_ctx
, dist
);
589 /* Update all interface's distribute list. */
591 babel_distribute_update_all (struct prefix_list
*notused
)
593 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
594 struct interface
*ifp
;
596 FOR_ALL_INTERFACES (vrf
, ifp
)
597 babel_distribute_update_interface (ifp
);
601 babel_distribute_update_all_wrapper (struct access_list
*notused
)
603 babel_distribute_update_all(NULL
);
608 DEFUN_NOSH (router_babel
,
611 "Enable a routing process\n"
612 "Make Babel instance command\n")
616 vty
->node
= BABEL_NODE
;
618 if (!babel_routing_process
) {
619 ret
= babel_create_routing_process ();
621 /* Notice to user we couldn't create Babel. */
623 zlog_warn ("can't create Babel");
632 DEFUN (no_router_babel
,
636 "Disable a routing process\n"
637 "Remove Babel instance command\n")
639 if(babel_routing_process
)
640 babel_clean_routing_process();
644 /* [Babel Command] */
645 DEFUN (babel_diversity
,
649 "Enable diversity-aware routing.\n")
651 diversity_kind
= DIVERSITY_CHANNEL
;
655 /* [Babel Command] */
656 DEFUN (no_babel_diversity
,
657 no_babel_diversity_cmd
,
658 "no babel diversity",
661 "Disable diversity-aware routing.\n")
663 diversity_kind
= DIVERSITY_NONE
;
667 /* [Babel Command] */
668 DEFUN (babel_diversity_factor
,
669 babel_diversity_factor_cmd
,
670 "babel diversity-factor (1-256)",
672 "Set the diversity factor.\n"
673 "Factor in units of 1/256.\n")
677 factor
= strtoul(argv
[2]->arg
, NULL
, 10);
679 diversity_factor
= factor
;
683 /* [Babel Command] */
684 DEFUN (babel_set_resend_delay
,
685 babel_set_resend_delay_cmd
,
686 "babel resend-delay (20-655340)",
688 "Time before resending a message\n"
693 interval
= strtoul(argv
[2]->arg
, NULL
, 10);
695 resend_delay
= interval
;
699 /* [Babel Command] */
700 DEFUN (babel_set_smoothing_half_life
,
701 babel_set_smoothing_half_life_cmd
,
702 "babel smoothing-half-life (0-65534)",
704 "Smoothing half-life\n"
705 "Seconds (0 to disable)\n")
709 seconds
= strtoul(argv
[2]->arg
, NULL
, 10);
711 change_smoothing_half_life(seconds
);
715 DEFUN (babel_distribute_list
,
716 babel_distribute_list_cmd
,
717 "distribute-list [prefix] WORD <in|out> [WORD]",
718 "Filter networks in routing updates\n"
721 "Filter incoming routing updates\n"
722 "Filter outgoing routing updates\n"
725 const char *ifname
= NULL
;
726 int prefix
= (argv
[1]->type
== WORD_TKN
) ? 1 : 0;
728 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
729 ifname
= argv
[argc
- 1]->arg
;
731 return distribute_list_parser(prefix
, true, argv
[2 + prefix
]->text
,
732 argv
[1 + prefix
]->arg
, ifname
);
735 DEFUN (babel_no_distribute_list
,
736 babel_no_distribute_list_cmd
,
737 "no distribute-list [prefix] WORD <in|out> [WORD]",
739 "Filter networks in routing updates\n"
742 "Filter incoming routing updates\n"
743 "Filter outgoing routing updates\n"
746 const char *ifname
= NULL
;
747 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
749 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
750 ifname
= argv
[argc
- 1]->arg
;
752 return distribute_list_no_parser(vty
, prefix
, true,
753 argv
[3 + prefix
]->text
,
754 argv
[2 + prefix
]->arg
, ifname
);
757 DEFUN (babel_ipv6_distribute_list
,
758 babel_ipv6_distribute_list_cmd
,
759 "ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
761 "Filter networks in routing updates\n"
764 "Filter incoming routing updates\n"
765 "Filter outgoing routing updates\n"
768 const char *ifname
= NULL
;
769 int prefix
= (argv
[2]->type
== WORD_TKN
) ? 1 : 0;
771 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
772 ifname
= argv
[argc
- 1]->arg
;
774 return distribute_list_parser(prefix
, false, argv
[3 + prefix
]->text
,
775 argv
[2 + prefix
]->arg
, ifname
);
778 DEFUN (babel_no_ipv6_distribute_list
,
779 babel_no_ipv6_distribute_list_cmd
,
780 "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
783 "Filter networks in routing updates\n"
786 "Filter incoming routing updates\n"
787 "Filter outgoing routing updates\n"
790 const char *ifname
= NULL
;
791 int prefix
= (argv
[3]->type
== WORD_TKN
) ? 1 : 0;
793 if (argv
[argc
- 1]->type
== VARIABLE_TKN
)
794 ifname
= argv
[argc
- 1]->arg
;
796 return distribute_list_no_parser(vty
, prefix
, false,
797 argv
[4 + prefix
]->text
,
798 argv
[3 + prefix
]->arg
, ifname
);
802 babeld_quagga_init(void)
805 install_node(&cmd_babel_node
);
807 install_element(CONFIG_NODE
, &router_babel_cmd
);
808 install_element(CONFIG_NODE
, &no_router_babel_cmd
);
810 install_default(BABEL_NODE
);
811 install_element(BABEL_NODE
, &babel_diversity_cmd
);
812 install_element(BABEL_NODE
, &no_babel_diversity_cmd
);
813 install_element(BABEL_NODE
, &babel_diversity_factor_cmd
);
814 install_element(BABEL_NODE
, &babel_set_resend_delay_cmd
);
815 install_element(BABEL_NODE
, &babel_set_smoothing_half_life_cmd
);
817 install_element(BABEL_NODE
, &babel_distribute_list_cmd
);
818 install_element(BABEL_NODE
, &babel_no_distribute_list_cmd
);
819 install_element(BABEL_NODE
, &babel_ipv6_distribute_list_cmd
);
820 install_element(BABEL_NODE
, &babel_no_ipv6_distribute_list_cmd
);
822 vrf_cmd_init(NULL
, &babeld_privs
);
826 /* Access list install. */
828 access_list_add_hook (babel_distribute_update_all_wrapper
);
829 access_list_delete_hook (babel_distribute_update_all_wrapper
);
831 /* Prefix list initialize.*/
833 prefix_list_add_hook (babel_distribute_update_all
);
834 prefix_list_delete_hook (babel_distribute_update_all
);
837 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
840 input_filter(const unsigned char *id
,
841 const unsigned char *prefix
, unsigned short plen
,
842 const unsigned char *neigh
, unsigned int ifindex
)
844 return babel_filter(0, prefix
, plen
, ifindex
);
848 output_filter(const unsigned char *id
, const unsigned char *prefix
,
849 unsigned short plen
, unsigned int ifindex
)
851 return babel_filter(1, prefix
, plen
, ifindex
);
854 /* There's no redistribute filter in Quagga -- the zebra daemon does its
857 redistribute_filter(const unsigned char *prefix
, unsigned short plen
,
858 unsigned int ifindex
, int proto
)
863 struct babel
*babel_lookup(void)
865 return babel_routing_process
;