blob: 9fea2e1012511e61f25b2b104adb4dfdc7964b5b [file] [log] [blame]
Paul Jakma57345092011-12-25 17:52:09 +01001/*
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * This file incorporates work covered by the following copyright and
16 * permission notice:
17 *
18
19Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20
21Permission is hereby granted, free of charge, to any person obtaining a copy
22of this software and associated documentation files (the "Software"), to deal
23in the Software without restriction, including without limitation the rights
24to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25copies of the Software, and to permit persons to whom the Software is
26furnished to do so, subject to the following conditions:
27
28The above copyright notice and this permission notice shall be included in
29all copies or substantial portions of the Software.
30
31THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37THE SOFTWARE.
38*/
39
40#include <zebra.h>
41#include "command.h"
42#include "prefix.h"
43#include "memory.h"
44#include "memtypes.h"
45#include "table.h"
46#include "distribute.h"
47#include "prefix.h"
48#include "filter.h"
49#include "plist.h"
50
51#include "babel_main.h"
52#include "babeld.h"
53#include "util.h"
54#include "net.h"
55#include "kernel.h"
56#include "babel_interface.h"
57#include "neighbour.h"
58#include "route.h"
59#include "message.h"
60#include "resend.h"
61#include "babel_filter.h"
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +040062#include "babel_zebra.h"
Paul Jakma57345092011-12-25 17:52:09 +010063
64
65static int babel_init_routing_process(struct thread *thread);
66static void babel_get_myid(void);
67static void babel_initial_noise(void);
68static int babel_read_protocol (struct thread *thread);
69static int babel_main_loop(struct thread *thread);
70static void babel_set_timer(struct timeval *timeout);
71static void babel_fill_with_next_timeout(struct timeval *tv);
72
73
74/* Informations relative to the babel running daemon. */
75static struct babel *babel_routing_process = NULL;
76static unsigned char *receive_buffer = NULL;
77static int receive_buffer_size = 0;
78
79/* timeouts */
80struct timeval check_neighbours_timeout;
81static time_t expiry_time;
82static time_t source_expiry_time;
83
84/* Babel node structure. */
85static struct cmd_node cmd_babel_node =
86{
87 .node = BABEL_NODE,
88 .prompt = "%s(config-router)# ",
89 .vtysh = 1,
90};
91
92/* print current babel configuration on vty */
93static int
94babel_config_write (struct vty *vty)
95{
Denis Ovsienkoa14ef5e2012-02-11 21:06:16 +040096 int lines = 0;
97 int i;
98
99 /* list enabled debug modes */
100 lines += debug_babel_config_write (vty);
101
102 if (!babel_routing_process)
103 return lines;
104 vty_out (vty, "router babel%s", VTY_NEWLINE);
105 /* list enabled interfaces */
106 lines = 1 + babel_enable_if_config_write (vty);
107 /* list redistributed protocols */
108 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
109 if (i != zclient->redist_default && zclient->redist[i])
110 {
111 vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE);
112 lines++;
113 }
114
115 return lines;
Paul Jakma57345092011-12-25 17:52:09 +0100116}
117
118
119static int
120babel_create_routing_process (void)
121{
122 assert (babel_routing_process == NULL);
123
124 /* Allocaste Babel instance. */
125 babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
126
127 /* Initialize timeouts */
128 gettime(&babel_now);
129 expiry_time = babel_now.tv_sec + roughly(30);
130 source_expiry_time = babel_now.tv_sec + roughly(300);
131
132 /* Make socket for Babel protocol. */
133 protocol_socket = babel_socket(protocol_port);
134 if (protocol_socket < 0) {
135 zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
136 goto fail;
137 }
138
139 /* Threads. */
140 babel_routing_process->t_read =
141 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
142 /* wait a little: zebra will announce interfaces, addresses, routes... */
143 babel_routing_process->t_update =
144 thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
145 return 0;
146
147fail:
148 XFREE(MTYPE_BABEL, babel_routing_process);
149 babel_routing_process = NULL;
150 return -1;
151}
152
153/* thread reading entries form others babel daemons */
154static int
155babel_read_protocol (struct thread *thread)
156{
157 int rc;
158 struct interface *ifp = NULL;
159 struct sockaddr_in6 sin6;
160 struct listnode *linklist_node = NULL;
161
162 assert(babel_routing_process != NULL);
163 assert(protocol_socket >= 0);
164
165 rc = babel_recv(protocol_socket,
166 receive_buffer, receive_buffer_size,
167 (struct sockaddr*)&sin6, sizeof(sin6));
168 if(rc < 0) {
169 if(errno != EAGAIN && errno != EINTR) {
170 zlog_err("recv: %s", safe_strerror(errno));
171 }
172 } else {
173 FOR_ALL_INTERFACES(ifp, linklist_node) {
174 if(!if_up(ifp))
175 continue;
176 if(ifp->ifindex == sin6.sin6_scope_id) {
177 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
178 receive_buffer, rc);
179 break;
180 }
181 }
182 }
183
184 /* re-add thread */
185 babel_routing_process->t_read =
186 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
187 return 0;
188}
189
190/* Zebra will give some information, especially about interfaces. This function
191 must be call with a litte timeout wich may give zebra the time to do his job,
192 making these inits have sense. */
193static int
194babel_init_routing_process(struct thread *thread)
195{
Matthieu Boutier69394542012-01-28 10:35:12 +0100196 myseqno = (random() & 0xFFFF);
Paul Jakma57345092011-12-25 17:52:09 +0100197 babel_get_myid();
Matthieu Boutier69394542012-01-28 10:35:12 +0100198 babel_load_state_file();
Paul Jakma57345092011-12-25 17:52:09 +0100199 debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
200 babel_initial_noise();
201 babel_main_loop(thread);/* this function self-add to the t_update thread */
202 return 0;
203}
204
205/* fill "myid" with an unique id (only if myid != {0}). */
206static void
207babel_get_myid(void)
208{
209 struct interface *ifp = NULL;
210 struct listnode *linklist_node = NULL;
211 int rc;
212 int i;
213
214 /* if we already have an id (from state file), we return. */
215 if (memcmp(myid, zeroes, 8) != 0) {
216 return;
217 }
218
219 FOR_ALL_INTERFACES(ifp, linklist_node) {
220 /* ifp->ifindex is not necessarily valid at this point */
221 int ifindex = if_nametoindex(ifp->name);
222 if(ifindex > 0) {
223 unsigned char eui[8];
224 rc = if_eui64(ifp->name, ifindex, eui);
225 if(rc < 0)
226 continue;
227 memcpy(myid, eui, 8);
228 return;
229 }
230 }
231
232 /* We failed to get a global EUI64 from the interfaces we were given.
233 Let's try to find an interface with a MAC address. */
234 for(i = 1; i < 256; i++) {
235 char buf[IF_NAMESIZE], *ifname;
236 unsigned char eui[8];
237 ifname = if_indextoname(i, buf);
238 if(ifname == NULL)
239 continue;
240 rc = if_eui64(ifname, i, eui);
241 if(rc < 0)
242 continue;
243 memcpy(myid, eui, 8);
244 return;
245 }
246
247 zlog_err("Warning: couldn't find router id -- using random value.");
248
249 rc = read_random_bytes(myid, 8);
250 if(rc < 0) {
251 zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
252 exit(1);
253 }
254 /* Clear group and global bits */
255 myid[0] &= ~3;
256}
257
258/* Make some noise so that others notice us, and send retractions in
259 case we were restarted recently */
260static void
261babel_initial_noise(void)
262{
263 struct interface *ifp = NULL;
264 struct listnode *linklist_node = NULL;
265
266 FOR_ALL_INTERFACES(ifp, linklist_node) {
267 if(!if_up(ifp))
268 continue;
269 /* Apply jitter before we send the first message. */
270 usleep(roughly(10000));
271 gettime(&babel_now);
272 send_hello(ifp);
273 send_wildcard_retraction(ifp);
274 }
275
276 FOR_ALL_INTERFACES(ifp, linklist_node) {
277 if(!if_up(ifp))
278 continue;
279 usleep(roughly(10000));
280 gettime(&babel_now);
281 send_hello(ifp);
282 send_wildcard_retraction(ifp);
283 send_self_update(ifp);
284 send_request(ifp, NULL, 0);
285 flushupdates(ifp);
286 flushbuf(ifp);
287 }
288}
289
290/* Delete all the added babel routes, make babeld only speak to zebra. */
291static void
292babel_clean_routing_process()
293{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100294 flush_all_routes();
Paul Jakma57345092011-12-25 17:52:09 +0100295 babel_interface_close_all();
296
297 /* cancel threads */
298 if (babel_routing_process->t_read != NULL) {
299 thread_cancel(babel_routing_process->t_read);
300 }
301 if (babel_routing_process->t_update != NULL) {
302 thread_cancel(babel_routing_process->t_update);
303 }
304
305 XFREE(MTYPE_BABEL, babel_routing_process);
306 babel_routing_process = NULL;
307}
308
309/* Function used with timeout. */
310static int
311babel_main_loop(struct thread *thread)
312{
313 struct timeval tv;
314 struct interface *ifp = NULL;
315 struct listnode *linklist_node = NULL;
316
317 while(1) {
318 gettime(&babel_now);
319
320 /* timeouts --------------------------------------------------------- */
321 /* get the next timeout */
322 babel_fill_with_next_timeout(&tv);
323 /* if there is no timeout, we must wait. */
324 if(timeval_compare(&tv, &babel_now) > 0) {
325 timeval_minus(&tv, &tv, &babel_now);
326 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
327 tv.tv_sec * 1000 + tv.tv_usec / 1000);
328 /* it happens often to have less than 1 ms, it's bad. */
329 timeval_add_msec(&tv, &tv, 300);
330 babel_set_timer(&tv);
331 return 0;
332 }
333
334 gettime(&babel_now);
335
336 /* update database -------------------------------------------------- */
337 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
338 int msecs;
339 msecs = check_neighbours();
340 msecs = MAX(msecs, 10);
341 schedule_neighbours_check(msecs, 1);
342 }
343
344 if(babel_now.tv_sec >= expiry_time) {
345 expire_routes();
346 expire_resend();
347 expiry_time = babel_now.tv_sec + roughly(30);
348 }
349
350 if(babel_now.tv_sec >= source_expiry_time) {
351 expire_sources();
352 source_expiry_time = babel_now.tv_sec + roughly(300);
353 }
354
355 FOR_ALL_INTERFACES(ifp, linklist_node) {
356 babel_interface_nfo *babel_ifp = NULL;
357 if(!if_up(ifp))
358 continue;
359 babel_ifp = babel_get_if_nfo(ifp);
360 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
361 send_hello(ifp);
362 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
363 send_update(ifp, 0, NULL, 0);
364 if(timeval_compare(&babel_now,
365 &babel_ifp->update_flush_timeout) >= 0)
366 flushupdates(ifp);
367 }
368
369 if(resend_time.tv_sec != 0) {
370 if(timeval_compare(&babel_now, &resend_time) >= 0)
371 do_resend();
372 }
373
374 if(unicast_flush_timeout.tv_sec != 0) {
375 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
376 flush_unicast(1);
377 }
378
379 FOR_ALL_INTERFACES(ifp, linklist_node) {
380 babel_interface_nfo *babel_ifp = NULL;
381 if(!if_up(ifp))
382 continue;
383 babel_ifp = babel_get_if_nfo(ifp);
384 if(babel_ifp->flush_timeout.tv_sec != 0) {
385 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
386 flushbuf(ifp);
387 }
388 }
389 }
390
391 assert(0); /* this line should never be reach */
392}
393
394static void
395printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
396{
397 static struct timeval curr_tv;
398 static char buffer[200];
399 static const char *curr_tag = NULL;
400
401 switch (cmd) {
402 case 0: /* reset timeval */
403 curr_tv = *tv;
404 if(ifname != NULL) {
405 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
406 curr_tag = buffer;
407 } else {
408 curr_tag = tag;
409 }
410 break;
411 case 1: /* take the min */
412 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
413 break;
414 }
415 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
416 tv->tv_usec < curr_tv.tv_usec)) {
417 curr_tv = *tv;
418 if(ifname != NULL) {
419 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
420 curr_tag = buffer;
421 } else {
422 curr_tag = tag;
423 }
424 }
425 break;
426 case 2: /* print message */
427 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
428 break;
429 default:
430 break;
431 }
432}
433
434static void
435babel_fill_with_next_timeout(struct timeval *tv)
436{
437#if (defined NO_DEBUG)
438#define printIfMin(a,b,c,d)
439#else
440#define printIfMin(a,b,c,d) \
441 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
442
443 struct interface *ifp = NULL;
444 struct listnode *linklist_node = NULL;
445
446 *tv = check_neighbours_timeout;
447 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
448 timeval_min_sec(tv, expiry_time);
449 printIfMin(tv, 1, "expiry_time", NULL);
450 timeval_min_sec(tv, source_expiry_time);
451 printIfMin(tv, 1, "source_expiry_time", NULL);
452 timeval_min(tv, &resend_time);
453 printIfMin(tv, 1, "resend_time", NULL);
454 FOR_ALL_INTERFACES(ifp, linklist_node) {
455 babel_interface_nfo *babel_ifp = NULL;
456 if(!if_up(ifp))
457 continue;
458 babel_ifp = babel_get_if_nfo(ifp);
459 timeval_min(tv, &babel_ifp->flush_timeout);
460 printIfMin(tv, 1, "flush_timeout", ifp->name);
461 timeval_min(tv, &babel_ifp->hello_timeout);
462 printIfMin(tv, 1, "hello_timeout", ifp->name);
463 timeval_min(tv, &babel_ifp->update_timeout);
464 printIfMin(tv, 1, "update_timeout", ifp->name);
465 timeval_min(tv, &babel_ifp->update_flush_timeout);
466 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
467 }
468 timeval_min(tv, &unicast_flush_timeout);
469 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
470 printIfMin(tv, 2, NULL, NULL);
471#undef printIfMin
472#endif
473}
474
475/* set the t_update thread of the babel routing process to be launch in
476 'timeout' (approximate at the milisecond) */
477static void
478babel_set_timer(struct timeval *timeout)
479{
480 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
481 if (babel_routing_process->t_update != NULL) {
482 thread_cancel(babel_routing_process->t_update);
483 }
484 babel_routing_process->t_update =
485 thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
486}
487
488/* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
489void
490schedule_neighbours_check(int msecs, int override)
491{
492 struct timeval timeout;
493
494 timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
495 if(override)
496 check_neighbours_timeout = timeout;
497 else
498 timeval_min(&check_neighbours_timeout, &timeout);
499}
500
501int
502resize_receive_buffer(int size)
503{
504 if(size <= receive_buffer_size)
505 return 0;
506
507 if(receive_buffer == NULL) {
508 receive_buffer = malloc(size);
509 if(receive_buffer == NULL) {
510 zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
511 return -1;
512 }
513 receive_buffer_size = size;
514 } else {
515 unsigned char *new;
516 new = realloc(receive_buffer, size);
517 if(new == NULL) {
518 zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
519 return -1;
520 }
521 receive_buffer = new;
522 receive_buffer_size = size;
523 }
524 return 1;
525}
526
527static void
528babel_distribute_update (struct distribute *dist)
529{
530 struct interface *ifp;
531 babel_interface_nfo *babel_ifp;
532 struct access_list *alist;
533 struct prefix_list *plist;
534
535 if (! dist->ifname)
536 return;
537
538 ifp = if_lookup_by_name (dist->ifname);
539 if (ifp == NULL)
540 return;
541
542 babel_ifp = babel_get_if_nfo(ifp);
543
544 if (dist->list[DISTRIBUTE_IN]) {
545 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
546 if (alist)
547 babel_ifp->list[BABEL_FILTER_IN] = alist;
548 else
549 babel_ifp->list[BABEL_FILTER_IN] = NULL;
550 } else {
551 babel_ifp->list[BABEL_FILTER_IN] = NULL;
552 }
553
554 if (dist->list[DISTRIBUTE_OUT]) {
555 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
556 if (alist)
557 babel_ifp->list[BABEL_FILTER_OUT] = alist;
558 else
559 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
560 } else {
561 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
562 }
563
564 if (dist->prefix[DISTRIBUTE_IN]) {
565 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
566 if (plist)
567 babel_ifp->prefix[BABEL_FILTER_IN] = plist;
568 else
569 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
570 } else {
571 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
572 }
573
574 if (dist->prefix[DISTRIBUTE_OUT]) {
575 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
576 if (plist)
577 babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
578 else
579 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
580 } else {
581 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
582 }
583}
584
Denis Ovsienko3dbda0c2012-01-08 16:52:36 +0400585static void
Paul Jakma57345092011-12-25 17:52:09 +0100586babel_distribute_update_interface (struct interface *ifp)
587{
588 struct distribute *dist;
589
590 dist = distribute_lookup (ifp->name);
591 if (dist)
592 babel_distribute_update (dist);
593}
594
595/* Update all interface's distribute list. */
596static void
597babel_distribute_update_all (struct prefix_list *notused)
598{
599 struct interface *ifp;
600 struct listnode *node;
601
602 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
603 babel_distribute_update_interface (ifp);
604}
605
606static void
607babel_distribute_update_all_wrapper (struct access_list *notused)
608{
609 babel_distribute_update_all(NULL);
610}
611
612
613/* [Command] */
614DEFUN (router_babel,
615 router_babel_cmd,
616 "router babel",
617 "Enable a routing process\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100618 "Make Babel instance command\n"
619 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100620{
621 int ret;
622
623 vty->node = BABEL_NODE;
624
625 if (!babel_routing_process) {
626 ret = babel_create_routing_process ();
627
628 /* Notice to user we couldn't create Babel. */
629 if (ret < 0) {
630 zlog_warn ("can't create Babel");
Juliusz Chroboczek38846de2012-02-07 05:43:36 +0100631 return CMD_WARNING;
Paul Jakma57345092011-12-25 17:52:09 +0100632 }
633 }
634
635 return CMD_SUCCESS;
636}
637
638/* [Command] */
639DEFUN (no_router_babel,
640 no_router_babel_cmd,
641 "no router babel",
642 NO_STR
643 "Disable a routing process\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100644 "Remove Babel instance command\n"
645 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100646{
647 if(babel_routing_process)
648 babel_clean_routing_process();
649 return CMD_SUCCESS;
650}
651
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100652/* [Babel Command] */
653DEFUN (babel_set_resend_delay,
654 babel_set_resend_delay_cmd,
655 "babel resend-delay <20-655340>",
656 "Babel commands\n"
657 "Time before resending a message\n"
658 "Milliseconds\n")
659{
660 int interval;
661
662 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
663
664 resend_delay = interval;
665 return CMD_SUCCESS;
666}
667
Paul Jakma57345092011-12-25 17:52:09 +0100668void
669babeld_quagga_init(void)
670{
671
672 install_node(&cmd_babel_node, &babel_config_write);
673
674 install_element(CONFIG_NODE, &router_babel_cmd);
675 install_element(CONFIG_NODE, &no_router_babel_cmd);
676
677 install_default(BABEL_NODE);
Juliusz Chroboczekc428edb2012-02-11 14:02:10 +0100678 install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
Paul Jakma57345092011-12-25 17:52:09 +0100679
680 babel_if_init();
681
682 /* Access list install. */
683 access_list_init ();
684 access_list_add_hook (babel_distribute_update_all_wrapper);
685 access_list_delete_hook (babel_distribute_update_all_wrapper);
686
687 /* Prefix list initialize.*/
688 prefix_list_init ();
689 prefix_list_add_hook (babel_distribute_update_all);
690 prefix_list_delete_hook (babel_distribute_update_all);
691
692 /* Distribute list install. */
693 distribute_list_init (BABEL_NODE);
694 distribute_list_add_hook (babel_distribute_update);
695 distribute_list_delete_hook (babel_distribute_update);
696}
697
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100698/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
699
700int
Paul Jakma57345092011-12-25 17:52:09 +0100701input_filter(const unsigned char *id,
702 const unsigned char *prefix, unsigned short plen,
703 const unsigned char *neigh, unsigned int ifindex)
704{
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100705 return babel_filter(0, prefix, plen, ifindex);
Paul Jakma57345092011-12-25 17:52:09 +0100706}
707
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100708int
Paul Jakma57345092011-12-25 17:52:09 +0100709output_filter(const unsigned char *id, const unsigned char *prefix,
710 unsigned short plen, unsigned int ifindex)
711{
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100712 return babel_filter(1, prefix, plen, ifindex);
Paul Jakma57345092011-12-25 17:52:09 +0100713}
714
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100715/* There's no redistribute filter in Quagga -- the zebra daemon does its
716 own filtering. */
717int
Paul Jakma57345092011-12-25 17:52:09 +0100718redistribute_filter(const unsigned char *prefix, unsigned short plen,
719 unsigned int ifindex, int proto)
720{
Juliusz Chroboczek31e2a192012-02-09 14:06:11 +0100721 return 0;
Paul Jakma57345092011-12-25 17:52:09 +0100722}
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100723