1/* 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 "memory.h" 42#include "log.h" 43#include "command.h" 44#include "prefix.h" 45#include "vector.h" 46#include "distribute.h" 47 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" 55#include "neighbour.h" 56#include "route.h" 57#include "xroute.h" 58 59 60#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0) 61 62static 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); 70static babel_interface_nfo * babel_interface_allocate (void); 71static 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; 92 ifp = zebra_interface_state_read(s); /* it updates iflist */ 93 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; 111 ifp = zebra_interface_state_read(s); /* it updates iflist */ 112 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); 136 return 0; 137} 138 139int 140babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length) 141{ 142 struct interface *ifp; 143 struct stream *s; 144 145 debugf(BABEL_DEBUG_IF, "receive a 'interface delete'"); 146 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 160 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) 263 interface_recalculate(ifp); 264 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) 286 interface_reset(ifp); 287 288 return 1; 289} 290 291/* [Babel Command] Babel enable on specified interface or matched network. */ 292DEFUN (babel_network, 293 babel_network_cmd, 294 "network IF_OR_ADDR", 295 "Enable Babel protocol on specified interface or network.\n" 296 "Interface or address") 297{ 298 int ret; 299 struct prefix p; 300 301 ret = str2prefix (argv[0], &p); 302 303 /* Given string is: */ 304 if (ret) /* an IPv4 or v6 network */ 305 return CMD_ERR_NO_MATCH; /* not implemented yet */ 306 else /* an interface name */ 307 ret = babel_enable_if_add (argv[0]); 308 309 if (ret < 0) { 310 vty_out (vty, "There is same network configuration %s%s", argv[0], 311 VTY_NEWLINE); 312 return CMD_WARNING; 313 } 314 315 return CMD_SUCCESS; 316} 317 318/* [Babel Command] Babel enable on specified interface or matched network. */ 319DEFUN (no_babel_network, 320 no_babel_network_cmd, 321 "no network IF_OR_ADDR", 322 NO_STR 323 "Disable Babel protocol on specified interface or network.\n" 324 "Interface or address") 325{ 326 int ret; 327 struct prefix p; 328 329 ret = str2prefix (argv[0], &p); 330 331 /* Given string is: */ 332 if (ret) /* an IPv4 or v6 network */ 333 return CMD_ERR_NO_MATCH; /* not implemented yet */ 334 else /* an interface name */ 335 ret = babel_enable_if_delete (argv[0]); 336 337 if (ret < 0) { 338 vty_out (vty, "can't find network %s%s", argv[0], 339 VTY_NEWLINE); 340 return CMD_WARNING; 341 } 342 343 return CMD_SUCCESS; 344} 345 346/* There are a number of interface parameters that must be changed when 347 an interface becomes wired/wireless. In Quagga, they cannot be 348 configured separately. */ 349 350static void 351babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired) 352{ 353 if(wired) { 354 babel_ifp->flags |= BABEL_IF_WIRED; 355 babel_ifp->cost = 96; 356 babel_ifp->flags &= ~BABEL_IF_LQ; 357 } else { 358 babel_ifp->flags &= ~BABEL_IF_WIRED; 359 babel_ifp->cost = 256; 360 babel_ifp->flags |= BABEL_IF_LQ; 361 } 362 363} 364 365/* [Interface Command] Tell the interface is wire. */ 366DEFUN (babel_set_wired, 367 babel_set_wired_cmd, 368 "babel wired", 369 "Babel interface commands\n" 370 "Enable wired optimisations") 371{ 372 struct interface *ifp; 373 babel_interface_nfo *babel_ifp; 374 375 ifp = vty->index; 376 babel_ifp = babel_get_if_nfo(ifp); 377 378 assert (babel_ifp != NULL); 379 babel_set_wired_internal(babel_ifp, 1); 380 return CMD_SUCCESS; 381} 382 383/* [Interface Command] Tell the interface is wireless (default). */ 384DEFUN (babel_set_wireless, 385 babel_set_wireless_cmd, 386 "babel wireless", 387 "Babel interface commands\n" 388 "Disable wired optimiations (assume wireless)") 389{ 390 struct interface *ifp; 391 babel_interface_nfo *babel_ifp; 392 393 ifp = vty->index; 394 babel_ifp = babel_get_if_nfo(ifp); 395 396 assert (babel_ifp != NULL); 397 babel_set_wired_internal(babel_ifp, 0); 398 return CMD_SUCCESS; 399} 400 401/* [Interface Command] Enable split horizon. */ 402DEFUN (babel_split_horizon, 403 babel_split_horizon_cmd, 404 "babel split-horizon", 405 "Babel interface commands\n" 406 "Enable split horizon processing") 407{ 408 struct interface *ifp; 409 babel_interface_nfo *babel_ifp; 410 411 ifp = vty->index; 412 babel_ifp = babel_get_if_nfo(ifp); 413 414 assert (babel_ifp != NULL); 415 babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON; 416 return CMD_SUCCESS; 417} 418 419/* [Interface Command] Disable split horizon (default). */ 420DEFUN (no_babel_split_horizon, 421 no_babel_split_horizon_cmd, 422 "no babel split-horizon", 423 NO_STR 424 "Babel interface commands\n" 425 "Disable split horizon processing") 426{ 427 struct interface *ifp; 428 babel_interface_nfo *babel_ifp; 429 430 ifp = vty->index; 431 babel_ifp = babel_get_if_nfo(ifp); 432 433 assert (babel_ifp != NULL); 434 babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON; 435 return CMD_SUCCESS; 436} 437 438/* [Interface Command]. */ 439DEFUN (babel_set_hello_interval, 440 babel_set_hello_interval_cmd, 441 "babel hello-interval <20-655340>", 442 "Babel interface commands\n" 443 "Time between scheduled hellos\n" 444 "Milliseconds\n") 445{ 446 struct interface *ifp; 447 babel_interface_nfo *babel_ifp; 448 int interval; 449 450 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE); 451 452 ifp = vty->index; 453 babel_ifp = babel_get_if_nfo(ifp); 454 assert (babel_ifp != NULL); 455 456 babel_ifp->hello_interval = interval; 457 return CMD_SUCCESS; 458} 459 460/* [Interface Command]. */ 461DEFUN (babel_set_update_interval, 462 babel_set_update_interval_cmd, 463 "babel update-interval <20-655340>", 464 "Babel interface commands\n" 465 "Time between scheduled updates\n" 466 "Milliseconds\n") 467{ 468 struct interface *ifp; 469 babel_interface_nfo *babel_ifp; 470 int interval; 471 472 VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE); 473 474 ifp = vty->index; 475 babel_ifp = babel_get_if_nfo(ifp); 476 assert (babel_ifp != NULL); 477 478 babel_ifp->update_interval = interval; 479 return CMD_SUCCESS; 480} 481 482/* This should be no more than half the hello interval, so that hellos 483 aren't sent late. The result is in milliseconds. */ 484unsigned 485jitter(babel_interface_nfo *babel_ifp, int urgent) 486{ 487 unsigned interval = babel_ifp->hello_interval; 488 if(urgent) 489 interval = MIN(interval, 100); 490 else 491 interval = MIN(interval, 4000); 492 return roughly(interval) / 4; 493} 494 495unsigned 496update_jitter(babel_interface_nfo *babel_ifp, int urgent) 497{ 498 unsigned interval = babel_ifp->hello_interval; 499 if(urgent) 500 interval = MIN(interval, 100); 501 else 502 interval = MIN(interval, 4000); 503 return roughly(interval); 504} 505 506/* calculate babeld's specific datas of an interface (change when the interface 507 change) */ 508static int 509interface_recalculate(struct interface *ifp) 510{ 511 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); 512 unsigned char *tmp = NULL; 513 int mtu, rc; 514 struct ipv6_mreq mreq; 515 516 if (!IS_ENABLE(ifp)) 517 return -1; 518 519 if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) { 520 interface_reset(ifp); 521 return -1; 522 } 523 524 babel_ifp->flags |= BABEL_IF_IS_UP; 525 526 mtu = MIN(ifp->mtu, ifp->mtu6); 527 528 /* We need to be able to fit at least two messages into a packet, 529 so MTUs below 116 require lower layer fragmentation. */ 530 /* In IPv6, the minimum MTU is 1280, and every host must be able 531 to reassemble up to 1500 bytes, but I'd rather not rely on this. */ 532 if(mtu < 128) { 533 debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).", 534 mtu, ifp->name, ifp->ifindex); 535 mtu = 128; 536 } 537 538 /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */ 539 babel_ifp->bufsize = mtu - sizeof(packet_header) - 60; 540 tmp = babel_ifp->sendbuf; 541 babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize); 542 if(babel_ifp->sendbuf == NULL) { 543 zlog_err("Couldn't reallocate sendbuf."); 544 free(tmp); 545 babel_ifp->bufsize = 0; 546 return -1; 547 } 548 tmp = NULL; 549 550 resize_receive_buffer(mtu); 551 552 memset(&mreq, 0, sizeof(mreq)); 553 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16); 554 mreq.ipv6mr_interface = ifp->ifindex; 555 556 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, 557 (char*)&mreq, sizeof(mreq)); 558 if(rc < 0) { 559 zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s", 560 ifp->name, safe_strerror(errno)); 561 /* This is probably due to a missing link-local address, 562 so down this interface, and wait until the main loop 563 tries to up it again. */ 564 interface_reset(ifp); 565 return -1; 566 } 567 568 set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval); 569 set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval); 570 send_hello(ifp); 571 send_request(ifp, NULL, 0); 572 573 update_interface_metric(ifp); 574 575 debugf(BABEL_DEBUG_COMMON, 576 "Upped interface %s (%s, cost=%d, channel=%d%s).", 577 ifp->name, 578 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless", 579 babel_ifp->cost, 580 babel_ifp->channel, 581 babel_ifp->ipv4 ? ", IPv4" : ""); 582 583 if(rc > 0) 584 send_update(ifp, 0, NULL, 0); 585 586 return 1; 587} 588 589/* Reset the interface as it was new: it's not removed from the interface list, 590 and may be considered as a upped interface. */ 591static int 592interface_reset(struct interface *ifp) 593{ 594 int rc; 595 struct ipv6_mreq mreq; 596 babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); 597 598 if (!(babel_ifp->flags & BABEL_IF_IS_UP)) 599 return 0; 600 601 debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name); 602 babel_ifp->flags &= ~BABEL_IF_IS_UP; 603 604 flush_interface_routes(ifp, 0); 605 babel_ifp->buffered = 0; 606 babel_ifp->bufsize = 0; 607 free(babel_ifp->sendbuf); 608 babel_ifp->num_buffered_updates = 0; 609 babel_ifp->update_bufsize = 0; 610 if(babel_ifp->buffered_updates) 611 free(babel_ifp->buffered_updates); 612 babel_ifp->buffered_updates = NULL; 613 babel_ifp->sendbuf = NULL; 614 615 if(ifp->ifindex > 0) { 616 memset(&mreq, 0, sizeof(mreq)); 617 memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16); 618 mreq.ipv6mr_interface = ifp->ifindex; 619 rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 620 (char*)&mreq, sizeof(mreq)); 621 if(rc < 0) 622 zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s", 623 ifp->name, safe_strerror(errno)); 624 } 625 626 update_interface_metric(ifp); 627 628 debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).", 629 ifp->name, 630 (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless", 631 babel_ifp->cost, 632 babel_ifp->ipv4 ? ", IPv4" : ""); 633 634 return 1; 635} 636 637/* Send retraction to all, and reset all interfaces statistics. */ 638void 639babel_interface_close_all(void) 640{ 641 struct interface *ifp = NULL; 642 struct listnode *linklist_node = NULL; 643 644 FOR_ALL_INTERFACES(ifp, linklist_node) { 645 if(!if_up(ifp)) 646 continue; 647 send_wildcard_retraction(ifp); 648 /* Make sure that we expire quickly from our neighbours' 649 association caches. */ 650 send_hello_noupdate(ifp, 10); 651 flushbuf(ifp); 652 usleep(roughly(1000)); 653 gettime(&babel_now); 654 } 655 FOR_ALL_INTERFACES(ifp, linklist_node) { 656 if(!if_up(ifp)) 657 continue; 658 /* Make sure they got it. */ 659 send_wildcard_retraction(ifp); 660 send_hello_noupdate(ifp, 1); 661 flushbuf(ifp); 662 usleep(roughly(10000)); 663 gettime(&babel_now); 664 interface_reset(ifp); 665 } 666} 667 668/* return "true" if address is one of our ipv6 addresses */ 669int 670is_interface_ll_address(struct interface *ifp, const unsigned char *address) 671{ 672 struct connected *connected; 673 struct listnode *node; 674 675 if(!if_up(ifp)) 676 return 0; 677 678 FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) { 679 if(connected->address->family == AF_INET6 && 680 memcmp(&connected->address->u.prefix6, address, 16) == 0) 681 return 1; 682 } 683 684 return 0; 685} 686 687static void 688show_babel_interface_sub (struct vty *vty, struct interface *ifp) 689{ 690 int is_up; 691 babel_interface_nfo *babel_ifp; 692 693 vty_out (vty, "%s is %s%s", ifp->name, 694 ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE); 695 vty_out (vty, " ifindex %u, MTU %u bytes %s%s", 696 ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE); 697 698 if (babel_enable_if_lookup (ifp->name) < 0) 699 { 700 vty_out (vty, " Babel protocol is not enabled on this interface%s", VTY_NEWLINE); 701 return; 702 } 703 if (!is_up) 704 { 705 vty_out (vty, " Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE); 706 return; 707 } 708 babel_ifp = babel_get_if_nfo (ifp); 709 vty_out (vty, " Babel protocol is running on this interface%s", VTY_NEWLINE); 710 vty_out (vty, " Operating mode is \"%s\"%s", 711 CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE); 712 vty_out (vty, " Split horizon mode is %s%s", 713 CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE); 714 vty_out (vty, " Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE); 715 vty_out (vty, " Update interval is %u ms%s", babel_ifp->update_interval, VTY_NEWLINE); 716} 717 718DEFUN (show_babel_interface, 719 show_babel_interface_cmd, 720 "show babel interface [INTERFACE]", 721 SHOW_STR 722 IP_STR 723 "Babel information\n" 724 "Interface information\n" 725 "Interface name\n") 726{ 727 struct interface *ifp; 728 struct listnode *node; 729 730 if (argc == 0) 731 { 732 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 733 show_babel_interface_sub (vty, ifp); 734 return CMD_SUCCESS; 735 } 736 if ((ifp = if_lookup_by_name (argv[0])) == NULL) 737 { 738 vty_out (vty, "No such interface name%s", VTY_NEWLINE); 739 return CMD_WARNING; 740 } 741 show_babel_interface_sub (vty, ifp); 742 return CMD_SUCCESS; 743} 744 745static void 746show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh) 747{ 748 vty_out (vty, 749 "Neighbour %s dev %s reach %04x rxcost %d txcost %d %s.%s", 750 format_address(neigh->address), 751 neigh->ifp->name, 752 neigh->reach, 753 neighbour_rxcost(neigh), 754 neigh->txcost, 755 if_up(neigh->ifp) ? "" : " (down)", 756 VTY_NEWLINE); 757} 758 759DEFUN (show_babel_neighbour, 760 show_babel_neighbour_cmd, 761 "show babel neighbour [INTERFACE]", 762 SHOW_STR 763 IP_STR 764 "Babel information\n" 765 "Print neighbours\n" 766 "Interface name\n") 767{ 768 struct neighbour *neigh; 769 struct interface *ifp; 770 771 if (argc == 0) { 772 FOR_ALL_NEIGHBOURS(neigh) { 773 show_babel_neighbour_sub(vty, neigh); 774 } 775 return CMD_SUCCESS; 776 } 777 if ((ifp = if_lookup_by_name (argv[0])) == NULL) 778 { 779 vty_out (vty, "No such interface name%s", VTY_NEWLINE); 780 return CMD_WARNING; 781 } 782 FOR_ALL_NEIGHBOURS(neigh) { 783 if(ifp->ifindex == neigh->ifp->ifindex) { 784 show_babel_neighbour_sub(vty, neigh); 785 } 786 } 787 return CMD_SUCCESS; 788} 789 790static void 791show_babel_routes_sub (struct babel_route *route, void *closure) 792{ 793 struct vty *vty = (struct vty*) closure; 794 const unsigned char *nexthop = 795 memcmp(route->nexthop, route->neigh->address, 16) == 0 ? 796 NULL : route->nexthop; 797 char channels[100]; 798 799 if(route->channels[0] == 0) 800 channels[0] = '\0'; 801 else { 802 int k, j = 0; 803 snprintf(channels, 100, " chan ("); 804 j = strlen(channels); 805 for(k = 0; k < DIVERSITY_HOPS; k++) { 806 if(route->channels[k] == 0) 807 break; 808 if(k > 0) 809 channels[j++] = ','; 810 snprintf(channels + j, 100 - j, "%d", route->channels[k]); 811 j = strlen(channels); 812 } 813 snprintf(channels + j, 100 - j, ")"); 814 if(k == 0) 815 channels[0] = '\0'; 816 } 817 818 vty_out(vty, 819 "%s metric %d refmetric %d id %s seqno %d%s age %d " 820 "via %s neigh %s%s%s%s%s", 821 format_prefix(route->src->prefix, route->src->plen), 822 route_metric(route), route->refmetric, 823 format_eui64(route->src->id), 824 (int)route->seqno, 825 channels, 826 (int)(babel_now.tv_sec - route->time), 827 route->neigh->ifp->name, 828 format_address(route->neigh->address), 829 nexthop ? " nexthop " : "", 830 nexthop ? format_address(nexthop) : "", 831 route->installed ? " (installed)" : 832 route_feasible(route) ? " (feasible)" : "", 833 VTY_NEWLINE); 834} 835 836static void 837show_babel_xroutes_sub (struct xroute *xroute, void *closure) 838{ 839 struct vty *vty = (struct vty *) closure; 840 vty_out(vty, "%s metric %d (exported)%s", 841 format_prefix(xroute->prefix, xroute->plen), 842 xroute->metric, 843 VTY_NEWLINE); 844} 845 846DEFUN (show_babel_database, 847 show_babel_database_cmd, 848 "show babel database", 849 SHOW_STR 850 IP_STR 851 "Babel information\n" 852 "Database information\n" 853 "No attributes\n") 854{ 855 for_all_routes(show_babel_routes_sub, vty); 856 for_all_xroutes(show_babel_xroutes_sub, vty); 857 return CMD_SUCCESS; 858} 859 860DEFUN (show_babel_parameters, 861 show_babel_parameters_cmd, 862 "show babel parameters", 863 SHOW_STR 864 IP_STR 865 "Babel information\n" 866 "Configuration information\n" 867 "No attributes\n") 868{ 869 vty_out(vty, " -- Babel running configuration --%s", VTY_NEWLINE); 870 show_babel_main_configuration(vty); 871 vty_out(vty, " -- distribution lists --%s", VTY_NEWLINE); 872 config_show_distribute(vty); 873 874 return CMD_SUCCESS; 875} 876 877void 878babel_if_init () 879{ 880 /* initialize interface list */ 881 if_init(); 882 if_add_hook (IF_NEW_HOOK, babel_if_new_hook); 883 if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook); 884 885 babel_enable_if = vector_init (1); 886 887 /* install interface node and commands */ 888 install_element (CONFIG_NODE, &interface_cmd); 889 install_element (CONFIG_NODE, &no_interface_cmd); 890 install_node (&babel_interface_node, interface_config_write); 891 install_default(INTERFACE_NODE); 892 install_element(INTERFACE_NODE, &interface_cmd); 893 install_element(INTERFACE_NODE, &no_interface_cmd); 894 895 install_element(BABEL_NODE, &babel_network_cmd); 896 install_element(BABEL_NODE, &no_babel_network_cmd); 897 install_element(INTERFACE_NODE, &babel_split_horizon_cmd); 898 install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd); 899 install_element(INTERFACE_NODE, &babel_set_wired_cmd); 900 install_element(INTERFACE_NODE, &babel_set_wireless_cmd); 901 install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd); 902 install_element(INTERFACE_NODE, &babel_set_update_interval_cmd); 903 904 /* "show babel ..." commands */ 905 install_element(VIEW_NODE, &show_babel_interface_cmd); 906 install_element(ENABLE_NODE, &show_babel_interface_cmd); 907 install_element(VIEW_NODE, &show_babel_neighbour_cmd); 908 install_element(ENABLE_NODE, &show_babel_neighbour_cmd); 909 install_element(VIEW_NODE, &show_babel_database_cmd); 910 install_element(ENABLE_NODE, &show_babel_database_cmd); 911 install_element(VIEW_NODE, &show_babel_parameters_cmd); 912 install_element(ENABLE_NODE, &show_babel_parameters_cmd); 913} 914 915/* hooks: functions called respectively when struct interface is 916 created or deleted. */ 917static int 918babel_if_new_hook (struct interface *ifp) 919{ 920 ifp->info = babel_interface_allocate(); 921 return 0; 922} 923 924static int 925babel_if_delete_hook (struct interface *ifp) 926{ 927 babel_interface_free(ifp->info); 928 ifp->info = NULL; 929 return 0; 930} 931 932/* Output an "interface" section for each of the known interfaces with 933babeld-specific statement lines where appropriate. */ 934static int 935interface_config_write (struct vty *vty) 936{ 937 struct listnode *node; 938 struct interface *ifp; 939 int write = 0; 940 941 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) { 942 vty_out (vty, "interface %s%s", ifp->name, 943 VTY_NEWLINE); 944 if (ifp->desc) 945 vty_out (vty, " description %s%s", ifp->desc, 946 VTY_NEWLINE); 947 if (IS_ENABLE (ifp)) 948 { 949 babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp); 950 /* wireless/no split-horizon is the default */ 951 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED)) 952 { 953 vty_out (vty, " babel wired%s", VTY_NEWLINE); 954 write++; 955 } 956 if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) 957 { 958 vty_out (vty, " babel split-horizon%s", VTY_NEWLINE); 959 write++; 960 } 961 if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL) 962 { 963 vty_out (vty, " babel hello-interval %u%s", babel_ifp->hello_interval, VTY_NEWLINE); 964 write++; 965 } 966 if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL) 967 { 968 vty_out (vty, " babel update-interval %u%s", babel_ifp->update_interval, VTY_NEWLINE); 969 write++; 970 } 971 } 972 vty_out (vty, "!%s", VTY_NEWLINE); 973 write++; 974 } 975 return write; 976} 977 978/* Output a "network" statement line for each of the enabled interfaces. */ 979int 980babel_enable_if_config_write (struct vty * vty) 981{ 982 unsigned int i, lines = 0; 983 char *str; 984 985 for (i = 0; i < vector_active (babel_enable_if); i++) 986 if ((str = vector_slot (babel_enable_if, i)) != NULL) 987 { 988 vty_out (vty, " network %s%s", str, VTY_NEWLINE); 989 lines++; 990 } 991 return lines; 992} 993 994/* functions to allocate or free memory for a babel_interface_nfo, filling 995 needed fields */ 996static babel_interface_nfo * 997babel_interface_allocate (void) 998{ 999 babel_interface_nfo *babel_ifp; 1000 babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo)); 1001 if(babel_ifp == NULL) 1002 return NULL; 1003 1004 /* Here are set the default values for an interface. */ 1005 memset(babel_ifp, 0, sizeof(babel_interface_nfo)); 1006 /* All flags are unset */ 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 = BABEL_DEFAULT_HELLO_INTERVAL; 1011 babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL; 1012 babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING; 1013 babel_set_wired_internal(babel_ifp, 0); 1014 1015 return babel_ifp; 1016} 1017 1018static void 1019babel_interface_free (babel_interface_nfo *babel_ifp) 1020{ 1021 XFREE(MTYPE_BABEL_IF, babel_ifp); 1022} 1023