blob: 6487bbe1505bf2a74e26f70db5d667c47abb4c7c [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"
62
63
64static int babel_init_routing_process(struct thread *thread);
65static void babel_get_myid(void);
66static void babel_initial_noise(void);
67static int babel_read_protocol (struct thread *thread);
68static int babel_main_loop(struct thread *thread);
69static void babel_set_timer(struct timeval *timeout);
70static void babel_fill_with_next_timeout(struct timeval *tv);
71
72
73/* Informations relative to the babel running daemon. */
74static struct babel *babel_routing_process = NULL;
75static unsigned char *receive_buffer = NULL;
76static int receive_buffer_size = 0;
77
78/* timeouts */
79struct timeval check_neighbours_timeout;
80static time_t expiry_time;
81static time_t source_expiry_time;
82
83/* Babel node structure. */
84static struct cmd_node cmd_babel_node =
85{
86 .node = BABEL_NODE,
87 .prompt = "%s(config-router)# ",
88 .vtysh = 1,
89};
90
91/* print current babel configuration on vty */
92static int
93babel_config_write (struct vty *vty)
94{
95 return 0;
96}
97
98
99static int
100babel_create_routing_process (void)
101{
102 assert (babel_routing_process == NULL);
103
104 /* Allocaste Babel instance. */
105 babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
106
107 /* Initialize timeouts */
108 gettime(&babel_now);
109 expiry_time = babel_now.tv_sec + roughly(30);
110 source_expiry_time = babel_now.tv_sec + roughly(300);
111
112 /* Make socket for Babel protocol. */
113 protocol_socket = babel_socket(protocol_port);
114 if (protocol_socket < 0) {
115 zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
116 goto fail;
117 }
118
119 /* Threads. */
120 babel_routing_process->t_read =
121 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
122 /* wait a little: zebra will announce interfaces, addresses, routes... */
123 babel_routing_process->t_update =
124 thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
125 return 0;
126
127fail:
128 XFREE(MTYPE_BABEL, babel_routing_process);
129 babel_routing_process = NULL;
130 return -1;
131}
132
133/* thread reading entries form others babel daemons */
134static int
135babel_read_protocol (struct thread *thread)
136{
137 int rc;
138 struct interface *ifp = NULL;
139 struct sockaddr_in6 sin6;
140 struct listnode *linklist_node = NULL;
141
142 assert(babel_routing_process != NULL);
143 assert(protocol_socket >= 0);
144
145 rc = babel_recv(protocol_socket,
146 receive_buffer, receive_buffer_size,
147 (struct sockaddr*)&sin6, sizeof(sin6));
148 if(rc < 0) {
149 if(errno != EAGAIN && errno != EINTR) {
150 zlog_err("recv: %s", safe_strerror(errno));
151 }
152 } else {
153 FOR_ALL_INTERFACES(ifp, linklist_node) {
154 if(!if_up(ifp))
155 continue;
156 if(ifp->ifindex == sin6.sin6_scope_id) {
157 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
158 receive_buffer, rc);
159 break;
160 }
161 }
162 }
163
164 /* re-add thread */
165 babel_routing_process->t_read =
166 thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
167 return 0;
168}
169
170/* Zebra will give some information, especially about interfaces. This function
171 must be call with a litte timeout wich may give zebra the time to do his job,
172 making these inits have sense. */
173static int
174babel_init_routing_process(struct thread *thread)
175{
176 babel_get_myid();
177 debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
178 babel_initial_noise();
179 babel_main_loop(thread);/* this function self-add to the t_update thread */
180 return 0;
181}
182
183/* fill "myid" with an unique id (only if myid != {0}). */
184static void
185babel_get_myid(void)
186{
187 struct interface *ifp = NULL;
188 struct listnode *linklist_node = NULL;
189 int rc;
190 int i;
191
192 /* if we already have an id (from state file), we return. */
193 if (memcmp(myid, zeroes, 8) != 0) {
194 return;
195 }
196
197 FOR_ALL_INTERFACES(ifp, linklist_node) {
198 /* ifp->ifindex is not necessarily valid at this point */
199 int ifindex = if_nametoindex(ifp->name);
200 if(ifindex > 0) {
201 unsigned char eui[8];
202 rc = if_eui64(ifp->name, ifindex, eui);
203 if(rc < 0)
204 continue;
205 memcpy(myid, eui, 8);
206 return;
207 }
208 }
209
210 /* We failed to get a global EUI64 from the interfaces we were given.
211 Let's try to find an interface with a MAC address. */
212 for(i = 1; i < 256; i++) {
213 char buf[IF_NAMESIZE], *ifname;
214 unsigned char eui[8];
215 ifname = if_indextoname(i, buf);
216 if(ifname == NULL)
217 continue;
218 rc = if_eui64(ifname, i, eui);
219 if(rc < 0)
220 continue;
221 memcpy(myid, eui, 8);
222 return;
223 }
224
225 zlog_err("Warning: couldn't find router id -- using random value.");
226
227 rc = read_random_bytes(myid, 8);
228 if(rc < 0) {
229 zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
230 exit(1);
231 }
232 /* Clear group and global bits */
233 myid[0] &= ~3;
234}
235
236/* Make some noise so that others notice us, and send retractions in
237 case we were restarted recently */
238static void
239babel_initial_noise(void)
240{
241 struct interface *ifp = NULL;
242 struct listnode *linklist_node = NULL;
243
244 FOR_ALL_INTERFACES(ifp, linklist_node) {
245 if(!if_up(ifp))
246 continue;
247 /* Apply jitter before we send the first message. */
248 usleep(roughly(10000));
249 gettime(&babel_now);
250 send_hello(ifp);
251 send_wildcard_retraction(ifp);
252 }
253
254 FOR_ALL_INTERFACES(ifp, linklist_node) {
255 if(!if_up(ifp))
256 continue;
257 usleep(roughly(10000));
258 gettime(&babel_now);
259 send_hello(ifp);
260 send_wildcard_retraction(ifp);
261 send_self_update(ifp);
262 send_request(ifp, NULL, 0);
263 flushupdates(ifp);
264 flushbuf(ifp);
265 }
266}
267
268/* Delete all the added babel routes, make babeld only speak to zebra. */
269static void
270babel_clean_routing_process()
271{
272 babel_uninstall_all_routes();
273 babel_interface_close_all();
274
275 /* cancel threads */
276 if (babel_routing_process->t_read != NULL) {
277 thread_cancel(babel_routing_process->t_read);
278 }
279 if (babel_routing_process->t_update != NULL) {
280 thread_cancel(babel_routing_process->t_update);
281 }
282
283 XFREE(MTYPE_BABEL, babel_routing_process);
284 babel_routing_process = NULL;
285}
286
287/* Function used with timeout. */
288static int
289babel_main_loop(struct thread *thread)
290{
291 struct timeval tv;
292 struct interface *ifp = NULL;
293 struct listnode *linklist_node = NULL;
294
295 while(1) {
296 gettime(&babel_now);
297
298 /* timeouts --------------------------------------------------------- */
299 /* get the next timeout */
300 babel_fill_with_next_timeout(&tv);
301 /* if there is no timeout, we must wait. */
302 if(timeval_compare(&tv, &babel_now) > 0) {
303 timeval_minus(&tv, &tv, &babel_now);
304 debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
305 tv.tv_sec * 1000 + tv.tv_usec / 1000);
306 /* it happens often to have less than 1 ms, it's bad. */
307 timeval_add_msec(&tv, &tv, 300);
308 babel_set_timer(&tv);
309 return 0;
310 }
311
312 gettime(&babel_now);
313
314 /* update database -------------------------------------------------- */
315 if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
316 int msecs;
317 msecs = check_neighbours();
318 msecs = MAX(msecs, 10);
319 schedule_neighbours_check(msecs, 1);
320 }
321
322 if(babel_now.tv_sec >= expiry_time) {
323 expire_routes();
324 expire_resend();
325 expiry_time = babel_now.tv_sec + roughly(30);
326 }
327
328 if(babel_now.tv_sec >= source_expiry_time) {
329 expire_sources();
330 source_expiry_time = babel_now.tv_sec + roughly(300);
331 }
332
333 FOR_ALL_INTERFACES(ifp, linklist_node) {
334 babel_interface_nfo *babel_ifp = NULL;
335 if(!if_up(ifp))
336 continue;
337 babel_ifp = babel_get_if_nfo(ifp);
338 if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
339 send_hello(ifp);
340 if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
341 send_update(ifp, 0, NULL, 0);
342 if(timeval_compare(&babel_now,
343 &babel_ifp->update_flush_timeout) >= 0)
344 flushupdates(ifp);
345 }
346
347 if(resend_time.tv_sec != 0) {
348 if(timeval_compare(&babel_now, &resend_time) >= 0)
349 do_resend();
350 }
351
352 if(unicast_flush_timeout.tv_sec != 0) {
353 if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
354 flush_unicast(1);
355 }
356
357 FOR_ALL_INTERFACES(ifp, linklist_node) {
358 babel_interface_nfo *babel_ifp = NULL;
359 if(!if_up(ifp))
360 continue;
361 babel_ifp = babel_get_if_nfo(ifp);
362 if(babel_ifp->flush_timeout.tv_sec != 0) {
363 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
364 flushbuf(ifp);
365 }
366 }
367 }
368
369 assert(0); /* this line should never be reach */
370}
371
372static void
373printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
374{
375 static struct timeval curr_tv;
376 static char buffer[200];
377 static const char *curr_tag = NULL;
378
379 switch (cmd) {
380 case 0: /* reset timeval */
381 curr_tv = *tv;
382 if(ifname != NULL) {
383 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
384 curr_tag = buffer;
385 } else {
386 curr_tag = tag;
387 }
388 break;
389 case 1: /* take the min */
390 if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
391 break;
392 }
393 if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
394 tv->tv_usec < curr_tv.tv_usec)) {
395 curr_tv = *tv;
396 if(ifname != NULL) {
397 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
398 curr_tag = buffer;
399 } else {
400 curr_tag = tag;
401 }
402 }
403 break;
404 case 2: /* print message */
405 debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
406 break;
407 default:
408 break;
409 }
410}
411
412static void
413babel_fill_with_next_timeout(struct timeval *tv)
414{
415#if (defined NO_DEBUG)
416#define printIfMin(a,b,c,d)
417#else
418#define printIfMin(a,b,c,d) \
419 if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
420
421 struct interface *ifp = NULL;
422 struct listnode *linklist_node = NULL;
423
424 *tv = check_neighbours_timeout;
425 printIfMin(tv, 0, "check_neighbours_timeout", NULL);
426 timeval_min_sec(tv, expiry_time);
427 printIfMin(tv, 1, "expiry_time", NULL);
428 timeval_min_sec(tv, source_expiry_time);
429 printIfMin(tv, 1, "source_expiry_time", NULL);
430 timeval_min(tv, &resend_time);
431 printIfMin(tv, 1, "resend_time", NULL);
432 FOR_ALL_INTERFACES(ifp, linklist_node) {
433 babel_interface_nfo *babel_ifp = NULL;
434 if(!if_up(ifp))
435 continue;
436 babel_ifp = babel_get_if_nfo(ifp);
437 timeval_min(tv, &babel_ifp->flush_timeout);
438 printIfMin(tv, 1, "flush_timeout", ifp->name);
439 timeval_min(tv, &babel_ifp->hello_timeout);
440 printIfMin(tv, 1, "hello_timeout", ifp->name);
441 timeval_min(tv, &babel_ifp->update_timeout);
442 printIfMin(tv, 1, "update_timeout", ifp->name);
443 timeval_min(tv, &babel_ifp->update_flush_timeout);
444 printIfMin(tv, 1, "update_flush_timeout",ifp->name);
445 }
446 timeval_min(tv, &unicast_flush_timeout);
447 printIfMin(tv, 1, "unicast_flush_timeout", NULL);
448 printIfMin(tv, 2, NULL, NULL);
449#undef printIfMin
450#endif
451}
452
453/* set the t_update thread of the babel routing process to be launch in
454 'timeout' (approximate at the milisecond) */
455static void
456babel_set_timer(struct timeval *timeout)
457{
458 long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
459 if (babel_routing_process->t_update != NULL) {
460 thread_cancel(babel_routing_process->t_update);
461 }
462 babel_routing_process->t_update =
463 thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
464}
465
466/* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
467void
468schedule_neighbours_check(int msecs, int override)
469{
470 struct timeval timeout;
471
472 timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
473 if(override)
474 check_neighbours_timeout = timeout;
475 else
476 timeval_min(&check_neighbours_timeout, &timeout);
477}
478
479int
480resize_receive_buffer(int size)
481{
482 if(size <= receive_buffer_size)
483 return 0;
484
485 if(receive_buffer == NULL) {
486 receive_buffer = malloc(size);
487 if(receive_buffer == NULL) {
488 zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
489 return -1;
490 }
491 receive_buffer_size = size;
492 } else {
493 unsigned char *new;
494 new = realloc(receive_buffer, size);
495 if(new == NULL) {
496 zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
497 return -1;
498 }
499 receive_buffer = new;
500 receive_buffer_size = size;
501 }
502 return 1;
503}
504
505static void
506babel_distribute_update (struct distribute *dist)
507{
508 struct interface *ifp;
509 babel_interface_nfo *babel_ifp;
510 struct access_list *alist;
511 struct prefix_list *plist;
512
513 if (! dist->ifname)
514 return;
515
516 ifp = if_lookup_by_name (dist->ifname);
517 if (ifp == NULL)
518 return;
519
520 babel_ifp = babel_get_if_nfo(ifp);
521
522 if (dist->list[DISTRIBUTE_IN]) {
523 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
524 if (alist)
525 babel_ifp->list[BABEL_FILTER_IN] = alist;
526 else
527 babel_ifp->list[BABEL_FILTER_IN] = NULL;
528 } else {
529 babel_ifp->list[BABEL_FILTER_IN] = NULL;
530 }
531
532 if (dist->list[DISTRIBUTE_OUT]) {
533 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
534 if (alist)
535 babel_ifp->list[BABEL_FILTER_OUT] = alist;
536 else
537 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
538 } else {
539 babel_ifp->list[BABEL_FILTER_OUT] = NULL;
540 }
541
542 if (dist->prefix[DISTRIBUTE_IN]) {
543 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
544 if (plist)
545 babel_ifp->prefix[BABEL_FILTER_IN] = plist;
546 else
547 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
548 } else {
549 babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
550 }
551
552 if (dist->prefix[DISTRIBUTE_OUT]) {
553 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
554 if (plist)
555 babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
556 else
557 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
558 } else {
559 babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
560 }
561}
562
Denis Ovsienko3dbda0c2012-01-08 16:52:36 +0400563static void
Paul Jakma57345092011-12-25 17:52:09 +0100564babel_distribute_update_interface (struct interface *ifp)
565{
566 struct distribute *dist;
567
568 dist = distribute_lookup (ifp->name);
569 if (dist)
570 babel_distribute_update (dist);
571}
572
573/* Update all interface's distribute list. */
574static void
575babel_distribute_update_all (struct prefix_list *notused)
576{
577 struct interface *ifp;
578 struct listnode *node;
579
580 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
581 babel_distribute_update_interface (ifp);
582}
583
584static void
585babel_distribute_update_all_wrapper (struct access_list *notused)
586{
587 babel_distribute_update_all(NULL);
588}
589
590
591/* [Command] */
592DEFUN (router_babel,
593 router_babel_cmd,
594 "router babel",
595 "Enable a routing process\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100596 "Make Babel instance command\n"
597 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100598{
599 int ret;
600
601 vty->node = BABEL_NODE;
602
603 if (!babel_routing_process) {
604 ret = babel_create_routing_process ();
605
606 /* Notice to user we couldn't create Babel. */
607 if (ret < 0) {
608 zlog_warn ("can't create Babel");
609 }
610 }
611
612 return CMD_SUCCESS;
613}
614
615/* [Command] */
616DEFUN (no_router_babel,
617 no_router_babel_cmd,
618 "no router babel",
619 NO_STR
620 "Disable a routing process\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100621 "Remove Babel instance command\n"
622 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100623{
624 if(babel_routing_process)
625 babel_clean_routing_process();
626 return CMD_SUCCESS;
627}
628
629/* [Babel Command] */
630DEFUN (babel_set_protocol_group,
631 babel_set_protocol_group_cmd,
632 "protocol group ADDR",
633 "Set the protocol group, default is ff02::1:6.\n"
634 "IPv6 address")
635{
636 int ret;
637 struct prefix p;
638
639 ret = str2prefix (argv[0], &p);
640
641 /* Given string is: */
642 if (ret) { /* an IPv4 or v6 network */
643 if (p.family != AF_INET6) {
644 return CMD_WARNING;
645 }
646 in6addr_to_uchar(protocol_group, &p.u.prefix6);
647 } else { /* an interface name */
648 return CMD_WARNING;
649 }
650
651 if (ret < 0) {
652 vty_out (vty, "%s must be an ipv6 address%s", argv[0],
653 VTY_NEWLINE);
654 return CMD_WARNING;
655 }
656
657 return CMD_SUCCESS;
658}
659
660/* [Babel Command] */
661DEFUN (babel_set_protocol_port,
662 babel_set_protocol_port_cmd,
663 "protocol port <1-65535>",
664 "Set the protocol port (default is defined in RFC).\n"
665 "IPv6 address")
666{
667 int port = atoi(argv[0]);
668 protocol_port = port;
669
670 return CMD_SUCCESS;
671}
672
673
674void
675babeld_quagga_init(void)
676{
677
678 install_node(&cmd_babel_node, &babel_config_write);
679
680 install_element(CONFIG_NODE, &router_babel_cmd);
681 install_element(CONFIG_NODE, &no_router_babel_cmd);
682
683 install_default(BABEL_NODE);
684
685 babel_if_init();
686
687 /* Access list install. */
688 access_list_init ();
689 access_list_add_hook (babel_distribute_update_all_wrapper);
690 access_list_delete_hook (babel_distribute_update_all_wrapper);
691
692 /* Prefix list initialize.*/
693 prefix_list_init ();
694 prefix_list_add_hook (babel_distribute_update_all);
695 prefix_list_delete_hook (babel_distribute_update_all);
696
697 /* Distribute list install. */
698 distribute_list_init (BABEL_NODE);
699 distribute_list_add_hook (babel_distribute_update);
700 distribute_list_delete_hook (babel_distribute_update);
701}
702
703int /* DEPRECATED: for compatibility with old babeld (configuration.{c,h})*/
704input_filter(const unsigned char *id,
705 const unsigned char *prefix, unsigned short plen,
706 const unsigned char *neigh, unsigned int ifindex)
707{
708 struct interface *ifp = NULL;
709 struct prefix p;
710 p.family = v4mapped(prefix) ? AF_INET : AF_INET6;
711 p.prefixlen = plen;
712 if (p.family == AF_INET) {
713 uchar_to_inaddr(&p.u.prefix4, prefix);
714 } else {
715 uchar_to_in6addr(&p.u.prefix6, prefix);
716 }
717
718 ifp = if_lookup_by_index(ifindex);
719 if (ifp != NULL) {
720 return babel_filter_in(&p, babel_get_if_nfo(ifp));
721 }
722
723 return babel_filter_in(&p, NULL);
724}
725
726int /* DEPRECATED: for compatibility with old babeld */
727output_filter(const unsigned char *id, const unsigned char *prefix,
728 unsigned short plen, unsigned int ifindex)
729{
730 struct interface *ifp = NULL;
731 struct prefix p;
732 p.family = v4mapped(prefix) ? AF_INET : AF_INET6;
733 p.prefixlen = plen;
734 if (p.family == AF_INET) {
735 uchar_to_inaddr(&p.u.prefix4, prefix);
736 } else {
737 uchar_to_in6addr(&p.u.prefix6, prefix);
738 }
739
740 ifp = if_lookup_by_index(ifindex);
741 if (ifp != NULL) {
742 return babel_filter_out(&p, babel_get_if_nfo(ifp));
743 }
744
745 return babel_filter_out(&p, NULL);
746}
747
748int /* DEPRECATED: for compatibility with old babeld */
749redistribute_filter(const unsigned char *prefix, unsigned short plen,
750 unsigned int ifindex, int proto)
751{
752 struct interface *ifp = NULL;
753 struct prefix p;
754 p.family = v4mapped(prefix) ? AF_INET : AF_INET6;
755 p.prefixlen = plen;
756 if (p.family == AF_INET) {
757 uchar_to_inaddr(&p.u.prefix4, prefix);
758 } else {
759 uchar_to_in6addr(&p.u.prefix6, prefix);
760 }
761
762 ifp = if_lookup_by_index(ifindex);
763 if (ifp != NULL) {
764 return babel_filter_redistribute(&p,babel_get_if_nfo(ifp));
765 }
766
767 return babel_filter_redistribute(&p, NULL);
768}
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100769
770void
771show_babeld_configuration (struct vty *vty)
772{
773 vty_out(vty, "babeld running process %s.%s",
774 babel_routing_process ? "enable" : "disable", VTY_NEWLINE);
775}