1/* Router advertisement 2 * Copyright (C) 1999 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#if defined (HAVE_IPV6) && defined (RTADV) 23#include <zebra.h> 24 25#include "memory.h" 26#include "sockopt.h" 27#include "thread.h" 28#include "if.h" 29#include "log.h" 30#include "prefix.h" 31#include "linklist.h" 32#include "command.h" 33 34#include "zebra/interface.h" 35#include "zebra/rtadv.h" 36#include "zebra/debug.h" 37 38//#if defined (HAVE_IPV6) && defined (RTADV) 39 40/* If RFC2133 definition is used. */ 41#ifndef IPV6_JOIN_GROUP 42#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP 43#endif 44#ifndef IPV6_LEAVE_GROUP 45#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP 46#endif 47 48#define ALLNODE "ff02::1" 49#define ALLROUTER "ff02::2" 50 51enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, RTADV_READ}; 52 53void rtadv_event (enum rtadv_event, int); 54 55int if_join_all_router (int, struct interface *); 56int if_leave_all_router (int, struct interface *); 57 58/* Structure which hold status of router advertisement. */ 59struct rtadv 60{ 61 int sock; 62 63 int adv_if_count; 64 65 struct thread *ra_read; 66 struct thread *ra_timer; 67}; 68 69struct rtadv *rtadv = NULL; 70 71struct rtadv * 72rtadv_new () 73{ 74 struct rtadv *new; 75 new = XMALLOC (MTYPE_TMP, sizeof (struct rtadv)); 76 memset (new, 0, sizeof (struct rtadv)); 77 return new; 78} 79 80void 81rtadv_free (struct rtadv *rtadv) 82{ 83 XFREE (MTYPE_TMP, rtadv); 84} 85 86int 87rtadv_recv_packet (int sock, u_char *buf, int buflen, 88 struct sockaddr_in6 *from, unsigned int *ifindex, 89 int *hoplimit) 90{ 91 int ret; 92 struct msghdr msg; 93 struct iovec iov; 94 struct cmsghdr *cmsgptr; 95 struct in6_addr dst; 96 97 char adata[1024]; 98 99 /* Fill in message and iovec. */ 100 msg.msg_name = (void *) from; 101 msg.msg_namelen = sizeof (struct sockaddr_in6); 102 msg.msg_iov = &iov; 103 msg.msg_iovlen = 1; 104 msg.msg_control = (void *) adata; 105 msg.msg_controllen = sizeof adata; 106 iov.iov_base = buf; 107 iov.iov_len = buflen; 108 109 /* If recvmsg fail return minus value. */ 110 ret = recvmsg (sock, &msg, 0); 111 if (ret < 0) 112 return ret; 113 114 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; 115 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) 116 { 117 /* I want interface index which this packet comes from. */ 118 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && 119 cmsgptr->cmsg_type == IPV6_PKTINFO) 120 { 121 struct in6_pktinfo *ptr; 122 123 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); 124 *ifindex = ptr->ipi6_ifindex; 125 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr)); 126 } 127 128 /* Incoming packet's hop limit. */ 129 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && 130 cmsgptr->cmsg_type == IPV6_HOPLIMIT) 131 *hoplimit = *((int *) CMSG_DATA (cmsgptr)); 132 } 133 return ret; 134} 135 136#define RTADV_MSG_SIZE 4096 137 138/* Send router advertisement packet. */ 139void 140rtadv_send_packet (int sock, struct interface *ifp) 141{ 142 struct msghdr msg; 143 struct iovec iov; 144 struct cmsghdr *cmsgptr; 145 struct in6_pktinfo *pkt; 146 struct sockaddr_in6 addr; 147#if HAVE_SOCKADDR_DL 148 struct sockaddr_dl *sdl; 149#endif /* HAVE_SOCKADDR_DL */ 150 char adata [sizeof (struct cmsghdr) + sizeof (struct in6_pktinfo)]; 151 unsigned char buf[RTADV_MSG_SIZE]; 152 struct nd_router_advert *rtadv; 153 int ret; 154 int len = 0; 155 struct zebra_if *zif; 156 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; 157 listnode node; 158 159 /* Logging of packet. */ 160 if (IS_ZEBRA_DEBUG_PACKET) 161 zlog_info ("Router advertisement send to %s", ifp->name); 162 163 /* Fill in sockaddr_in6. */ 164 memset (&addr, 0, sizeof (struct sockaddr_in6)); 165 addr.sin6_family = AF_INET6; 166#ifdef SIN6_LEN 167 addr.sin6_len = sizeof (struct sockaddr_in6); 168#endif /* SIN6_LEN */ 169 addr.sin6_port = htons (IPPROTO_ICMPV6); 170 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr)); 171 172 /* Fetch interface information. */ 173 zif = ifp->info; 174 175 /* Make router advertisement message. */ 176 rtadv = (struct nd_router_advert *) buf; 177 178 rtadv->nd_ra_type = ND_ROUTER_ADVERT; 179 rtadv->nd_ra_code = 0; 180 rtadv->nd_ra_cksum = 0; 181 182 rtadv->nd_ra_curhoplimit = 64; 183 rtadv->nd_ra_flags_reserved = 0; 184 if (zif->rtadv.AdvManagedFlag) 185 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; 186 if (zif->rtadv.AdvOtherConfigFlag) 187 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; 188 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime); 189 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime); 190 rtadv->nd_ra_retransmit = htonl (0); 191 192 len = sizeof (struct nd_router_advert); 193 194 /* Fill in prefix. */ 195 for (node = listhead (zif->rtadv.AdvPrefixList); node; node = nextnode (node)) 196 { 197 struct nd_opt_prefix_info *pinfo; 198 struct rtadv_prefix *rprefix; 199 200 rprefix = getdata (node); 201 202 pinfo = (struct nd_opt_prefix_info *) (buf + len); 203 204 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 205 pinfo->nd_opt_pi_len = 4; 206 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen; 207 208 pinfo->nd_opt_pi_flags_reserved = 0; 209 if (rprefix->AdvOnLinkFlag) 210 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; 211 if (rprefix->AdvAutonomousFlag) 212 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; 213 214 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime); 215 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime); 216 pinfo->nd_opt_pi_reserved2 = 0; 217 218 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6, 219 sizeof (struct in6_addr)); 220 221#ifdef DEBUG 222 { 223 u_char buf[INET6_ADDRSTRLEN]; 224 225 zlog_info ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix, buf, INET6_ADDRSTRLEN)); 226 227 } 228#endif /* DEBUG */ 229 230 len += sizeof (struct nd_opt_prefix_info); 231 } 232 233 /* Hardware address. */ 234#ifdef HAVE_SOCKADDR_DL 235 sdl = &ifp->sdl; 236 if (sdl != NULL && sdl->sdl_alen != 0) 237 { 238 buf[len++] = ND_OPT_SOURCE_LINKADDR; 239 buf[len++] = (sdl->sdl_alen + 2) >> 3; 240 241 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen); 242 len += sdl->sdl_alen; 243 } 244#else 245 if (ifp->hw_addr_len != 0) 246 { 247 buf[len++] = ND_OPT_SOURCE_LINKADDR; 248 buf[len++] = (ifp->hw_addr_len + 2) >> 3; 249 250 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len); 251 len += ifp->hw_addr_len; 252 } 253#endif /* HAVE_SOCKADDR_DL */ 254 255 msg.msg_name = (void *) &addr; 256 msg.msg_namelen = sizeof (struct sockaddr_in6); 257 msg.msg_iov = &iov; 258 msg.msg_iovlen = 1; 259 msg.msg_control = (void *) adata; 260 msg.msg_controllen = sizeof adata; 261 iov.iov_base = buf; 262 iov.iov_len = len; 263 264 cmsgptr = (struct cmsghdr *)adata; 265 cmsgptr->cmsg_len = sizeof adata; 266 cmsgptr->cmsg_level = IPPROTO_IPV6; 267 cmsgptr->cmsg_type = IPV6_PKTINFO; 268 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); 269 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr)); 270 pkt->ipi6_ifindex = ifp->ifindex; 271 272 ret = sendmsg (sock, &msg, 0); 273 if (ret <0) 274 perror ("sendmsg"); 275} 276 277int 278rtadv_timer (struct thread *thread) 279{ 280 listnode node; 281 struct interface *ifp; 282 struct zebra_if *zif; 283 284 rtadv->ra_timer = NULL; 285 rtadv_event (RTADV_TIMER, 1); 286 287 for (node = listhead (iflist); node; nextnode (node)) 288 { 289 ifp = getdata (node); 290 291 if (if_is_loopback (ifp)) 292 continue; 293 294 zif = ifp->info; 295 296 if (zif->rtadv.AdvSendAdvertisements) 297 if (--zif->rtadv.AdvIntervalTimer <= 0) 298 { 299 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; 300 rtadv_send_packet (rtadv->sock, ifp); 301 } 302 } 303 return 0; 304} 305 306void 307rtadv_process_solicit (struct interface *ifp) 308{ 309 zlog_info ("Router solicitation received on %s", ifp->name); 310 311 rtadv_send_packet (rtadv->sock, ifp); 312} 313 314void 315rtadv_process_advert () 316{ 317 zlog_info ("Router advertisement received"); 318} 319 320void 321rtadv_process_packet (u_char *buf, int len, unsigned int ifindex, int hoplimit) 322{ 323 struct icmp6_hdr *icmph; 324 struct interface *ifp; 325 struct zebra_if *zif; 326 327 /* Interface search. */ 328 ifp = if_lookup_by_index (ifindex); 329 if (ifp == NULL) 330 { 331 zlog_warn ("Unknown interface index: %d", ifindex); 332 return; 333 } 334 335 if (if_is_loopback (ifp)) 336 return; 337 338 /* Check interface configuration. */ 339 zif = ifp->info; 340 if (! zif->rtadv.AdvSendAdvertisements) 341 return; 342 343 /* ICMP message length check. */ 344 if (len < sizeof (struct icmp6_hdr)) 345 { 346 zlog_warn ("Invalid ICMPV6 packet length: %d", len); 347 return; 348 } 349 350 icmph = (struct icmp6_hdr *) buf; 351 352 /* ICMP message type check. */ 353 if (icmph->icmp6_type != ND_ROUTER_SOLICIT && 354 icmph->icmp6_type != ND_ROUTER_ADVERT) 355 { 356 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type); 357 return; 358 } 359 360 /* Hoplimit check. */ 361 if (hoplimit >= 0 && hoplimit != 255) 362 { 363 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet", 364 hoplimit); 365 return; 366 } 367 368 /* Check ICMP message type. */ 369 if (icmph->icmp6_type == ND_ROUTER_SOLICIT) 370 rtadv_process_solicit (ifp); 371 else if (icmph->icmp6_type == ND_ROUTER_ADVERT) 372 rtadv_process_advert (); 373 374 return; 375} 376 377int 378rtadv_read (struct thread *thread) 379{ 380 int sock; 381 int len; 382 u_char buf[RTADV_MSG_SIZE]; 383 struct sockaddr_in6 from; 384 unsigned int ifindex; 385 int hoplimit = -1; 386 387 sock = THREAD_FD (thread); 388 rtadv->ra_read = NULL; 389 390 /* Register myself. */ 391 rtadv_event (RTADV_READ, sock); 392 393 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); 394 395 if (len < 0) 396 { 397 zlog_warn ("router solicitation recv failed: %s.", strerror (errno)); 398 return len; 399 } 400 401 rtadv_process_packet (buf, len, ifindex, hoplimit); 402 403 return 0; 404} 405 406int 407rtadv_make_socket (void) 408{ 409 int sock; 410 int ret; 411 struct icmp6_filter filter; 412 413 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 414 415 /* When we can't make ICMPV6 socket simply back. Router 416 advertisement feature will not be supported. */ 417 if (sock < 0) 418 return -1; 419 420 ret = setsockopt_ipv6_pktinfo (sock, 1); 421 if (ret < 0) 422 return ret; 423 ret = setsockopt_ipv6_checksum (sock, 2); 424 if (ret < 0) 425 return ret; 426 ret = setsockopt_ipv6_multicast_loop (sock, 0); 427 if (ret < 0) 428 return ret; 429 ret = setsockopt_ipv6_unicast_hops (sock, 255); 430 if (ret < 0) 431 return ret; 432 ret = setsockopt_ipv6_multicast_hops (sock, 255); 433 if (ret < 0) 434 return ret; 435 ret = setsockopt_ipv6_hoplimit (sock, 1); 436 if (ret < 0) 437 return ret; 438 439 ICMP6_FILTER_SETBLOCKALL(&filter); 440 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter); 441 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter); 442 443 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 444 sizeof (struct icmp6_filter)); 445 if (ret < 0) 446 { 447 zlog_info ("ICMP6_FILTER set fail: %s", strerror (errno)); 448 return ret; 449 } 450 451 return sock; 452} 453 454struct rtadv_prefix * 455rtadv_prefix_new () 456{ 457 struct rtadv_prefix *new; 458 459 new = XMALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix)); 460 memset (new, 0, sizeof (struct rtadv_prefix)); 461 462 return new; 463} 464 465void 466rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix) 467{ 468 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix); 469} 470 471struct rtadv_prefix * 472rtadv_prefix_lookup (list rplist, struct prefix *p) 473{ 474 listnode node; 475 struct rtadv_prefix *rprefix; 476 477 for (node = listhead (rplist); node; node = nextnode (node)) 478 { 479 rprefix = getdata (node); 480 if (prefix_same (&rprefix->prefix, p)) 481 return rprefix; 482 } 483 return NULL; 484} 485 486struct rtadv_prefix * 487rtadv_prefix_get (list rplist, struct prefix *p) 488{ 489 struct rtadv_prefix *rprefix; 490 491 rprefix = rtadv_prefix_lookup (rplist, p); 492 if (rprefix) 493 return rprefix; 494 495 rprefix = rtadv_prefix_new (); 496 memcpy (&rprefix->prefix, p, sizeof (struct prefix)); 497 listnode_add (rplist, rprefix); 498 499 return rprefix; 500} 501 502void 503rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp) 504{ 505 struct rtadv_prefix *rprefix; 506 507 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix); 508 509 /* Set parameters. */ 510 rprefix->AdvValidLifetime = rp->AdvValidLifetime; 511 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime; 512 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag; 513 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag; 514} 515 516int 517rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp) 518{ 519 struct rtadv_prefix *rprefix; 520 521 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix); 522 if (rprefix != NULL) 523 { 524 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix); 525 rtadv_prefix_free (rprefix); 526 return 1; 527 } 528 else 529 return 0; 530} 531 532DEFUN (ipv6_nd_suppress_ra, 533 ipv6_nd_suppress_ra_cmd, 534 "ipv6 nd suppress-ra", 535 IP_STR 536 "Neighbor discovery\n" 537 "Suppress Router Advertisement\n") 538{ 539 struct interface *ifp; 540 struct zebra_if *zif; 541 542 ifp = vty->index; 543 zif = ifp->info; 544 545 if (if_is_loopback (ifp)) 546 { 547 vty_out (vty, "Invalid interface%s", VTY_NEWLINE); 548 return CMD_WARNING; 549 } 550 551 if (zif->rtadv.AdvSendAdvertisements) 552 { 553 zif->rtadv.AdvSendAdvertisements = 0; 554 zif->rtadv.AdvIntervalTimer = 0; 555 rtadv->adv_if_count--; 556 557 if_leave_all_router (rtadv->sock, ifp); 558 559 if (rtadv->adv_if_count == 0) 560 rtadv_event (RTADV_STOP, 0); 561 } 562 563 return CMD_SUCCESS; 564} 565 566ALIAS (ipv6_nd_suppress_ra, 567 no_ipv6_nd_send_ra_cmd, 568 "no ipv6 nd send-ra", 569 NO_STR 570 IP_STR 571 "Neighbor discovery\n" 572 "Send Router Advertisement\n") 573 574DEFUN (no_ipv6_nd_suppress_ra, 575 no_ipv6_nd_suppress_ra_cmd, 576 "no ipv6 nd suppress-ra", 577 NO_STR 578 IP_STR 579 "Neighbor discovery\n" 580 "Suppress Router Advertisement\n") 581{ 582 struct interface *ifp; 583 struct zebra_if *zif; 584 585 ifp = vty->index; 586 zif = ifp->info; 587 588 if (if_is_loopback (ifp)) 589 { 590 vty_out (vty, "Invalid interface%s", VTY_NEWLINE); 591 return CMD_WARNING; 592 } 593 594 if (! zif->rtadv.AdvSendAdvertisements) 595 { 596 zif->rtadv.AdvSendAdvertisements = 1; 597 zif->rtadv.AdvIntervalTimer = 0; 598 rtadv->adv_if_count++; 599 600 if_join_all_router (rtadv->sock, ifp); 601 602 if (rtadv->adv_if_count == 1) 603 rtadv_event (RTADV_START, rtadv->sock); 604 } 605 606 return CMD_SUCCESS; 607} 608 609ALIAS (no_ipv6_nd_suppress_ra, 610 ipv6_nd_send_ra_cmd, 611 "ipv6 nd send-ra", 612 IP_STR 613 "Neighbor discovery\n" 614 "Send Router Advertisement\n") 615 616DEFUN (ipv6_nd_ra_interval, 617 ipv6_nd_ra_interval_cmd, 618 "ipv6 nd ra-interval SECONDS", 619 IP_STR 620 "Neighbor discovery\n" 621 "Router Advertisement interval\n" 622 "Router Advertisement interval in seconds\n") 623{ 624 int interval; 625 struct interface *ifp; 626 struct zebra_if *zif; 627 628 ifp = (struct interface *) vty->index; 629 zif = ifp->info; 630 631 interval = atoi (argv[0]); 632 633 if (interval < 0) 634 { 635 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE); 636 return CMD_WARNING; 637 } 638 639 zif->rtadv.MaxRtrAdvInterval = interval; 640 zif->rtadv.MinRtrAdvInterval = 0.33 * interval; 641 zif->rtadv.AdvIntervalTimer = 0; 642 643 return CMD_SUCCESS; 644} 645 646DEFUN (no_ipv6_nd_ra_interval, 647 no_ipv6_nd_ra_interval_cmd, 648 "no ipv6 nd ra-interval", 649 NO_STR 650 IP_STR 651 "Neighbor discovery\n" 652 "Router Advertisement interval\n") 653{ 654 struct interface *ifp; 655 struct zebra_if *zif; 656 657 ifp = (struct interface *) vty->index; 658 zif = ifp->info; 659 660 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; 661 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; 662 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; 663 664 return CMD_SUCCESS; 665} 666 667DEFUN (ipv6_nd_ra_lifetime, 668 ipv6_nd_ra_lifetime_cmd, 669 "ipv6 nd ra-lifetime SECONDS", 670 IP_STR 671 "Neighbor discovery\n" 672 "Router lifetime\n" 673 "Router lifetime in seconds\n") 674{ 675 int lifetime; 676 struct interface *ifp; 677 struct zebra_if *zif; 678 679 ifp = (struct interface *) vty->index; 680 zif = ifp->info; 681 682 lifetime = atoi (argv[0]); 683 684 if (lifetime < 0 || lifetime > 0xffff) 685 { 686 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE); 687 return CMD_WARNING; 688 } 689 690 zif->rtadv.AdvDefaultLifetime = lifetime; 691 692 return CMD_SUCCESS; 693} 694 695DEFUN (no_ipv6_nd_ra_lifetime, 696 no_ipv6_nd_ra_lifetime_cmd, 697 "no ipv6 nd ra-lifetime", 698 NO_STR 699 IP_STR 700 "Neighbor discovery\n" 701 "Router lifetime\n") 702{ 703 struct interface *ifp; 704 struct zebra_if *zif; 705 706 ifp = (struct interface *) vty->index; 707 zif = ifp->info; 708 709 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME; 710 711 return CMD_SUCCESS; 712} 713 714DEFUN (ipv6_nd_reachable_time, 715 ipv6_nd_reachable_time_cmd, 716 "ipv6 nd reachable-time MILLISECONDS", 717 IP_STR 718 "Neighbor discovery\n" 719 "Reachable time\n" 720 "Reachable time in milliseconds\n") 721{ 722 u_int32_t rtime; 723 struct interface *ifp; 724 struct zebra_if *zif; 725 726 ifp = (struct interface *) vty->index; 727 zif = ifp->info; 728 729 rtime = (u_int32_t) atol (argv[0]); 730 731 if (rtime > RTADV_MAX_REACHABLE_TIME) 732 { 733 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE); 734 return CMD_WARNING; 735 } 736 737 zif->rtadv.AdvReachableTime = rtime; 738 739 return CMD_SUCCESS; 740} 741 742DEFUN (no_ipv6_nd_reachable_time, 743 no_ipv6_nd_reachable_time_cmd, 744 "no ipv6 nd reachable-time", 745 NO_STR 746 IP_STR 747 "Neighbor discovery\n" 748 "Reachable time\n") 749{ 750 struct interface *ifp; 751 struct zebra_if *zif; 752 753 ifp = (struct interface *) vty->index; 754 zif = ifp->info; 755 756 zif->rtadv.AdvReachableTime = 0; 757 758 return CMD_SUCCESS; 759} 760 761DEFUN (ipv6_nd_managed_config_flag, 762 ipv6_nd_managed_config_flag_cmd, 763 "ipv6 nd managed-config-flag", 764 IP_STR 765 "Neighbor discovery\n" 766 "Managed address configuration flag\n") 767{ 768 struct interface *ifp; 769 struct zebra_if *zif; 770 771 ifp = (struct interface *) vty->index; 772 zif = ifp->info; 773 774 zif->rtadv.AdvManagedFlag = 1; 775 776 return CMD_SUCCESS; 777} 778 779DEFUN (no_ipv6_nd_managed_config_flag, 780 no_ipv6_nd_managed_config_flag_cmd, 781 "no ipv6 nd managed-config-flag", 782 NO_STR 783 IP_STR 784 "Neighbor discovery\n" 785 "Managed address configuration flag\n") 786{ 787 struct interface *ifp; 788 struct zebra_if *zif; 789 790 ifp = (struct interface *) vty->index; 791 zif = ifp->info; 792 793 zif->rtadv.AdvManagedFlag = 0; 794 795 return CMD_SUCCESS; 796} 797 798DEFUN (ipv6_nd_other_config_flag, 799 ipv6_nd_other_config_flag_cmd, 800 "ipv6 nd other-config-flag", 801 IP_STR 802 "Neighbor discovery\n" 803 "Other statefull configuration flag\n") 804{ 805 struct interface *ifp; 806 struct zebra_if *zif; 807 808 ifp = (struct interface *) vty->index; 809 zif = ifp->info; 810 811 zif->rtadv.AdvOtherConfigFlag = 1; 812 813 return CMD_SUCCESS; 814} 815 816DEFUN (no_ipv6_nd_other_config_flag, 817 no_ipv6_nd_other_config_flag_cmd, 818 "no ipv6 nd other-config-flag", 819 NO_STR 820 IP_STR 821 "Neighbor discovery\n" 822 "Other statefull configuration flag\n") 823{ 824 struct interface *ifp; 825 struct zebra_if *zif; 826 827 ifp = (struct interface *) vty->index; 828 zif = ifp->info; 829 830 zif->rtadv.AdvOtherConfigFlag = 0; 831 832 return CMD_SUCCESS; 833} 834 835DEFUN (ipv6_nd_prefix_advertisement, 836 ipv6_nd_prefix_advertisement_cmd, 837 "ipv6 nd prefix-advertisement IPV6PREFIX VALID PREFERRED [onlink] [autoconfig]", 838 IP_STR 839 "Neighbor discovery\n" 840 "Prefix information\n" 841 "IPv6 prefix\n" 842 "Valid lifetime in seconds\n" 843 "Preferred lifetime in seconds\n" 844 "On link flag\n" 845 "Autonomous address-configuration flag\n") 846{ 847 int i; 848 int ret; 849 struct interface *ifp; 850 struct zebra_if *zebra_if; 851 struct rtadv_prefix rp; 852 853 ifp = (struct interface *) vty->index; 854 zebra_if = ifp->info; 855 856 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix); 857 if (!ret) 858 { 859 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE); 860 return CMD_WARNING; 861 } 862 863 if (argc == 1) 864 { 865 rp.AdvValidLifetime = RTADV_VALID_LIFETIME; 866 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME; 867 rp.AdvOnLinkFlag = 1; 868 rp.AdvAutonomousFlag = 1; 869 } 870 else 871 { 872 rp.AdvValidLifetime = (u_int32_t) atol (argv[1]); 873 rp.AdvPreferredLifetime = (u_int32_t) atol (argv[2]); 874 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) 875 { 876 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE); 877 return CMD_WARNING; 878 } 879 880 rp.AdvOnLinkFlag = 0; 881 rp.AdvAutonomousFlag = 0; 882 for (i = 3; i < argc; i++) 883 { 884 if (! strcmp (argv[i], "onlink")) 885 rp.AdvOnLinkFlag = 1; 886 else if (! strcmp (argv[i], "autoconfig")) 887 rp.AdvAutonomousFlag = 1; 888 } 889 } 890 891 rtadv_prefix_set (zebra_if, &rp); 892 893 return CMD_SUCCESS; 894} 895 896ALIAS (ipv6_nd_prefix_advertisement, 897 ipv6_nd_prefix_advertisement_no_val_cmd, 898 "ipv6 nd prefix-advertisement IPV6PREFIX", 899 IP_STR 900 "Neighbor discovery\n" 901 "Prefix information\n" 902 "IPv6 prefix\n") 903 904DEFUN (no_ipv6_nd_prefix_advertisement, 905 no_ipv6_nd_prefix_advertisement_cmd, 906 "no ipv6 nd prefix-advertisement IPV6PREFIX", 907 NO_STR 908 IP_STR 909 "Neighbor discovery\n" 910 "Prefix information\n" 911 "IPv6 prefix\n") 912{ 913 int ret; 914 struct interface *ifp; 915 struct zebra_if *zebra_if; 916 struct rtadv_prefix rp; 917 918 ifp = (struct interface *) vty->index; 919 zebra_if = ifp->info; 920 921 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix); 922 if (!ret) 923 { 924 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE); 925 return CMD_WARNING; 926 } 927 928 ret = rtadv_prefix_reset (zebra_if, &rp); 929 if (!ret) 930 { 931 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE); 932 return CMD_WARNING; 933 } 934 935 return CMD_SUCCESS; 936} 937 938/* Write configuration about router advertisement. */ 939void 940rtadv_config_write (struct vty *vty, struct interface *ifp) 941{ 942 struct zebra_if *zif; 943 listnode node; 944 struct rtadv_prefix *rprefix; 945 u_char buf[INET6_ADDRSTRLEN]; 946 947 if (! rtadv) 948 return; 949 950 zif = ifp->info; 951 952 if (! if_is_loopback (ifp)) 953 { 954 if (zif->rtadv.AdvSendAdvertisements) 955 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE); 956 else 957 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE); 958 } 959 960 if (zif->rtadv.MaxRtrAdvInterval != RTADV_MAX_RTR_ADV_INTERVAL) 961 vty_out (vty, " ipv6 nd ra-interval %d%s", zif->rtadv.MaxRtrAdvInterval, 962 VTY_NEWLINE); 963 964 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME) 965 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime, 966 VTY_NEWLINE); 967 968 if (zif->rtadv.AdvReachableTime) 969 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime, 970 VTY_NEWLINE); 971 972 if (zif->rtadv.AdvManagedFlag) 973 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE); 974 975 if (zif->rtadv.AdvOtherConfigFlag) 976 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE); 977 978 for (node = listhead(zif->rtadv.AdvPrefixList); node; node = nextnode (node)) 979 { 980 rprefix = getdata (node); 981 vty_out (vty, " ipv6 nd prefix-advertisement %s/%d %d %d", 982 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6, 983 buf, INET6_ADDRSTRLEN), 984 rprefix->prefix.prefixlen, 985 rprefix->AdvValidLifetime, 986 rprefix->AdvPreferredLifetime); 987 if (rprefix->AdvOnLinkFlag) 988 vty_out (vty, " onlink"); 989 if (rprefix->AdvAutonomousFlag) 990 vty_out (vty, " autoconfig"); 991 vty_out (vty, "%s", VTY_NEWLINE); 992 } 993} 994 995extern struct thread_master *master; 996 997void 998rtadv_event (enum rtadv_event event, int val) 999{ 1000 switch (event) 1001 { 1002 case RTADV_START: 1003 if (! rtadv->ra_read) 1004 rtadv->ra_read = thread_add_read (master, rtadv_read, NULL, val); 1005 if (! rtadv->ra_timer) 1006 rtadv->ra_timer = thread_add_event (master, rtadv_timer, NULL, 0); 1007 break; 1008 case RTADV_STOP: 1009 if (rtadv->ra_timer) 1010 { 1011 thread_cancel (rtadv->ra_timer); 1012 rtadv->ra_timer = NULL; 1013 } 1014 if (rtadv->ra_read) 1015 { 1016 thread_cancel (rtadv->ra_read); 1017 rtadv->ra_read = NULL; 1018 } 1019 break; 1020 case RTADV_TIMER: 1021 if (! rtadv->ra_timer) 1022 rtadv->ra_timer = thread_add_timer (master, rtadv_timer, NULL, val); 1023 break; 1024 case RTADV_READ: 1025 if (! rtadv->ra_read) 1026 rtadv->ra_read = thread_add_read (master, rtadv_read, NULL, val); 1027 break; 1028 default: 1029 break; 1030 } 1031 return; 1032} 1033 1034void 1035rtadv_init () 1036{ 1037 int sock; 1038 1039 sock = rtadv_make_socket (); 1040 if (sock < 0) 1041 return; 1042 1043 rtadv = rtadv_new (); 1044 rtadv->sock = sock; 1045 1046#ifdef FOX_CMD_SUPPORT 1047 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); 1048 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); 1049 install_element (INTERFACE_NODE, &ipv6_nd_send_ra_cmd); 1050 install_element (INTERFACE_NODE, &no_ipv6_nd_send_ra_cmd); 1051 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); 1052 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd); 1053 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd); 1054 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd); 1055 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd); 1056 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd); 1057 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd); 1058 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd); 1059 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd); 1060 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd); 1061 install_element (INTERFACE_NODE, &ipv6_nd_prefix_advertisement_cmd); 1062 install_element (INTERFACE_NODE, &ipv6_nd_prefix_advertisement_no_val_cmd); 1063 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_advertisement_cmd); 1064#endif /* FOX_CMD_SUPPORT */ 1065} 1066 1067int 1068if_join_all_router (int sock, struct interface *ifp) 1069{ 1070 int ret; 1071 1072 struct ipv6_mreq mreq; 1073 1074 memset (&mreq, 0, sizeof (struct ipv6_mreq)); 1075 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); 1076 mreq.ipv6mr_interface = ifp->ifindex; 1077 1078 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 1079 (char *) &mreq, sizeof mreq); 1080 if (ret < 0) 1081 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno)); 1082 1083 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name); 1084 1085 return 0; 1086} 1087 1088int 1089if_leave_all_router (int sock, struct interface *ifp) 1090{ 1091 int ret; 1092 1093 struct ipv6_mreq mreq; 1094 1095 memset (&mreq, 0, sizeof (struct ipv6_mreq)); 1096 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); 1097 mreq.ipv6mr_interface = ifp->ifindex; 1098 1099 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 1100 (char *) &mreq, sizeof mreq); 1101 if (ret < 0) 1102 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", strerror (errno)); 1103 1104 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name); 1105 1106 return 0; 1107} 1108 1109#else 1110void 1111rtadv_init () 1112{ 1113 /* Empty.*/; 1114} 1115#endif /* RTADV && HAVE_IPV6 */ 1116