1/* 2 * Interface related function for RIPng. 3 * Copyright (C) 1998 Kunihiro Ishiguro 4 * 5 * This file is part of GNU Zebra. 6 * 7 * GNU Zebra is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * GNU Zebra is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 23#include <zebra.h> 24 25#include "linklist.h" 26#include "if.h" 27#include "prefix.h" 28#include "memory.h" 29#include "network.h" 30#include "filter.h" 31#include "log.h" 32#include "stream.h" 33#include "zclient.h" 34#include "command.h" 35#include "table.h" 36#include "thread.h" 37 38#include "ripngd/ripngd.h" 39#include "ripngd/ripng_debug.h" 40 41/* If RFC2133 definition is used. */ 42#ifndef IPV6_JOIN_GROUP 43#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP 44#endif 45#ifndef IPV6_LEAVE_GROUP 46#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP 47#endif 48 49/* Static utility function. */ 50static void ripng_enable_apply (struct interface *); 51static void ripng_passive_interface_apply (struct interface *); 52 53/* Join to the all rip routers multicast group. */ 54int 55ripng_multicast_join (struct interface *ifp) 56{ 57 int ret; 58 struct ipv6_mreq mreq; 59 60 memset (&mreq, 0, sizeof (mreq)); 61 inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); 62 mreq.ipv6mr_interface = ifp->ifindex; 63 64 ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 65 (char *) &mreq, sizeof (mreq)); 66 if (ret < 0) 67 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno)); 68 69 if (IS_RIPNG_DEBUG_EVENT) 70 zlog_info ("RIPng %s join to all-rip-routers multicast group", ifp->name); 71 72 return ret; 73} 74 75/* Leave from the all rip routers multicast group. */ 76int 77ripng_multicast_leave (struct interface *ifp) 78{ 79 int ret; 80 struct ipv6_mreq mreq; 81 82 memset (&mreq, 0, sizeof (mreq)); 83 inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); 84 mreq.ipv6mr_interface = ifp->ifindex; 85 86 ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 87 (char *) &mreq, sizeof (mreq)); 88 if (ret < 0) 89 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", strerror (errno)); 90 91 if (IS_RIPNG_DEBUG_EVENT) 92 zlog_info ("RIPng %s leave from all-rip-routers multicast group", 93 ifp->name); 94 95 return ret; 96} 97 98/* Check max mtu size. */ 99int 100ripng_check_max_mtu () 101{ 102 listnode node; 103 struct interface *ifp; 104 int mtu; 105 106 mtu = 0; 107 for (node = listhead (iflist); node; nextnode (node)) 108 { 109 ifp = getdata (node); 110 if (mtu < ifp->mtu) 111 mtu = ifp->mtu; 112 } 113 return mtu; 114} 115 116int 117ripng_if_down (struct interface *ifp) 118{ 119 struct route_node *rp; 120 struct ripng_info *rinfo; 121 struct ripng_interface *ri; 122 123 if (ripng->table) 124 { 125 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) 126 if ((rinfo = rp->info) != NULL) 127 { 128 /* Routes got through this interface. */ 129 if (rinfo->ifindex == ifp->ifindex 130 && rinfo->type == ZEBRA_ROUTE_RIPNG 131 && rinfo->sub_type == RIPNG_ROUTE_RTE) 132 { 133 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *) &rp->p, 134 &rinfo->nexthop, 135 rinfo->ifindex); 136 137 RIPNG_TIMER_OFF (rinfo->t_timeout); 138 RIPNG_TIMER_OFF (rinfo->t_garbage_collect); 139 140 rp->info = NULL; 141 route_unlock_node (rp); 142 143 ripng_info_free (rinfo); 144 } 145 else 146 { 147 /* All redistributed routes got through this interface. */ 148 if (rinfo->ifindex == ifp->ifindex) 149 ripng_redistribute_delete (rinfo->type, rinfo->sub_type, 150 (struct prefix_ipv6 *) &rp->p, 151 rinfo->ifindex); 152 } 153 } 154 } 155 156 ri = ifp->info; 157 158 if (ripng && ri->running) 159 { 160 if (IS_RIPNG_DEBUG_EVENT) 161 zlog_info ("turn off %s", ifp->name); 162 163 /* Leave from multicast group. */ 164 ripng_multicast_leave (ifp); 165 166 ri->running = 0; 167 } 168 169 return 0; 170} 171 172/* Inteface link up message processing. */ 173int 174ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length) 175{ 176 struct stream *s; 177 struct interface *ifp; 178 179 /* zebra_interface_state_read() updates interface structure in iflist. */ 180 s = zclient->ibuf; 181 ifp = zebra_interface_state_read (s); 182 183 if (ifp == NULL) 184 return 0; 185 186 if (IS_RIPNG_DEBUG_ZEBRA) 187 zlog_info ("interface up %s index %d flags %ld metric %d mtu %d", 188 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); 189 190 /* Check if this interface is RIPng enabled or not. */ 191 ripng_enable_apply (ifp); 192 193 /* Check for a passive interface. */ 194 ripng_passive_interface_apply (ifp); 195 196 /* Apply distribute list to the all interface. */ 197 ripng_distribute_update_interface (ifp); 198 199 return 0; 200} 201 202/* Inteface link down message processing. */ 203int 204ripng_interface_down (int command, struct zclient *zclient, 205 zebra_size_t length) 206{ 207 struct stream *s; 208 struct interface *ifp; 209 210 /* zebra_interface_state_read() updates interface structure in iflist. */ 211 s = zclient->ibuf; 212 ifp = zebra_interface_state_read (s); 213 214 if (ifp == NULL) 215 return 0; 216 217 ripng_if_down (ifp); 218 219 if (IS_RIPNG_DEBUG_ZEBRA) 220 zlog_info ("interface down %s index %d flags %ld metric %d mtu %d", 221 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); 222 223 return 0; 224} 225 226/* Inteface addition message from zebra. */ 227int 228ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length) 229{ 230 struct interface *ifp; 231 232 ifp = zebra_interface_add_read (zclient->ibuf); 233 234 if (IS_RIPNG_DEBUG_ZEBRA) 235 zlog_info ("RIPng interface add %s index %d flags %ld metric %d mtu %d", 236 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); 237 238 /* Check is this interface is RIP enabled or not.*/ 239 ripng_enable_apply (ifp); 240 241 /* Apply distribute list to the interface. */ 242 ripng_distribute_update_interface (ifp); 243 244 /* Check interface routemap. */ 245 ripng_if_rmap_update_interface (ifp); 246 247 return 0; 248} 249 250int 251ripng_interface_delete (int command, struct zclient *zclient, 252 zebra_size_t length) 253{ 254 return 0; 255} 256 257int 258ripng_interface_address_add (int command, struct zclient *zclient, 259 zebra_size_t length) 260{ 261 struct connected *c; 262 struct prefix *p; 263 char buf[INET6_ADDRSTRLEN]; 264 265 c = zebra_interface_address_add_read (zclient->ibuf); 266 267 if (c == NULL) 268 return 0; 269 270 p = c->address; 271 272 if (p->family == AF_INET6) 273 { 274 if (IS_RIPNG_DEBUG_ZEBRA) 275 zlog_info ("RIPng connected address %s/%d add", 276 inet_ntop (AF_INET6, &p->u.prefix6, buf, INET6_ADDRSTRLEN), 277 p->prefixlen); 278 279 /* Check is this interface is RIP enabled or not.*/ 280 ripng_enable_apply (c->ifp); 281 } 282 283 return 0; 284} 285 286int 287ripng_interface_address_delete (int command, struct zclient *zclient, 288 zebra_size_t length) 289{ 290 struct connected *ifc; 291 struct prefix *p; 292 char buf[INET6_ADDRSTRLEN]; 293 294 ifc = zebra_interface_address_delete_read (zclient->ibuf); 295 296 if (ifc) 297 { 298 p = ifc->address; 299 300 if (p->family == AF_INET6) 301 { 302 if (IS_RIPNG_DEBUG_ZEBRA) 303 zlog_info ("RIPng connected address %s/%d delete", 304 inet_ntop (AF_INET6, &p->u.prefix6, buf, 305 INET6_ADDRSTRLEN), 306 p->prefixlen); 307 308 /* Check is this interface is RIP enabled or not.*/ 309 ripng_enable_apply (ifc->ifp); 310 } 311 connected_free (ifc); 312 } 313 314 return 0; 315} 316 317/* RIPng enable interface vector. */ 318vector ripng_enable_if; 319 320/* RIPng enable network table. */ 321struct route_table *ripng_enable_network; 322 323/* Lookup RIPng enable network. */ 324int 325ripng_enable_network_lookup (struct interface *ifp) 326{ 327 listnode listnode; 328 struct connected *connected; 329 330 for (listnode = listhead (ifp->connected); listnode; nextnode (listnode)) 331 if ((connected = getdata (listnode)) != NULL) 332 { 333 struct prefix *p; 334 struct route_node *node; 335 336 p = connected->address; 337 338 if (p->family == AF_INET6) 339 { 340 node = route_node_match (ripng_enable_network, p); 341 if (node) 342 { 343 route_unlock_node (node); 344 return 1; 345 } 346 } 347 } 348 return -1; 349} 350 351/* Add RIPng enable network. */ 352int 353ripng_enable_network_add (struct prefix *p) 354{ 355 struct route_node *node; 356 357 node = route_node_get (ripng_enable_network, p); 358 359 if (node->info) 360 { 361 route_unlock_node (node); 362 return -1; 363 } 364 else 365 node->info = "enabled"; 366 367 return 1; 368} 369 370/* Delete RIPng enable network. */ 371int 372ripng_enable_network_delete (struct prefix *p) 373{ 374 struct route_node *node; 375 376 node = route_node_lookup (ripng_enable_network, p); 377 if (node) 378 { 379 node->info = NULL; 380 381 /* Unlock info lock. */ 382 route_unlock_node (node); 383 384 /* Unlock lookup lock. */ 385 route_unlock_node (node); 386 387 return 1; 388 } 389 return -1; 390} 391 392/* Lookup function. */ 393int 394ripng_enable_if_lookup (char *ifname) 395{ 396 int i; 397 char *str; 398 399 for (i = 0; i < vector_max (ripng_enable_if); i++) 400 if ((str = vector_slot (ripng_enable_if, i)) != NULL) 401 if (strcmp (str, ifname) == 0) 402 return i; 403 return -1; 404} 405 406/* Add interface to ripng_enable_if. */ 407int 408ripng_enable_if_add (char *ifname) 409{ 410 int ret; 411 412 ret = ripng_enable_if_lookup (ifname); 413 if (ret >= 0) 414 return -1; 415 416 vector_set (ripng_enable_if, strdup (ifname)); 417 418 return 1; 419} 420 421/* Delete interface from ripng_enable_if. */ 422int 423ripng_enable_if_delete (char *ifname) 424{ 425 int index; 426 char *str; 427 428 index = ripng_enable_if_lookup (ifname); 429 if (index < 0) 430 return -1; 431 432 str = vector_slot (ripng_enable_if, index); 433 free (str); 434 vector_unset (ripng_enable_if, index); 435 436 return 1; 437} 438 439/* Wake up interface. */ 440int 441ripng_interface_wakeup (struct thread *t) 442{ 443 struct interface *ifp; 444 struct ripng_interface *ri; 445 446 /* Get interface. */ 447 ifp = THREAD_ARG (t); 448 449 ri = ifp->info; 450 ri->t_wakeup = NULL; 451 452 /* Join to multicast group. */ 453 ripng_multicast_join (ifp); 454 455 /* Send RIP request to the interface. */ 456 ripng_request (ifp); 457 458 return 0; 459} 460 461/* Check RIPng is enabed on this interface. */ 462void 463ripng_enable_apply (struct interface *ifp) 464{ 465 int ret; 466 struct ripng_interface *ri = NULL; 467 468 /* Check interface. */ 469 if (if_is_loopback (ifp)) 470 return; 471 472 if (! if_is_up (ifp)) 473 return; 474 475 ri = ifp->info; 476 477 /* Check network configuration. */ 478 ret = ripng_enable_network_lookup (ifp); 479 480 /* If the interface is matched. */ 481 if (ret > 0) 482 ri->enable_network = 1; 483 else 484 ri->enable_network = 0; 485 486 /* Check interface name configuration. */ 487 ret = ripng_enable_if_lookup (ifp->name); 488 if (ret >= 0) 489 ri->enable_interface = 1; 490 else 491 ri->enable_interface = 0; 492 493 /* Update running status of the interface. */ 494 if (ri->enable_network || ri->enable_interface) 495 { 496 if (! ri->running) 497 { 498 if (IS_RIPNG_DEBUG_EVENT) 499 zlog_info ("RIPng turn on %s", ifp->name); 500 501 /* Add interface wake up thread. */ 502 if (! ri->t_wakeup) 503 ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup, 504 ifp, 1); 505#if 0 506 /* Join to multicast group. */ 507 ripng_multicast_join (ifp); 508 509 /* Send RIP request to the interface. */ 510 ripng_request (ifp); 511#endif /* 0 */ 512 513 ri->running = 1; 514 } 515 } 516 else 517 { 518 if (ri->running) 519 { 520 if (IS_RIPNG_DEBUG_EVENT) 521 zlog_info ("RIPng turn off %s", ifp->name); 522 523 /* Leave from multicast group. */ 524 ripng_multicast_leave (ifp); 525 526 ri->running = 0; 527 } 528 } 529} 530 531/* Set distribute list to all interfaces. */ 532static void 533ripng_enable_apply_all () 534{ 535 struct interface *ifp; 536 listnode node; 537 538 for (node = listhead (iflist); node; nextnode (node)) 539 { 540 ifp = getdata (node); 541 ripng_enable_apply (ifp); 542 } 543} 544 545/* Vector to store passive-interface name. */ 546vector Vripng_passive_interface; 547 548/* Utility function for looking up passive interface settings. */ 549int 550ripng_passive_interface_lookup (char *ifname) 551{ 552 int i; 553 char *str; 554 555 for (i = 0; i < vector_max (Vripng_passive_interface); i++) 556 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL) 557 if (strcmp (str, ifname) == 0) 558 return i; 559 return -1; 560} 561 562void 563ripng_passive_interface_apply (struct interface *ifp) 564{ 565 int ret; 566 struct ripng_interface *ri; 567 568 ri = ifp->info; 569 570 ret = ripng_passive_interface_lookup (ifp->name); 571 if (ret < 0) 572 ri->passive = 0; 573 else 574 ri->passive = 1; 575} 576 577void 578ripng_passive_interface_apply_all (void) 579{ 580 struct interface *ifp; 581 listnode node; 582 583 for (node = listhead (iflist); node; nextnode (node)) 584 { 585 ifp = getdata (node); 586 ripng_passive_interface_apply (ifp); 587 } 588} 589 590/* Passive interface. */ 591int 592ripng_passive_interface_set (struct vty *vty, char *ifname) 593{ 594 if (ripng_passive_interface_lookup (ifname) >= 0) 595 return CMD_WARNING; 596 597 vector_set (Vripng_passive_interface, strdup (ifname)); 598 599 ripng_passive_interface_apply_all (); 600 601 return CMD_SUCCESS; 602} 603 604int 605ripng_passive_interface_unset (struct vty *vty, char *ifname) 606{ 607 int i; 608 char *str; 609 610 i = ripng_passive_interface_lookup (ifname); 611 if (i < 0) 612 return CMD_WARNING; 613 614 str = vector_slot (Vripng_passive_interface, i); 615 free (str); 616 vector_unset (Vripng_passive_interface, i); 617 618 ripng_passive_interface_apply_all (); 619 620 return CMD_SUCCESS; 621} 622 623/* Free all configured RIP passive-interface settings. */ 624void 625ripng_passive_interface_clean (void) 626{ 627 int i; 628 char *str; 629 630 for (i = 0; i < vector_max (Vripng_passive_interface); i++) 631 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL) 632 { 633 free (str); 634 vector_slot (Vripng_passive_interface, i) = NULL; 635 } 636 ripng_passive_interface_apply_all (); 637} 638 639/* Write RIPng enable network and interface to the vty. */ 640int 641ripng_network_write (struct vty *vty) 642{ 643 int i; 644 char *str; 645 char *ifname; 646 struct route_node *node; 647 char buf[BUFSIZ]; 648 649 /* Write enable network. */ 650 for (node = route_top (ripng_enable_network); node; node = route_next (node)) 651 if (node->info) 652 { 653 struct prefix *p = &node->p; 654 vty_out (vty, " network %s/%d%s", 655 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), 656 p->prefixlen, 657 VTY_NEWLINE); 658 659 } 660 661 /* Write enable interface. */ 662 for (i = 0; i < vector_max (ripng_enable_if); i++) 663 if ((str = vector_slot (ripng_enable_if, i)) != NULL) 664 vty_out (vty, " network %s%s", str, 665 VTY_NEWLINE); 666 667 /* Write passive interface. */ 668 for (i = 0; i < vector_max (Vripng_passive_interface); i++) 669 if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL) 670 vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE); 671 672 return 0; 673} 674 675/* RIPng enable on specified interface or matched network. */ 676DEFUN (ripng_network, 677 ripng_network_cmd, 678 "network IF_OR_ADDR", 679 "RIPng enable on specified interface or network.\n" 680 "Interface or address") 681{ 682 int ret; 683 struct prefix p; 684 685 ret = str2prefix (argv[0], &p); 686 687 /* Given string is IPv6 network or interface name. */ 688 if (ret) 689 ret = ripng_enable_network_add (&p); 690 else 691 ret = ripng_enable_if_add (argv[0]); 692 693 if (ret < 0) 694 { 695 vty_out (vty, "There is same network configuration %s%s", argv[0], 696 VTY_NEWLINE); 697 return CMD_WARNING; 698 } 699 700 ripng_enable_apply_all (); 701 702 return CMD_SUCCESS; 703} 704 705/* RIPng enable on specified interface or matched network. */ 706DEFUN (no_ripng_network, 707 no_ripng_network_cmd, 708 "no network IF_OR_ADDR", 709 NO_STR 710 "RIPng enable on specified interface or network.\n" 711 "Interface or address") 712{ 713 int ret; 714 struct prefix p; 715 716 ret = str2prefix (argv[0], &p); 717 718 /* Given string is interface name. */ 719 if (ret) 720 ret = ripng_enable_network_delete (&p); 721 else 722 ret = ripng_enable_if_delete (argv[0]); 723 724 if (ret < 0) 725 { 726 vty_out (vty, "can't find network %s%s", argv[0], 727 VTY_NEWLINE); 728 return CMD_WARNING; 729 } 730 731 ripng_enable_apply_all (); 732 733 return CMD_SUCCESS; 734} 735 736DEFUN (ripng_passive_interface, 737 ripng_passive_interface_cmd, 738 "passive-interface IFNAME", 739 "Suppress routing updates on an interface\n" 740 "Interface name\n") 741{ 742 return ripng_passive_interface_set (vty, argv[0]); 743} 744 745DEFUN (no_ripng_passive_interface, 746 no_ripng_passive_interface_cmd, 747 "no passive-interface IFNAME", 748 NO_STR 749 "Suppress routing updates on an interface\n" 750 "Interface name\n") 751{ 752 return ripng_passive_interface_unset (vty, argv[0]); 753} 754 755struct ripng_interface * 756ri_new () 757{ 758 struct ripng_interface *ri; 759 ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface)); 760 return ri; 761} 762 763int 764ripng_if_new_hook (struct interface *ifp) 765{ 766 ifp->info = ri_new (); 767 return 0; 768} 769 770/* Configuration write function for ripngd. */ 771int 772interface_config_write (struct vty *vty) 773{ 774 listnode node; 775 struct interface *ifp; 776 struct ripng_interface *ri; 777 int write = 0; 778 779 for (node = listhead (iflist); node; nextnode (node)) 780 { 781 ifp = getdata (node); 782 ri = ifp->info; 783 784 vty_out (vty, "interface %s%s", ifp->name, 785 VTY_NEWLINE); 786 if (ifp->desc) 787 vty_out (vty, " description %s%s", ifp->desc, 788 VTY_NEWLINE); 789 790 vty_out (vty, "!%s", VTY_NEWLINE); 791 792 write++; 793 } 794 return write; 795} 796 797/* ripngd's interface node. */ 798struct cmd_node interface_node = 799{ 800 INTERFACE_NODE, 801 "%s(config-if)# ", 802}; 803 804/* Initialization of interface. */ 805void 806ripng_if_init () 807{ 808 /* Interface initialize. */ 809 iflist = list_new (); 810 if_add_hook (IF_NEW_HOOK, ripng_if_new_hook); 811 812 /* RIPng enable network init. */ 813 ripng_enable_network = route_table_init (); 814 815 /* RIPng enable interface init. */ 816 ripng_enable_if = vector_init (1); 817 818 /* RIPng passive interface. */ 819 Vripng_passive_interface = vector_init (1); 820 821 /* Install interface node. */ 822 install_node (&interface_node, interface_config_write); 823 824 install_element (CONFIG_NODE, &interface_cmd); 825 install_element (INTERFACE_NODE, &config_end_cmd); 826 install_element (INTERFACE_NODE, &config_exit_cmd); 827 install_element (INTERFACE_NODE, &config_help_cmd); 828 install_element (INTERFACE_NODE, &interface_desc_cmd); 829 install_element (INTERFACE_NODE, &no_interface_desc_cmd); 830 831 install_element (RIPNG_NODE, &ripng_network_cmd); 832 install_element (RIPNG_NODE, &no_ripng_network_cmd); 833 install_element (RIPNG_NODE, &ripng_passive_interface_cmd); 834 install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd); 835} 836