blob: fafe009f8769ce71c0389dbf591fa7714b37ec87 [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
Paul Jakma57345092011-12-25 17:52:09 +010040#include <zebra.h>
41#include "memory.h"
42#include "log.h"
43#include "command.h"
44#include "prefix.h"
45#include "vector.h"
Matthieu Boutierd3351d12012-01-19 22:36:56 +010046#include "distribute.h"
Paul Jakma57345092011-12-25 17:52:09 +010047
48#include "babel_main.h"
49#include "util.h"
50#include "kernel.h"
51#include "babel_interface.h"
52#include "message.h"
53#include "route.h"
54#include "babel_zebra.h"
Matthieu Boutier297a55b2012-01-18 16:39:29 +010055#include "neighbour.h"
Matthieu Boutier1f39f462012-01-18 20:01:31 +010056#include "route.h"
57#include "xroute.h"
Paul Jakma57345092011-12-25 17:52:09 +010058
59
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +010060#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
61
Paul Jakma57345092011-12-25 17:52:09 +010062static int babel_enable_if_lookup (const char *ifname);
63static int babel_enable_if_add (const char *ifname);
64static int babel_enable_if_delete (const char *ifname);
65static int interface_recalculate(struct interface *ifp);
66static int interface_reset(struct interface *ifp);
67static int babel_if_new_hook (struct interface *ifp);
68static int babel_if_delete_hook (struct interface *ifp);
69static int interface_config_write (struct vty *vty);
Matthieu Boutierc7c53fa2012-01-08 16:43:08 +010070static babel_interface_nfo * babel_interface_allocate (void);
Paul Jakma57345092011-12-25 17:52:09 +010071static void babel_interface_free (babel_interface_nfo *bi);
72
73
74static vector babel_enable_if; /* enable interfaces (by cmd). */
75static struct cmd_node babel_interface_node = /* babeld's interface node. */
76{
77 INTERFACE_NODE,
78 "%s(config-if)# ",
79 1 /* VTYSH */
80};
81
82
83int
84babel_interface_up (int cmd, struct zclient *client, zebra_size_t length)
85{
86 struct stream *s = NULL;
87 struct interface *ifp = NULL;
88
89 debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
90
91 s = zclient->ibuf;
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +010092 ifp = zebra_interface_state_read(s); /* it updates iflist */
Paul Jakma57345092011-12-25 17:52:09 +010093
94 if (ifp == NULL) {
95 return 0;
96 }
97
98 interface_recalculate(ifp);
99 return 0;
100}
101
102int
103babel_interface_down (int cmd, struct zclient *client, zebra_size_t length)
104{
105 struct stream *s = NULL;
106 struct interface *ifp = NULL;
107
108 debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
109
110 s = zclient->ibuf;
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100111 ifp = zebra_interface_state_read(s); /* it updates iflist */
Paul Jakma57345092011-12-25 17:52:09 +0100112
113 if (ifp == NULL) {
114 return 0;
115 }
116
117 interface_reset(ifp);
118 return 0;
119}
120
121int
122babel_interface_add (int cmd, struct zclient *client, zebra_size_t length)
123{
124 struct interface *ifp = NULL;
125
126 debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
127
128 /* read and add the interface in the iflist. */
129 ifp = zebra_interface_add_read (zclient->ibuf);
130
131 if (ifp == NULL) {
132 return 0;
133 }
134
135 interface_recalculate(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100136 return 0;
137}
138
139int
140babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length)
141{
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100142 struct interface *ifp;
143 struct stream *s;
144
Paul Jakma57345092011-12-25 17:52:09 +0100145 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100146
147 s = zclient->ibuf;
148 ifp = zebra_interface_state_read(s); /* it updates iflist */
149
150 if (ifp == NULL)
151 return 0;
152
153 if (IS_ENABLE(ifp))
154 interface_reset(ifp);
155
156 /* To support pseudo interface do not free interface structure. */
157 /* if_delete(ifp); */
158 ifp->ifindex = IFINDEX_INTERNAL;
159
Paul Jakma57345092011-12-25 17:52:09 +0100160 return 0;
161}
162
163int
164babel_interface_address_add (int cmd, struct zclient *client,
165 zebra_size_t length)
166{
167 babel_interface_nfo *babel_ifp;
168 struct connected *ifc;
169 struct prefix *prefix;
170
171 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
172
173 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
174 zclient->ibuf);
175
176 if (ifc == NULL)
177 return 0;
178
179 prefix = ifc->address;
180
181 if (prefix->family == AF_INET) {
182 flush_interface_routes(ifc->ifp, 0);
183 babel_ifp = babel_get_if_nfo(ifc->ifp);
184 if (babel_ifp->ipv4 == NULL) {
185 babel_ifp->ipv4 = malloc(4);
186 if (babel_ifp->ipv4 == NULL) {
187 zlog_err("not einough memory");
188 } else {
189 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
190 }
191 }
192 }
193
194 send_request(ifc->ifp, NULL, 0);
195 send_update(ifc->ifp, 0, NULL, 0);
196
197 return 0;
198}
199
200int
201babel_interface_address_delete (int cmd, struct zclient *client,
202 zebra_size_t length)
203{
204 babel_interface_nfo *babel_ifp;
205 struct connected *ifc;
206 struct prefix *prefix;
207
208 debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
209
210 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
211 zclient->ibuf);
212
213 if (ifc == NULL)
214 return 0;
215
216 prefix = ifc->address;
217
218 if (prefix->family == AF_INET) {
219 flush_interface_routes(ifc->ifp, 0);
220 babel_ifp = babel_get_if_nfo(ifc->ifp);
221 if (babel_ifp->ipv4 != NULL
222 && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
223 free(babel_ifp->ipv4);
224 babel_ifp->ipv4 = NULL;
225 }
226 }
227
228 send_request(ifc->ifp, NULL, 0);
229 send_update(ifc->ifp, 0, NULL, 0);
230
231 return 0;
232}
233
234/* Lookup function. */
235static int
236babel_enable_if_lookup (const char *ifname)
237{
238 unsigned int i;
239 char *str;
240
241 for (i = 0; i < vector_active (babel_enable_if); i++)
242 if ((str = vector_slot (babel_enable_if, i)) != NULL)
243 if (strcmp (str, ifname) == 0)
244 return i;
245 return -1;
246}
247
248/* Add interface to babel_enable_if. */
249static int
250babel_enable_if_add (const char *ifname)
251{
252 int ret;
253 struct interface *ifp = NULL;
254
255 ret = babel_enable_if_lookup (ifname);
256 if (ret >= 0)
257 return -1;
258
259 vector_set (babel_enable_if, strdup (ifname));
260
261 ifp = if_lookup_by_name(ifname);
262 if (ifp != NULL)
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100263 interface_recalculate(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100264
265 return 1;
266}
267
268/* Delete interface from babel_enable_if. */
269static int
270babel_enable_if_delete (const char *ifname)
271{
272 int babel_enable_if_index;
273 char *str;
274 struct interface *ifp = NULL;
275
276 babel_enable_if_index = babel_enable_if_lookup (ifname);
277 if (babel_enable_if_index < 0)
278 return -1;
279
280 str = vector_slot (babel_enable_if, babel_enable_if_index);
281 free (str);
282 vector_unset (babel_enable_if, babel_enable_if_index);
283
284 ifp = if_lookup_by_name(ifname);
285 if (ifp != NULL)
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100286 interface_reset(ifp);
Paul Jakma57345092011-12-25 17:52:09 +0100287
288 return 1;
289}
290
291
292/* [Babel Command] Babel enable on specified interface or matched network. */
293DEFUN (babel_network,
294 babel_network_cmd,
295 "network IF_OR_ADDR",
296 "Babel enable on specified interface or network.\n"
297 "Interface or address")
298{
299 int ret;
300 struct prefix p;
301
302 ret = str2prefix (argv[0], &p);
303
304 /* Given string is: */
305 if (ret) /* an IPv4 or v6 network */
306 return CMD_ERR_NO_MATCH; /* not implemented yet */
307 else /* an interface name */
308 ret = babel_enable_if_add (argv[0]);
309
310 if (ret < 0) {
311 vty_out (vty, "There is same network configuration %s%s", argv[0],
312 VTY_NEWLINE);
313 return CMD_WARNING;
314 }
315
316 return CMD_SUCCESS;
317}
318
319/* [Babel Command] Babel enable on specified interface or matched network. */
320DEFUN (no_babel_network,
321 no_babel_network_cmd,
322 "no network IF_OR_ADDR",
323 NO_STR
324 "Babel enable on specified interface or network.\n"
325 "Interface or address")
326{
327 int ret;
328 struct prefix p;
329
330 ret = str2prefix (argv[0], &p);
331
332 /* Given string is: */
333 if (ret) /* an IPv4 or v6 network */
334 return CMD_ERR_NO_MATCH; /* not implemented yet */
335 else /* an interface name */
336 ret = babel_enable_if_delete (argv[0]);
337
338 if (ret < 0) {
339 vty_out (vty, "can't find network %s%s", argv[0],
340 VTY_NEWLINE);
341 return CMD_WARNING;
342 }
343
344 return CMD_SUCCESS;
345}
346
347/* [Interface Command] Tell the interface is wire. */
348DEFUN (babel_set_wired,
349 babel_set_wired_cmd,
350 "wired",
351 "Set this interface as wired (default: wireless).\n"
352 "No attributes")
353{
354 struct interface *ifp;
355 babel_interface_nfo *babel_ifp;
356
357 ifp = vty->index;
358 babel_ifp = babel_get_if_nfo(ifp);
359
360 assert (babel_ifp != NULL);
361 babel_ifp->flags |= BABEL_IF_WIRED;
362 return CMD_SUCCESS;
363}
364
365/* [Interface Command] Tell the interface is wireless (default). */
366DEFUN (babel_set_wireless,
367 babel_set_wireless_cmd,
368 "wireless",
369 NO_STR
370 "Set this interface as wireless (is default).\n"
371 "No attributes")
372{
373 struct interface *ifp;
374 babel_interface_nfo *babel_ifp;
375
376 ifp = vty->index;
377 babel_ifp = babel_get_if_nfo(ifp);
378
379 assert (babel_ifp != NULL);
380 babel_ifp->flags &= ~BABEL_IF_WIRED;
381 return CMD_SUCCESS;
382}
383
384/* [Interface Command] Enable split horizon. */
385DEFUN (babel_split_horizon,
386 babel_split_horizon_cmd,
387 "babel split-horizon",
388 IPV6_STR
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100389 "Perform split horizon\n"
390 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100391{
392 struct interface *ifp;
393 babel_interface_nfo *babel_ifp;
394
395 ifp = vty->index;
396 babel_ifp = babel_get_if_nfo(ifp);
397
398 assert (babel_ifp != NULL);
399 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
400 return CMD_SUCCESS;
401}
402
403/* [Interface Command] Disable split horizon (default). */
404DEFUN (no_babel_split_horizon,
405 no_babel_split_horizon_cmd,
406 "no babel split-horizon",
407 NO_STR
408 IPV6_STR
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100409 "Disable split horizon\n"
410 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100411{
412 struct interface *ifp;
413 babel_interface_nfo *babel_ifp;
414
415 ifp = vty->index;
416 babel_ifp = babel_get_if_nfo(ifp);
417
418 assert (babel_ifp != NULL);
419 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
420 return CMD_SUCCESS;
421}
422
423/* [Interface Command]. */
424DEFUN (babel_set_hello_interval,
425 babel_set_hello_interval_cmd,
426 "hello interval <5-1000000>",
427 "Set interface's hello interval (default: 4000).\n"
428 "Value in miliseconds\n")
429{
430 struct interface *ifp;
431 babel_interface_nfo *babel_ifp;
432
433 int interval = atoi(argv[1]);
434
435 ifp = vty->index;
436 babel_ifp = babel_get_if_nfo(ifp);
437
438 assert (babel_ifp != NULL);
439 babel_ifp->hello_interval = interval;
440 return CMD_SUCCESS;
441}
442
443/* [Interface Command]. */
444DEFUN (babel_passive_interface,
445 babel_passive_interface_cmd,
446 "passive-interface",
447 "The daemon will only announce redistributed routes\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100448 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100449{
450 if (allow_duplicates) {
451 return CMD_WARNING;
452 }
453 parasitic = -1;
454 return CMD_SUCCESS;
455}
456
457/* [Interface Command]. */
458DEFUN (no_babel_passive_interface,
459 no_babel_passive_interface_cmd,
460 "no passive-interface",
461 NO_STR
462 "The daemon will announce all (filtred) routes\n"
Matthieu Boutier3f031ed2012-01-18 23:03:00 +0100463 "No attributes\n")
Paul Jakma57345092011-12-25 17:52:09 +0100464{
465 parasitic = 0;
466 return CMD_SUCCESS;
467}
468
469
470int
471interface_idle(babel_interface_nfo *babel_ifp)
472{
473 return (idle_hello_interval > 0 &&
474 babel_ifp->activity_time < babel_now.tv_sec - idle_time);
475}
476
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100477int
478update_hello_interval(struct interface *ifp)
479{
480 int rc = 0;
481 unsigned short interval;
482 struct babel_interface *babel_ifp = babel_get_if_nfo(ifp);
483
484 if(interface_idle(babel_ifp))
485 interval = idle_hello_interval;
486 else if(IF_CONF(ifp, hello_interval) > 0)
487 interval = IF_CONF(ifp, hello_interval);
488 else if((ifp->flags & BABEL_IF_WIRED))
489 interval = wired_hello_interval;
490 else
491 interval = wireless_hello_interval;
492
493 if(babel_ifp->hello_interval != interval) {
494 babel_ifp->hello_interval = interval;
495 rc = 1;
496 }
497
498 return rc;
499}
500
Paul Jakma57345092011-12-25 17:52:09 +0100501/* This should be no more than half the hello interval, so that hellos
502 aren't sent late. The result is in milliseconds. */
503unsigned
504jitter(babel_interface_nfo *babel_ifp, int urgent)
505{
506 unsigned interval = babel_ifp->hello_interval;
507 if(urgent)
508 interval = MIN(interval, 100);
509 else
510 interval = MIN(interval, 4000);
511 return roughly(interval) / 4;
512}
513
514unsigned
515update_jitter(babel_interface_nfo *babel_ifp, int urgent)
516{
517 unsigned interval = babel_ifp->hello_interval;
518 if(urgent)
519 interval = MIN(interval, 100);
520 else
521 interval = MIN(interval, 4000);
522 return roughly(interval);
523}
524
525/* calculate babeld's specific datas of an interface (change when the interface
526 change) */
527static int
528interface_recalculate(struct interface *ifp)
529{
530 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
531 unsigned char *tmp = NULL;
532 int mtu, rc;
533 struct ipv6_mreq mreq;
534
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100535 if (!IS_ENABLE(ifp))
536 return -1;
537
Matthieu Boutier0ee8a1f2012-01-18 00:52:06 +0100538 if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
539 interface_reset(ifp);
540 return -1;
541 }
542
543 babel_ifp->flags |= BABEL_IF_IS_UP;
544
Paul Jakma57345092011-12-25 17:52:09 +0100545 mtu = MIN(ifp->mtu, ifp->mtu6);
546
547 /* We need to be able to fit at least two messages into a packet,
548 so MTUs below 116 require lower layer fragmentation. */
549 /* In IPv6, the minimum MTU is 1280, and every host must be able
550 to reassemble up to 1500 bytes, but I'd rather not rely on this. */
551 if(mtu < 128) {
552 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
553 mtu, ifp->name, ifp->ifindex);
554 mtu = 128;
555 }
556
557 /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
558 babel_ifp->bufsize = mtu - sizeof(packet_header) - 60;
559 tmp = babel_ifp->sendbuf;
560 babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
561 if(babel_ifp->sendbuf == NULL) {
Matthieu Boutier4eedea52012-01-17 22:46:21 +0100562 zlog_err("Couldn't reallocate sendbuf.");
Paul Jakma57345092011-12-25 17:52:09 +0100563 free(tmp);
564 babel_ifp->bufsize = 0;
565 return -1;
566 }
567 tmp = NULL;
568
569 resize_receive_buffer(mtu);
570
571 if(!(babel_ifp->flags & BABEL_IF_WIRED)) { /* if (wired) */
572 babel_ifp->cost = 96;
573 babel_ifp->flags &= ~BABEL_IF_LQ;
574 } else {
575 babel_ifp->cost = 256;
576 babel_ifp->flags |= BABEL_IF_LQ;
577 }
578
579 babel_ifp->activity_time = babel_now.tv_sec;
580 /* Since the interface was marked as active above, the
581 idle_hello_interval cannot be the one being used here. */
582 babel_ifp->update_interval = babel_ifp->hello_interval * 4;
583
584 memset(&mreq, 0, sizeof(mreq));
585 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
586 mreq.ipv6mr_interface = ifp->ifindex;
587
588 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
589 (char*)&mreq, sizeof(mreq));
590 if(rc < 0) {
591 zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
592 ifp->name, safe_strerror(errno));
593 /* This is probably due to a missing link-local address,
594 so down this interface, and wait until the main loop
595 tries to up it again. */
596 interface_reset(ifp);
597 return -1;
598 }
599
600 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
601 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
602 send_hello(ifp);
603 send_request(ifp, NULL, 0);
604
605 update_interface_metric(ifp);
606
607 debugf(BABEL_DEBUG_COMMON,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100608 "Upped interface %s (%s, cost=%d, channel=%d%s).",
Paul Jakma57345092011-12-25 17:52:09 +0100609 ifp->name,
610 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
611 babel_ifp->cost,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100612 babel_ifp->channel,
Paul Jakma57345092011-12-25 17:52:09 +0100613 babel_ifp->ipv4 ? ", IPv4" : "");
614
615 if(rc > 0)
616 send_update(ifp, 0, NULL, 0);
617
Paul Jakma57345092011-12-25 17:52:09 +0100618 return 1;
619}
620
621/* Reset the interface as it was new: it's not removed from the interface list,
622 and may be considered as a upped interface. */
623static int
624interface_reset(struct interface *ifp)
625{
626 int rc;
627 struct ipv6_mreq mreq;
628 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
629
Matthieu Boutier8c4e57a2012-01-28 00:29:51 +0100630 if (!(babel_ifp->flags & BABEL_IF_IS_UP))
631 return 0;
632
Matthieu Boutier0ee8a1f2012-01-18 00:52:06 +0100633 debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
634 babel_ifp->flags &= ~BABEL_IF_IS_UP;
635
Paul Jakma57345092011-12-25 17:52:09 +0100636 flush_interface_routes(ifp, 0);
637 babel_ifp->buffered = 0;
638 babel_ifp->bufsize = 0;
639 free(babel_ifp->sendbuf);
640 babel_ifp->num_buffered_updates = 0;
641 babel_ifp->update_bufsize = 0;
642 if(babel_ifp->buffered_updates)
643 free(babel_ifp->buffered_updates);
644 babel_ifp->buffered_updates = NULL;
645 babel_ifp->sendbuf = NULL;
646
647 if(ifp->ifindex > 0) {
648 memset(&mreq, 0, sizeof(mreq));
649 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
650 mreq.ipv6mr_interface = ifp->ifindex;
651 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
652 (char*)&mreq, sizeof(mreq));
653 if(rc < 0)
654 zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
655 ifp->name, safe_strerror(errno));
656 }
657
658 update_interface_metric(ifp);
659
660 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
661 ifp->name,
662 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
663 babel_ifp->cost,
664 babel_ifp->ipv4 ? ", IPv4" : "");
665
666 return 1;
667}
668
669/* Send retraction to all, and reset all interfaces statistics. */
670void
671babel_interface_close_all(void)
672{
673 struct interface *ifp = NULL;
674 struct listnode *linklist_node = NULL;
675
676 FOR_ALL_INTERFACES(ifp, linklist_node) {
677 if(!if_up(ifp))
678 continue;
679 send_wildcard_retraction(ifp);
680 /* Make sure that we expire quickly from our neighbours'
681 association caches. */
682 send_hello_noupdate(ifp, 10);
683 flushbuf(ifp);
684 usleep(roughly(1000));
685 gettime(&babel_now);
686 }
687 FOR_ALL_INTERFACES(ifp, linklist_node) {
688 if(!if_up(ifp))
689 continue;
690 /* Make sure they got it. */
691 send_wildcard_retraction(ifp);
692 send_hello_noupdate(ifp, 1);
693 flushbuf(ifp);
694 usleep(roughly(10000));
695 gettime(&babel_now);
696 interface_reset(ifp);
697 }
698}
699
700/* return "true" if address is one of our ipv6 addresses */
701int
702is_interface_ll_address(struct interface *ifp, const unsigned char *address)
703{
704 struct connected *connected;
705 struct listnode *node;
706
707 if(!if_up(ifp))
708 return 0;
709
710 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
711 if(connected->address->family == AF_INET6 &&
712 memcmp(&connected->address->u.prefix6, address, 16) == 0)
713 return 1;
714 }
715
716 return 0;
717}
718
Denis Ovsienkod4e46e62012-01-17 19:25:03 +0400719static void
720show_babel_interface_sub (struct vty *vty, struct interface *ifp)
721{
722 int is_up;
723 babel_interface_nfo *babel_ifp;
724
725 vty_out (vty, "%s is %s%s", ifp->name,
726 ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE);
727 vty_out (vty, " ifindex %u, MTU %u bytes %s%s",
728 ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE);
729
730 if (babel_enable_if_lookup (ifp->name) < 0)
731 {
732 vty_out (vty, " Babel protocol is not enabled on this interface%s", VTY_NEWLINE);
733 return;
734 }
735 if (!is_up)
736 {
737 vty_out (vty, " Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE);
738 return;
739 }
740 babel_ifp = babel_get_if_nfo (ifp);
741 vty_out (vty, " Babel protocol is running on this interface%s", VTY_NEWLINE);
742 vty_out (vty, " Operating mode is \"%s\"%s",
743 CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE);
744 vty_out (vty, " Split horizon mode is %s%s",
745 CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE);
746 vty_out (vty, " Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE);
747}
748
749DEFUN (show_babel_interface,
750 show_babel_interface_cmd,
751 "show babel interface [INTERFACE]",
752 SHOW_STR
753 IP_STR
754 "Babel information\n"
755 "Interface information\n"
756 "Interface name\n")
757{
758 struct interface *ifp;
759 struct listnode *node;
760
761 if (argc == 0)
762 {
763 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
764 show_babel_interface_sub (vty, ifp);
765 return CMD_SUCCESS;
766 }
767 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
768 {
769 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
770 return CMD_WARNING;
771 }
772 show_babel_interface_sub (vty, ifp);
773 return CMD_SUCCESS;
774}
Paul Jakma57345092011-12-25 17:52:09 +0100775
Matthieu Boutier297a55b2012-01-18 16:39:29 +0100776static void
777show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
778{
779 vty_out (vty,
780 "Neighbour %s dev %s reach %04x rxcost %d txcost %d %s.%s",
781 format_address(neigh->address),
782 neigh->ifp->name,
783 neigh->reach,
784 neighbour_rxcost(neigh),
785 neigh->txcost,
786 if_up(neigh->ifp) ? "" : " (down)",
787 VTY_NEWLINE);
788}
789
790DEFUN (show_babel_neighbour,
791 show_babel_neighbour_cmd,
792 "show babel neighbour [INTERFACE]",
793 SHOW_STR
794 IP_STR
795 "Babel information\n"
796 "Print neighbours\n"
797 "Interface name\n")
798{
799 struct neighbour *neigh;
800 struct interface *ifp;
801
802 if (argc == 0) {
803 FOR_ALL_NEIGHBOURS(neigh) {
804 show_babel_neighbour_sub(vty, neigh);
805 }
806 return CMD_SUCCESS;
807 }
808 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
809 {
810 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
811 return CMD_WARNING;
812 }
813 FOR_ALL_NEIGHBOURS(neigh) {
814 if(ifp->ifindex == neigh->ifp->ifindex) {
815 show_babel_neighbour_sub(vty, neigh);
816 }
817 }
818 return CMD_SUCCESS;
819}
820
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100821static void
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100822show_babel_routes_sub (struct babel_route *route, void *closure)
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100823{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100824 struct vty *vty = (struct vty*) closure;
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100825 const unsigned char *nexthop =
826 memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
827 NULL : route->nexthop;
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100828 char channels[100];
829
830 if(route->channels[0] == 0)
831 channels[0] = '\0';
832 else {
833 int k, j = 0;
834 snprintf(channels, 100, " chan (");
835 j = strlen(channels);
836 for(k = 0; k < DIVERSITY_HOPS; k++) {
837 if(route->channels[k] == 0)
838 break;
839 if(k > 0)
840 channels[j++] = ',';
841 snprintf(channels + j, 100 - j, "%d", route->channels[k]);
842 j = strlen(channels);
843 }
844 snprintf(channels + j, 100 - j, ")");
845 if(k == 0)
846 channels[0] = '\0';
847 }
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100848
849 vty_out(vty,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100850 "%s metric %d refmetric %d id %s seqno %d%s age %d "
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100851 "via %s neigh %s%s%s%s%s",
852 format_prefix(route->src->prefix, route->src->plen),
853 route_metric(route), route->refmetric,
854 format_eui64(route->src->id),
855 (int)route->seqno,
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100856 channels,
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100857 (int)(babel_now.tv_sec - route->time),
858 route->neigh->ifp->name,
859 format_address(route->neigh->address),
860 nexthop ? " nexthop " : "",
861 nexthop ? format_address(nexthop) : "",
862 route->installed ? " (installed)" :
863 route_feasible(route) ? " (feasible)" : "",
864 VTY_NEWLINE);
865}
866
867static void
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100868show_babel_xroutes_sub (struct xroute *xroute, void *closure)
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100869{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100870 struct vty *vty = (struct vty *) closure;
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100871 vty_out(vty, "%s metric %d (exported)%s",
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100872 format_prefix(xroute->prefix, xroute->plen),
873 xroute->metric,
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100874 VTY_NEWLINE);
875}
876
877DEFUN (show_babel_database,
878 show_babel_database_cmd,
879 "show babel database",
880 SHOW_STR
881 IP_STR
882 "Babel information\n"
883 "Database information\n"
884 "No attributes\n")
885{
Matthieu Boutierc35fafd2012-01-23 23:46:32 +0100886 for_all_routes(show_babel_routes_sub, vty);
887 for_all_xroutes(show_babel_xroutes_sub, vty);
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100888 return CMD_SUCCESS;
889}
890
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100891DEFUN (show_babel_running_config,
892 show_babel_running_config_cmd,
893 "show babel running-config",
894 SHOW_STR
895 IP_STR
896 "Babel information\n"
897 "Configuration information\n"
898 "No attributes\n")
899{
900 vty_out(vty, " -- Babel running configuration --%s", VTY_NEWLINE);
901 show_babel_main_configuration(vty);
902 show_babeld_configuration(vty);
903 vty_out(vty, " -- ditribution lists --%s", VTY_NEWLINE);
904 config_show_distribute(vty);
905
906 return CMD_SUCCESS;
907}
908
Paul Jakma57345092011-12-25 17:52:09 +0100909void
910babel_if_init ()
911{
912 /* initialize interface list */
913 if_init();
914 if_add_hook (IF_NEW_HOOK, babel_if_new_hook);
915 if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);
916
917 babel_enable_if = vector_init (1);
918
919 /* install interface node and commands */
920 install_element (CONFIG_NODE, &interface_cmd);
921 install_element (CONFIG_NODE, &no_interface_cmd);
922 install_node (&babel_interface_node, interface_config_write);
923 install_default(INTERFACE_NODE);
924 install_element(INTERFACE_NODE, &interface_cmd);
925 install_element(INTERFACE_NODE, &no_interface_cmd);
926
927 install_element(BABEL_NODE, &babel_network_cmd);
928 install_element(BABEL_NODE, &no_babel_network_cmd);
929 install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
930 install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
931 install_element(INTERFACE_NODE, &babel_set_wired_cmd);
932 install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
933 install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
934 install_element(INTERFACE_NODE, &babel_passive_interface_cmd);
935 install_element(INTERFACE_NODE, &no_babel_passive_interface_cmd);
Denis Ovsienkod4e46e62012-01-17 19:25:03 +0400936
937 /* "show babel ..." commands */
938 install_element (VIEW_NODE, &show_babel_interface_cmd);
939 install_element (ENABLE_NODE, &show_babel_interface_cmd);
Matthieu Boutier297a55b2012-01-18 16:39:29 +0100940 install_element(VIEW_NODE, &show_babel_neighbour_cmd);
941 install_element(ENABLE_NODE, &show_babel_neighbour_cmd);
Matthieu Boutier1f39f462012-01-18 20:01:31 +0100942 install_element(VIEW_NODE, &show_babel_database_cmd);
943 install_element(ENABLE_NODE, &show_babel_database_cmd);
Matthieu Boutierd3351d12012-01-19 22:36:56 +0100944 install_element(VIEW_NODE, &show_babel_running_config_cmd);
945 install_element(ENABLE_NODE, &show_babel_running_config_cmd);
Paul Jakma57345092011-12-25 17:52:09 +0100946}
947
948/* hooks: functions called respectively when struct interface is
949 created or deleted. */
950static int
951babel_if_new_hook (struct interface *ifp)
952{
953 ifp->info = babel_interface_allocate();
954 return 0;
955}
956
957static int
958babel_if_delete_hook (struct interface *ifp)
959{
960 babel_interface_free(ifp->info);
961 ifp->info = NULL;
962 return 0;
963}
964
965/* Configuration write function for babeld. */
966static int
967interface_config_write (struct vty *vty)
968{
969 struct listnode *node;
970 struct interface *ifp;
Paul Jakma57345092011-12-25 17:52:09 +0100971 int write = 0;
972
973 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) {
Paul Jakma57345092011-12-25 17:52:09 +0100974 /* Do not display the interface if there is no configuration about it */
975 if (ifp->desc == NULL)
976 continue;
977
978 vty_out (vty, "interface %s%s", ifp->name,
979 VTY_NEWLINE);
980 if (ifp->desc)
981 vty_out (vty, " description %s%s", ifp->desc,
982 VTY_NEWLINE);
983
984 /* TODO: to be completed... */
985
986 vty_out (vty, "!%s", VTY_NEWLINE);
987
988 write++;
989 }
990 return write;
991}
992
993/* functions to allocate or free memory for a babel_interface_nfo, filling
994 needed fields */
995static babel_interface_nfo *
Matthieu Boutierc7c53fa2012-01-08 16:43:08 +0100996babel_interface_allocate (void)
Paul Jakma57345092011-12-25 17:52:09 +0100997{
998 babel_interface_nfo *babel_ifp;
999 babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
1000 if(babel_ifp == NULL)
1001 return NULL;
1002
1003 /* Here are set the default values for an interface. */
1004 memset(babel_ifp, 0, sizeof(babel_interface_nfo));
1005 /* All flags are unset */
1006 babel_ifp->activity_time = babel_now.tv_sec;
1007 babel_ifp->bucket_time = babel_now.tv_sec;
1008 babel_ifp->bucket = BUCKET_TOKENS_MAX;
1009 babel_ifp->hello_seqno = (random() & 0xFFFF);
1010 babel_ifp->hello_interval = BABELD_DEFAULT_HELLO_INTERVAL;
Matthieu Boutierc35fafd2012-01-23 23:46:32 +01001011 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
Paul Jakma57345092011-12-25 17:52:09 +01001012
1013 return babel_ifp;
1014}
1015
1016static void
1017babel_interface_free (babel_interface_nfo *babel_ifp)
1018{
1019 XFREE(MTYPE_BABEL_IF, babel_ifp);
1020}