Annotation of embedaddon/quagga/zebra/rtadv.c, revision 1.1
1.1 ! misho 1: /* Router advertisement
! 2: * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
! 3: * Copyright (C) 1999 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 "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: #include "privs.h"
! 34:
! 35: #include "zebra/interface.h"
! 36: #include "zebra/rtadv.h"
! 37: #include "zebra/debug.h"
! 38: #include "zebra/rib.h"
! 39: #include "zebra/zserv.h"
! 40:
! 41: extern struct zebra_privs_t zserv_privs;
! 42:
! 43: #if defined (HAVE_IPV6) && defined (RTADV)
! 44:
! 45: #ifdef OPEN_BSD
! 46: #include <netinet/icmp6.h>
! 47: #endif
! 48:
! 49: /* If RFC2133 definition is used. */
! 50: #ifndef IPV6_JOIN_GROUP
! 51: #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
! 52: #endif
! 53: #ifndef IPV6_LEAVE_GROUP
! 54: #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
! 55: #endif
! 56:
! 57: #define ALLNODE "ff02::1"
! 58: #define ALLROUTER "ff02::2"
! 59:
! 60: extern struct zebra_t zebrad;
! 61:
! 62: enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
! 63: RTADV_TIMER_MSEC, RTADV_READ};
! 64:
! 65: static void rtadv_event (enum rtadv_event, int);
! 66:
! 67: static int if_join_all_router (int, struct interface *);
! 68: static int if_leave_all_router (int, struct interface *);
! 69:
! 70: /* Structure which hold status of router advertisement. */
! 71: struct rtadv
! 72: {
! 73: int sock;
! 74:
! 75: int adv_if_count;
! 76: int adv_msec_if_count;
! 77:
! 78: struct thread *ra_read;
! 79: struct thread *ra_timer;
! 80: };
! 81:
! 82: struct rtadv *rtadv = NULL;
! 83:
! 84: static struct rtadv *
! 85: rtadv_new (void)
! 86: {
! 87: return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
! 88: }
! 89:
! 90: static int
! 91: rtadv_recv_packet (int sock, u_char *buf, int buflen,
! 92: struct sockaddr_in6 *from, unsigned int *ifindex,
! 93: int *hoplimit)
! 94: {
! 95: int ret;
! 96: struct msghdr msg;
! 97: struct iovec iov;
! 98: struct cmsghdr *cmsgptr;
! 99: struct in6_addr dst;
! 100:
! 101: char adata[1024];
! 102:
! 103: /* Fill in message and iovec. */
! 104: msg.msg_name = (void *) from;
! 105: msg.msg_namelen = sizeof (struct sockaddr_in6);
! 106: msg.msg_iov = &iov;
! 107: msg.msg_iovlen = 1;
! 108: msg.msg_control = (void *) adata;
! 109: msg.msg_controllen = sizeof adata;
! 110: iov.iov_base = buf;
! 111: iov.iov_len = buflen;
! 112:
! 113: /* If recvmsg fail return minus value. */
! 114: ret = recvmsg (sock, &msg, 0);
! 115: if (ret < 0)
! 116: return ret;
! 117:
! 118: for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
! 119: cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
! 120: {
! 121: /* I want interface index which this packet comes from. */
! 122: if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
! 123: cmsgptr->cmsg_type == IPV6_PKTINFO)
! 124: {
! 125: struct in6_pktinfo *ptr;
! 126:
! 127: ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
! 128: *ifindex = ptr->ipi6_ifindex;
! 129: memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
! 130: }
! 131:
! 132: /* Incoming packet's hop limit. */
! 133: if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
! 134: cmsgptr->cmsg_type == IPV6_HOPLIMIT)
! 135: {
! 136: int *hoptr = (int *) CMSG_DATA (cmsgptr);
! 137: *hoplimit = *hoptr;
! 138: }
! 139: }
! 140: return ret;
! 141: }
! 142:
! 143: #define RTADV_MSG_SIZE 4096
! 144:
! 145: /* Send router advertisement packet. */
! 146: static void
! 147: rtadv_send_packet (int sock, struct interface *ifp)
! 148: {
! 149: struct msghdr msg;
! 150: struct iovec iov;
! 151: struct cmsghdr *cmsgptr;
! 152: struct in6_pktinfo *pkt;
! 153: struct sockaddr_in6 addr;
! 154: #ifdef HAVE_STRUCT_SOCKADDR_DL
! 155: struct sockaddr_dl *sdl;
! 156: #endif /* HAVE_STRUCT_SOCKADDR_DL */
! 157: static void *adata = NULL;
! 158: unsigned char buf[RTADV_MSG_SIZE];
! 159: struct nd_router_advert *rtadv;
! 160: int ret;
! 161: int len = 0;
! 162: struct zebra_if *zif;
! 163: struct rtadv_prefix *rprefix;
! 164: u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
! 165: struct listnode *node;
! 166:
! 167: /*
! 168: * Allocate control message bufffer. This is dynamic because
! 169: * CMSG_SPACE is not guaranteed not to call a function. Note that
! 170: * the size will be different on different architectures due to
! 171: * differing alignment rules.
! 172: */
! 173: if (adata == NULL)
! 174: {
! 175: /* XXX Free on shutdown. */
! 176: adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
! 177:
! 178: if (adata == NULL)
! 179: zlog_err("rtadv_send_packet: can't malloc control data\n");
! 180: }
! 181:
! 182: /* Logging of packet. */
! 183: if (IS_ZEBRA_DEBUG_PACKET)
! 184: zlog_debug ("Router advertisement send to %s", ifp->name);
! 185:
! 186: /* Fill in sockaddr_in6. */
! 187: memset (&addr, 0, sizeof (struct sockaddr_in6));
! 188: addr.sin6_family = AF_INET6;
! 189: #ifdef SIN6_LEN
! 190: addr.sin6_len = sizeof (struct sockaddr_in6);
! 191: #endif /* SIN6_LEN */
! 192: addr.sin6_port = htons (IPPROTO_ICMPV6);
! 193: memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
! 194:
! 195: /* Fetch interface information. */
! 196: zif = ifp->info;
! 197:
! 198: /* Make router advertisement message. */
! 199: rtadv = (struct nd_router_advert *) buf;
! 200:
! 201: rtadv->nd_ra_type = ND_ROUTER_ADVERT;
! 202: rtadv->nd_ra_code = 0;
! 203: rtadv->nd_ra_cksum = 0;
! 204:
! 205: rtadv->nd_ra_curhoplimit = 64;
! 206:
! 207: /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
! 208: rtadv->nd_ra_flags_reserved =
! 209: zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
! 210: rtadv->nd_ra_flags_reserved <<= 3;
! 211:
! 212: if (zif->rtadv.AdvManagedFlag)
! 213: rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
! 214: if (zif->rtadv.AdvOtherConfigFlag)
! 215: rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
! 216: if (zif->rtadv.AdvHomeAgentFlag)
! 217: rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
! 218: rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
! 219: rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
! 220: rtadv->nd_ra_retransmit = htonl (0);
! 221:
! 222: len = sizeof (struct nd_router_advert);
! 223:
! 224: if (zif->rtadv.AdvHomeAgentFlag)
! 225: {
! 226: struct nd_opt_homeagent_info *ndopt_hai =
! 227: (struct nd_opt_homeagent_info *)(buf + len);
! 228: ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
! 229: ndopt_hai->nd_opt_hai_len = 1;
! 230: ndopt_hai->nd_opt_hai_reserved = 0;
! 231: ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
! 232: ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
! 233: len += sizeof(struct nd_opt_homeagent_info);
! 234: }
! 235:
! 236: if (zif->rtadv.AdvIntervalOption)
! 237: {
! 238: struct nd_opt_adv_interval *ndopt_adv =
! 239: (struct nd_opt_adv_interval *)(buf + len);
! 240: ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
! 241: ndopt_adv->nd_opt_ai_len = 1;
! 242: ndopt_adv->nd_opt_ai_reserved = 0;
! 243: ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
! 244: len += sizeof(struct nd_opt_adv_interval);
! 245: }
! 246:
! 247: /* Fill in prefix. */
! 248: for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
! 249: {
! 250: struct nd_opt_prefix_info *pinfo;
! 251:
! 252: pinfo = (struct nd_opt_prefix_info *) (buf + len);
! 253:
! 254: pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
! 255: pinfo->nd_opt_pi_len = 4;
! 256: pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
! 257:
! 258: pinfo->nd_opt_pi_flags_reserved = 0;
! 259: if (rprefix->AdvOnLinkFlag)
! 260: pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
! 261: if (rprefix->AdvAutonomousFlag)
! 262: pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
! 263: if (rprefix->AdvRouterAddressFlag)
! 264: pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
! 265:
! 266: pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
! 267: pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
! 268: pinfo->nd_opt_pi_reserved2 = 0;
! 269:
! 270: memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
! 271: sizeof (struct in6_addr));
! 272:
! 273: #ifdef DEBUG
! 274: {
! 275: u_char buf[INET6_ADDRSTRLEN];
! 276:
! 277: zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
! 278: buf, INET6_ADDRSTRLEN));
! 279:
! 280: }
! 281: #endif /* DEBUG */
! 282:
! 283: len += sizeof (struct nd_opt_prefix_info);
! 284: }
! 285:
! 286: /* Hardware address. */
! 287: #ifdef HAVE_STRUCT_SOCKADDR_DL
! 288: sdl = &ifp->sdl;
! 289: if (sdl != NULL && sdl->sdl_alen != 0)
! 290: {
! 291: buf[len++] = ND_OPT_SOURCE_LINKADDR;
! 292:
! 293: /* Option length should be rounded up to next octet if
! 294: the link address does not end on an octet boundary. */
! 295: buf[len++] = (sdl->sdl_alen + 9) >> 3;
! 296:
! 297: memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
! 298: len += sdl->sdl_alen;
! 299:
! 300: /* Pad option to end on an octet boundary. */
! 301: memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
! 302: len += -(sdl->sdl_alen + 2) & 0x7;
! 303: }
! 304: #else
! 305: if (ifp->hw_addr_len != 0)
! 306: {
! 307: buf[len++] = ND_OPT_SOURCE_LINKADDR;
! 308:
! 309: /* Option length should be rounded up to next octet if
! 310: the link address does not end on an octet boundary. */
! 311: buf[len++] = (ifp->hw_addr_len + 9) >> 3;
! 312:
! 313: memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
! 314: len += ifp->hw_addr_len;
! 315:
! 316: /* Pad option to end on an octet boundary. */
! 317: memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
! 318: len += -(ifp->hw_addr_len + 2) & 0x7;
! 319: }
! 320: #endif /* HAVE_STRUCT_SOCKADDR_DL */
! 321:
! 322: msg.msg_name = (void *) &addr;
! 323: msg.msg_namelen = sizeof (struct sockaddr_in6);
! 324: msg.msg_iov = &iov;
! 325: msg.msg_iovlen = 1;
! 326: msg.msg_control = (void *) adata;
! 327: msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
! 328: msg.msg_flags = 0;
! 329: iov.iov_base = buf;
! 330: iov.iov_len = len;
! 331:
! 332: cmsgptr = ZCMSG_FIRSTHDR(&msg);
! 333: cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
! 334: cmsgptr->cmsg_level = IPPROTO_IPV6;
! 335: cmsgptr->cmsg_type = IPV6_PKTINFO;
! 336:
! 337: pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
! 338: memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
! 339: pkt->ipi6_ifindex = ifp->ifindex;
! 340:
! 341: ret = sendmsg (sock, &msg, 0);
! 342: if (ret < 0)
! 343: {
! 344: zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
! 345: errno, safe_strerror(errno));
! 346: }
! 347: }
! 348:
! 349: static int
! 350: rtadv_timer (struct thread *thread)
! 351: {
! 352: struct listnode *node, *nnode;
! 353: struct interface *ifp;
! 354: struct zebra_if *zif;
! 355: int period;
! 356:
! 357: rtadv->ra_timer = NULL;
! 358: if (rtadv->adv_msec_if_count == 0)
! 359: {
! 360: period = 1000; /* 1 s */
! 361: rtadv_event (RTADV_TIMER, 1 /* 1 s */);
! 362: }
! 363: else
! 364: {
! 365: period = 10; /* 10 ms */
! 366: rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
! 367: }
! 368:
! 369: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
! 370: {
! 371: if (if_is_loopback (ifp))
! 372: continue;
! 373:
! 374: zif = ifp->info;
! 375:
! 376: if (zif->rtadv.AdvSendAdvertisements)
! 377: {
! 378: zif->rtadv.AdvIntervalTimer -= period;
! 379: if (zif->rtadv.AdvIntervalTimer <= 0)
! 380: {
! 381: zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
! 382: rtadv_send_packet (rtadv->sock, ifp);
! 383: }
! 384: }
! 385: }
! 386: return 0;
! 387: }
! 388:
! 389: static void
! 390: rtadv_process_solicit (struct interface *ifp)
! 391: {
! 392: zlog_info ("Router solicitation received on %s", ifp->name);
! 393:
! 394: rtadv_send_packet (rtadv->sock, ifp);
! 395: }
! 396:
! 397: static void
! 398: rtadv_process_advert (void)
! 399: {
! 400: zlog_info ("Router advertisement received");
! 401: }
! 402:
! 403: static void
! 404: rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
! 405: {
! 406: struct icmp6_hdr *icmph;
! 407: struct interface *ifp;
! 408: struct zebra_if *zif;
! 409:
! 410: /* Interface search. */
! 411: ifp = if_lookup_by_index (ifindex);
! 412: if (ifp == NULL)
! 413: {
! 414: zlog_warn ("Unknown interface index: %d", ifindex);
! 415: return;
! 416: }
! 417:
! 418: if (if_is_loopback (ifp))
! 419: return;
! 420:
! 421: /* Check interface configuration. */
! 422: zif = ifp->info;
! 423: if (! zif->rtadv.AdvSendAdvertisements)
! 424: return;
! 425:
! 426: /* ICMP message length check. */
! 427: if (len < sizeof (struct icmp6_hdr))
! 428: {
! 429: zlog_warn ("Invalid ICMPV6 packet length: %d", len);
! 430: return;
! 431: }
! 432:
! 433: icmph = (struct icmp6_hdr *) buf;
! 434:
! 435: /* ICMP message type check. */
! 436: if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
! 437: icmph->icmp6_type != ND_ROUTER_ADVERT)
! 438: {
! 439: zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
! 440: return;
! 441: }
! 442:
! 443: /* Hoplimit check. */
! 444: if (hoplimit >= 0 && hoplimit != 255)
! 445: {
! 446: zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
! 447: hoplimit);
! 448: return;
! 449: }
! 450:
! 451: /* Check ICMP message type. */
! 452: if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
! 453: rtadv_process_solicit (ifp);
! 454: else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
! 455: rtadv_process_advert ();
! 456:
! 457: return;
! 458: }
! 459:
! 460: static int
! 461: rtadv_read (struct thread *thread)
! 462: {
! 463: int sock;
! 464: int len;
! 465: u_char buf[RTADV_MSG_SIZE];
! 466: struct sockaddr_in6 from;
! 467: unsigned int ifindex = 0;
! 468: int hoplimit = -1;
! 469:
! 470: sock = THREAD_FD (thread);
! 471: rtadv->ra_read = NULL;
! 472:
! 473: /* Register myself. */
! 474: rtadv_event (RTADV_READ, sock);
! 475:
! 476: len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
! 477:
! 478: if (len < 0)
! 479: {
! 480: zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
! 481: return len;
! 482: }
! 483:
! 484: rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
! 485:
! 486: return 0;
! 487: }
! 488:
! 489: static int
! 490: rtadv_make_socket (void)
! 491: {
! 492: int sock;
! 493: int ret;
! 494: struct icmp6_filter filter;
! 495:
! 496: if ( zserv_privs.change (ZPRIVS_RAISE) )
! 497: zlog_err ("rtadv_make_socket: could not raise privs, %s",
! 498: safe_strerror (errno) );
! 499:
! 500: sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
! 501:
! 502: if ( zserv_privs.change (ZPRIVS_LOWER) )
! 503: zlog_err ("rtadv_make_socket: could not lower privs, %s",
! 504: safe_strerror (errno) );
! 505:
! 506: /* When we can't make ICMPV6 socket simply back. Router
! 507: advertisement feature will not be supported. */
! 508: if (sock < 0)
! 509: return -1;
! 510:
! 511: ret = setsockopt_ipv6_pktinfo (sock, 1);
! 512: if (ret < 0)
! 513: return ret;
! 514: ret = setsockopt_ipv6_multicast_loop (sock, 0);
! 515: if (ret < 0)
! 516: return ret;
! 517: ret = setsockopt_ipv6_unicast_hops (sock, 255);
! 518: if (ret < 0)
! 519: return ret;
! 520: ret = setsockopt_ipv6_multicast_hops (sock, 255);
! 521: if (ret < 0)
! 522: return ret;
! 523: ret = setsockopt_ipv6_hoplimit (sock, 1);
! 524: if (ret < 0)
! 525: return ret;
! 526:
! 527: ICMP6_FILTER_SETBLOCKALL(&filter);
! 528: ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
! 529: ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
! 530:
! 531: ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
! 532: sizeof (struct icmp6_filter));
! 533: if (ret < 0)
! 534: {
! 535: zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
! 536: return ret;
! 537: }
! 538:
! 539: return sock;
! 540: }
! 541:
! 542: static struct rtadv_prefix *
! 543: rtadv_prefix_new (void)
! 544: {
! 545: return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
! 546: }
! 547:
! 548: static void
! 549: rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
! 550: {
! 551: XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
! 552: }
! 553:
! 554: static struct rtadv_prefix *
! 555: rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
! 556: {
! 557: struct listnode *node;
! 558: struct rtadv_prefix *rprefix;
! 559:
! 560: for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
! 561: if (prefix_same (&rprefix->prefix, p))
! 562: return rprefix;
! 563: return NULL;
! 564: }
! 565:
! 566: static struct rtadv_prefix *
! 567: rtadv_prefix_get (struct list *rplist, struct prefix *p)
! 568: {
! 569: struct rtadv_prefix *rprefix;
! 570:
! 571: rprefix = rtadv_prefix_lookup (rplist, p);
! 572: if (rprefix)
! 573: return rprefix;
! 574:
! 575: rprefix = rtadv_prefix_new ();
! 576: memcpy (&rprefix->prefix, p, sizeof (struct prefix));
! 577: listnode_add (rplist, rprefix);
! 578:
! 579: return rprefix;
! 580: }
! 581:
! 582: static void
! 583: rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
! 584: {
! 585: struct rtadv_prefix *rprefix;
! 586:
! 587: rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
! 588:
! 589: /* Set parameters. */
! 590: rprefix->AdvValidLifetime = rp->AdvValidLifetime;
! 591: rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
! 592: rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
! 593: rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
! 594: rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
! 595: }
! 596:
! 597: static int
! 598: rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
! 599: {
! 600: struct rtadv_prefix *rprefix;
! 601:
! 602: rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
! 603: if (rprefix != NULL)
! 604: {
! 605: listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
! 606: rtadv_prefix_free (rprefix);
! 607: return 1;
! 608: }
! 609: else
! 610: return 0;
! 611: }
! 612:
! 613: DEFUN (ipv6_nd_suppress_ra,
! 614: ipv6_nd_suppress_ra_cmd,
! 615: "ipv6 nd suppress-ra",
! 616: "Interface IPv6 config commands\n"
! 617: "Neighbor discovery\n"
! 618: "Suppress Router Advertisement\n")
! 619: {
! 620: struct interface *ifp;
! 621: struct zebra_if *zif;
! 622:
! 623: ifp = vty->index;
! 624: zif = ifp->info;
! 625:
! 626: if (if_is_loopback (ifp))
! 627: {
! 628: vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
! 629: return CMD_WARNING;
! 630: }
! 631:
! 632: if (zif->rtadv.AdvSendAdvertisements)
! 633: {
! 634: zif->rtadv.AdvSendAdvertisements = 0;
! 635: zif->rtadv.AdvIntervalTimer = 0;
! 636: rtadv->adv_if_count--;
! 637:
! 638: if_leave_all_router (rtadv->sock, ifp);
! 639:
! 640: if (rtadv->adv_if_count == 0)
! 641: rtadv_event (RTADV_STOP, 0);
! 642: }
! 643:
! 644: return CMD_SUCCESS;
! 645: }
! 646:
! 647: DEFUN (no_ipv6_nd_suppress_ra,
! 648: no_ipv6_nd_suppress_ra_cmd,
! 649: "no ipv6 nd suppress-ra",
! 650: NO_STR
! 651: "Interface IPv6 config commands\n"
! 652: "Neighbor discovery\n"
! 653: "Suppress Router Advertisement\n")
! 654: {
! 655: struct interface *ifp;
! 656: struct zebra_if *zif;
! 657:
! 658: ifp = vty->index;
! 659: zif = ifp->info;
! 660:
! 661: if (if_is_loopback (ifp))
! 662: {
! 663: vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
! 664: return CMD_WARNING;
! 665: }
! 666:
! 667: if (! zif->rtadv.AdvSendAdvertisements)
! 668: {
! 669: zif->rtadv.AdvSendAdvertisements = 1;
! 670: zif->rtadv.AdvIntervalTimer = 0;
! 671: rtadv->adv_if_count++;
! 672:
! 673: if_join_all_router (rtadv->sock, ifp);
! 674:
! 675: if (rtadv->adv_if_count == 1)
! 676: rtadv_event (RTADV_START, rtadv->sock);
! 677: }
! 678:
! 679: return CMD_SUCCESS;
! 680: }
! 681:
! 682: DEFUN (ipv6_nd_ra_interval_msec,
! 683: ipv6_nd_ra_interval_msec_cmd,
! 684: "ipv6 nd ra-interval msec MILLISECONDS",
! 685: "Interface IPv6 config commands\n"
! 686: "Neighbor discovery\n"
! 687: "Router Advertisement interval\n"
! 688: "Router Advertisement interval in milliseconds\n")
! 689: {
! 690: int interval;
! 691: struct interface *ifp;
! 692: struct zebra_if *zif;
! 693:
! 694: ifp = (struct interface *) vty->index;
! 695: zif = ifp->info;
! 696:
! 697: interval = atoi (argv[0]);
! 698:
! 699: if (interval <= 0)
! 700: {
! 701: vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
! 702: return CMD_WARNING;
! 703: }
! 704:
! 705: if (zif->rtadv.MaxRtrAdvInterval % 1000)
! 706: rtadv->adv_msec_if_count--;
! 707:
! 708: if (interval % 1000)
! 709: rtadv->adv_msec_if_count++;
! 710:
! 711: zif->rtadv.MaxRtrAdvInterval = interval;
! 712: zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
! 713: zif->rtadv.AdvIntervalTimer = 0;
! 714:
! 715: return CMD_SUCCESS;
! 716: }
! 717:
! 718: DEFUN (ipv6_nd_ra_interval,
! 719: ipv6_nd_ra_interval_cmd,
! 720: "ipv6 nd ra-interval SECONDS",
! 721: "Interface IPv6 config commands\n"
! 722: "Neighbor discovery\n"
! 723: "Router Advertisement interval\n"
! 724: "Router Advertisement interval in seconds\n")
! 725: {
! 726: int interval;
! 727: struct interface *ifp;
! 728: struct zebra_if *zif;
! 729:
! 730: ifp = (struct interface *) vty->index;
! 731: zif = ifp->info;
! 732:
! 733: interval = atoi (argv[0]);
! 734:
! 735: if (interval <= 0)
! 736: {
! 737: vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
! 738: return CMD_WARNING;
! 739: }
! 740:
! 741: if (zif->rtadv.MaxRtrAdvInterval % 1000)
! 742: rtadv->adv_msec_if_count--;
! 743:
! 744: /* convert to milliseconds */
! 745: interval = interval * 1000;
! 746:
! 747: zif->rtadv.MaxRtrAdvInterval = interval;
! 748: zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
! 749: zif->rtadv.AdvIntervalTimer = 0;
! 750:
! 751: return CMD_SUCCESS;
! 752: }
! 753:
! 754: DEFUN (no_ipv6_nd_ra_interval,
! 755: no_ipv6_nd_ra_interval_cmd,
! 756: "no ipv6 nd ra-interval",
! 757: NO_STR
! 758: "Interface IPv6 config commands\n"
! 759: "Neighbor discovery\n"
! 760: "Router Advertisement interval\n")
! 761: {
! 762: struct interface *ifp;
! 763: struct zebra_if *zif;
! 764:
! 765: ifp = (struct interface *) vty->index;
! 766: zif = ifp->info;
! 767:
! 768: if (zif->rtadv.MaxRtrAdvInterval % 1000)
! 769: rtadv->adv_msec_if_count--;
! 770:
! 771: zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
! 772: zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
! 773: zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
! 774:
! 775: return CMD_SUCCESS;
! 776: }
! 777:
! 778: DEFUN (ipv6_nd_ra_lifetime,
! 779: ipv6_nd_ra_lifetime_cmd,
! 780: "ipv6 nd ra-lifetime SECONDS",
! 781: "Interface IPv6 config commands\n"
! 782: "Neighbor discovery\n"
! 783: "Router lifetime\n"
! 784: "Router lifetime in seconds\n")
! 785: {
! 786: int lifetime;
! 787: struct interface *ifp;
! 788: struct zebra_if *zif;
! 789:
! 790: ifp = (struct interface *) vty->index;
! 791: zif = ifp->info;
! 792:
! 793: lifetime = atoi (argv[0]);
! 794:
! 795: if (lifetime < 0 || lifetime > 0xffff)
! 796: {
! 797: vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
! 798: return CMD_WARNING;
! 799: }
! 800:
! 801: zif->rtadv.AdvDefaultLifetime = lifetime;
! 802:
! 803: return CMD_SUCCESS;
! 804: }
! 805:
! 806: DEFUN (no_ipv6_nd_ra_lifetime,
! 807: no_ipv6_nd_ra_lifetime_cmd,
! 808: "no ipv6 nd ra-lifetime",
! 809: NO_STR
! 810: "Interface IPv6 config commands\n"
! 811: "Neighbor discovery\n"
! 812: "Router lifetime\n")
! 813: {
! 814: struct interface *ifp;
! 815: struct zebra_if *zif;
! 816:
! 817: ifp = (struct interface *) vty->index;
! 818: zif = ifp->info;
! 819:
! 820: zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
! 821:
! 822: return CMD_SUCCESS;
! 823: }
! 824:
! 825: DEFUN (ipv6_nd_reachable_time,
! 826: ipv6_nd_reachable_time_cmd,
! 827: "ipv6 nd reachable-time MILLISECONDS",
! 828: "Interface IPv6 config commands\n"
! 829: "Neighbor discovery\n"
! 830: "Reachable time\n"
! 831: "Reachable time in milliseconds\n")
! 832: {
! 833: u_int32_t rtime;
! 834: struct interface *ifp;
! 835: struct zebra_if *zif;
! 836:
! 837: ifp = (struct interface *) vty->index;
! 838: zif = ifp->info;
! 839:
! 840: rtime = (u_int32_t) atol (argv[0]);
! 841:
! 842: if (rtime > RTADV_MAX_REACHABLE_TIME)
! 843: {
! 844: vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
! 845: return CMD_WARNING;
! 846: }
! 847:
! 848: zif->rtadv.AdvReachableTime = rtime;
! 849:
! 850: return CMD_SUCCESS;
! 851: }
! 852:
! 853: DEFUN (no_ipv6_nd_reachable_time,
! 854: no_ipv6_nd_reachable_time_cmd,
! 855: "no ipv6 nd reachable-time",
! 856: NO_STR
! 857: "Interface IPv6 config commands\n"
! 858: "Neighbor discovery\n"
! 859: "Reachable time\n")
! 860: {
! 861: struct interface *ifp;
! 862: struct zebra_if *zif;
! 863:
! 864: ifp = (struct interface *) vty->index;
! 865: zif = ifp->info;
! 866:
! 867: zif->rtadv.AdvReachableTime = 0;
! 868:
! 869: return CMD_SUCCESS;
! 870: }
! 871:
! 872: DEFUN (ipv6_nd_homeagent_preference,
! 873: ipv6_nd_homeagent_preference_cmd,
! 874: "ipv6 nd home-agent-preference PREFERENCE",
! 875: "Interface IPv6 config commands\n"
! 876: "Neighbor discovery\n"
! 877: "Home Agent preference\n"
! 878: "Home Agent preference value 0..65535\n")
! 879: {
! 880: u_int32_t hapref;
! 881: struct interface *ifp;
! 882: struct zebra_if *zif;
! 883:
! 884: ifp = (struct interface *) vty->index;
! 885: zif = ifp->info;
! 886:
! 887: hapref = (u_int32_t) atol (argv[0]);
! 888:
! 889: if (hapref > 65535)
! 890: {
! 891: vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
! 892: return CMD_WARNING;
! 893: }
! 894:
! 895: zif->rtadv.HomeAgentPreference = hapref;
! 896:
! 897: return CMD_SUCCESS;
! 898: }
! 899:
! 900: DEFUN (no_ipv6_nd_homeagent_preference,
! 901: no_ipv6_nd_homeagent_preference_cmd,
! 902: "no ipv6 nd home-agent-preference",
! 903: NO_STR
! 904: "Interface IPv6 config commands\n"
! 905: "Neighbor discovery\n"
! 906: "Home Agent preference\n")
! 907: {
! 908: struct interface *ifp;
! 909: struct zebra_if *zif;
! 910:
! 911: ifp = (struct interface *) vty->index;
! 912: zif = ifp->info;
! 913:
! 914: zif->rtadv.HomeAgentPreference = 0;
! 915:
! 916: return CMD_SUCCESS;
! 917: }
! 918:
! 919: DEFUN (ipv6_nd_homeagent_lifetime,
! 920: ipv6_nd_homeagent_lifetime_cmd,
! 921: "ipv6 nd home-agent-lifetime SECONDS",
! 922: "Interface IPv6 config commands\n"
! 923: "Neighbor discovery\n"
! 924: "Home Agent lifetime\n"
! 925: "Home Agent lifetime in seconds\n")
! 926: {
! 927: u_int32_t ha_ltime;
! 928: struct interface *ifp;
! 929: struct zebra_if *zif;
! 930:
! 931: ifp = (struct interface *) vty->index;
! 932: zif = ifp->info;
! 933:
! 934: ha_ltime = (u_int32_t) atol (argv[0]);
! 935:
! 936: if (ha_ltime > RTADV_MAX_HALIFETIME)
! 937: {
! 938: vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
! 939: return CMD_WARNING;
! 940: }
! 941:
! 942: zif->rtadv.HomeAgentLifetime = ha_ltime;
! 943:
! 944: return CMD_SUCCESS;
! 945: }
! 946:
! 947: DEFUN (no_ipv6_nd_homeagent_lifetime,
! 948: no_ipv6_nd_homeagent_lifetime_cmd,
! 949: "no ipv6 nd home-agent-lifetime",
! 950: NO_STR
! 951: "Interface IPv6 config commands\n"
! 952: "Neighbor discovery\n"
! 953: "Home Agent lifetime\n")
! 954: {
! 955: struct interface *ifp;
! 956: struct zebra_if *zif;
! 957:
! 958: ifp = (struct interface *) vty->index;
! 959: zif = ifp->info;
! 960:
! 961: zif->rtadv.HomeAgentLifetime = 0;
! 962:
! 963: return CMD_SUCCESS;
! 964: }
! 965:
! 966: DEFUN (ipv6_nd_managed_config_flag,
! 967: ipv6_nd_managed_config_flag_cmd,
! 968: "ipv6 nd managed-config-flag",
! 969: "Interface IPv6 config commands\n"
! 970: "Neighbor discovery\n"
! 971: "Managed address configuration flag\n")
! 972: {
! 973: struct interface *ifp;
! 974: struct zebra_if *zif;
! 975:
! 976: ifp = (struct interface *) vty->index;
! 977: zif = ifp->info;
! 978:
! 979: zif->rtadv.AdvManagedFlag = 1;
! 980:
! 981: return CMD_SUCCESS;
! 982: }
! 983:
! 984: DEFUN (no_ipv6_nd_managed_config_flag,
! 985: no_ipv6_nd_managed_config_flag_cmd,
! 986: "no ipv6 nd managed-config-flag",
! 987: NO_STR
! 988: "Interface IPv6 config commands\n"
! 989: "Neighbor discovery\n"
! 990: "Managed address configuration flag\n")
! 991: {
! 992: struct interface *ifp;
! 993: struct zebra_if *zif;
! 994:
! 995: ifp = (struct interface *) vty->index;
! 996: zif = ifp->info;
! 997:
! 998: zif->rtadv.AdvManagedFlag = 0;
! 999:
! 1000: return CMD_SUCCESS;
! 1001: }
! 1002:
! 1003: DEFUN (ipv6_nd_homeagent_config_flag,
! 1004: ipv6_nd_homeagent_config_flag_cmd,
! 1005: "ipv6 nd home-agent-config-flag",
! 1006: "Interface IPv6 config commands\n"
! 1007: "Neighbor discovery\n"
! 1008: "Home Agent configuration flag\n")
! 1009: {
! 1010: struct interface *ifp;
! 1011: struct zebra_if *zif;
! 1012:
! 1013: ifp = (struct interface *) vty->index;
! 1014: zif = ifp->info;
! 1015:
! 1016: zif->rtadv.AdvHomeAgentFlag = 1;
! 1017:
! 1018: return CMD_SUCCESS;
! 1019: }
! 1020:
! 1021: DEFUN (no_ipv6_nd_homeagent_config_flag,
! 1022: no_ipv6_nd_homeagent_config_flag_cmd,
! 1023: "no ipv6 nd home-agent-config-flag",
! 1024: NO_STR
! 1025: "Interface IPv6 config commands\n"
! 1026: "Neighbor discovery\n"
! 1027: "Home Agent configuration flag\n")
! 1028: {
! 1029: struct interface *ifp;
! 1030: struct zebra_if *zif;
! 1031:
! 1032: ifp = (struct interface *) vty->index;
! 1033: zif = ifp->info;
! 1034:
! 1035: zif->rtadv.AdvHomeAgentFlag = 0;
! 1036:
! 1037: return CMD_SUCCESS;
! 1038: }
! 1039:
! 1040: DEFUN (ipv6_nd_adv_interval_config_option,
! 1041: ipv6_nd_adv_interval_config_option_cmd,
! 1042: "ipv6 nd adv-interval-option",
! 1043: "Interface IPv6 config commands\n"
! 1044: "Neighbor discovery\n"
! 1045: "Advertisement Interval Option\n")
! 1046: {
! 1047: struct interface *ifp;
! 1048: struct zebra_if *zif;
! 1049:
! 1050: ifp = (struct interface *) vty->index;
! 1051: zif = ifp->info;
! 1052:
! 1053: zif->rtadv.AdvIntervalOption = 1;
! 1054:
! 1055: return CMD_SUCCESS;
! 1056: }
! 1057:
! 1058: DEFUN (no_ipv6_nd_adv_interval_config_option,
! 1059: no_ipv6_nd_adv_interval_config_option_cmd,
! 1060: "no ipv6 nd adv-interval-option",
! 1061: NO_STR
! 1062: "Interface IPv6 config commands\n"
! 1063: "Neighbor discovery\n"
! 1064: "Advertisement Interval Option\n")
! 1065: {
! 1066: struct interface *ifp;
! 1067: struct zebra_if *zif;
! 1068:
! 1069: ifp = (struct interface *) vty->index;
! 1070: zif = ifp->info;
! 1071:
! 1072: zif->rtadv.AdvIntervalOption = 0;
! 1073:
! 1074: return CMD_SUCCESS;
! 1075: }
! 1076:
! 1077: DEFUN (ipv6_nd_other_config_flag,
! 1078: ipv6_nd_other_config_flag_cmd,
! 1079: "ipv6 nd other-config-flag",
! 1080: "Interface IPv6 config commands\n"
! 1081: "Neighbor discovery\n"
! 1082: "Other statefull configuration flag\n")
! 1083: {
! 1084: struct interface *ifp;
! 1085: struct zebra_if *zif;
! 1086:
! 1087: ifp = (struct interface *) vty->index;
! 1088: zif = ifp->info;
! 1089:
! 1090: zif->rtadv.AdvOtherConfigFlag = 1;
! 1091:
! 1092: return CMD_SUCCESS;
! 1093: }
! 1094:
! 1095: DEFUN (no_ipv6_nd_other_config_flag,
! 1096: no_ipv6_nd_other_config_flag_cmd,
! 1097: "no ipv6 nd other-config-flag",
! 1098: NO_STR
! 1099: "Interface IPv6 config commands\n"
! 1100: "Neighbor discovery\n"
! 1101: "Other statefull configuration flag\n")
! 1102: {
! 1103: struct interface *ifp;
! 1104: struct zebra_if *zif;
! 1105:
! 1106: ifp = (struct interface *) vty->index;
! 1107: zif = ifp->info;
! 1108:
! 1109: zif->rtadv.AdvOtherConfigFlag = 0;
! 1110:
! 1111: return CMD_SUCCESS;
! 1112: }
! 1113:
! 1114: DEFUN (ipv6_nd_prefix,
! 1115: ipv6_nd_prefix_cmd,
! 1116: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1117: "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
! 1118: "Interface IPv6 config commands\n"
! 1119: "Neighbor discovery\n"
! 1120: "Prefix information\n"
! 1121: "IPv6 prefix\n"
! 1122: "Valid lifetime in seconds\n"
! 1123: "Infinite valid lifetime\n"
! 1124: "Preferred lifetime in seconds\n"
! 1125: "Infinite preferred lifetime\n"
! 1126: "Do not use prefix for onlink determination\n"
! 1127: "Do not use prefix for autoconfiguration\n"
! 1128: "Set Router Address flag\n")
! 1129: {
! 1130: int i;
! 1131: int ret;
! 1132: int cursor = 1;
! 1133: struct interface *ifp;
! 1134: struct zebra_if *zebra_if;
! 1135: struct rtadv_prefix rp;
! 1136:
! 1137: ifp = (struct interface *) vty->index;
! 1138: zebra_if = ifp->info;
! 1139:
! 1140: ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
! 1141: if (!ret)
! 1142: {
! 1143: vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
! 1144: return CMD_WARNING;
! 1145: }
! 1146: rp.AdvOnLinkFlag = 1;
! 1147: rp.AdvAutonomousFlag = 1;
! 1148: rp.AdvRouterAddressFlag = 0;
! 1149: rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
! 1150: rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
! 1151:
! 1152: if (argc > 1)
! 1153: {
! 1154: if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
! 1155: {
! 1156: if ( strncmp (argv[1], "i", 1) == 0)
! 1157: rp.AdvValidLifetime = UINT32_MAX;
! 1158: else
! 1159: rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
! 1160: (char **)NULL, 10);
! 1161:
! 1162: if ( strncmp (argv[2], "i", 1) == 0)
! 1163: rp.AdvPreferredLifetime = UINT32_MAX;
! 1164: else
! 1165: rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
! 1166: (char **)NULL, 10);
! 1167:
! 1168: if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
! 1169: {
! 1170: vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
! 1171: return CMD_WARNING;
! 1172: }
! 1173: cursor = cursor + 2;
! 1174: }
! 1175: if (argc > cursor)
! 1176: {
! 1177: for (i = cursor; i < argc; i++)
! 1178: {
! 1179: if (strncmp (argv[i], "of", 2) == 0)
! 1180: rp.AdvOnLinkFlag = 0;
! 1181: if (strncmp (argv[i], "no", 2) == 0)
! 1182: rp.AdvAutonomousFlag = 0;
! 1183: if (strncmp (argv[i], "ro", 2) == 0)
! 1184: rp.AdvRouterAddressFlag = 1;
! 1185: }
! 1186: }
! 1187: }
! 1188:
! 1189: rtadv_prefix_set (zebra_if, &rp);
! 1190:
! 1191: return CMD_SUCCESS;
! 1192: }
! 1193:
! 1194: ALIAS (ipv6_nd_prefix,
! 1195: ipv6_nd_prefix_val_nortaddr_cmd,
! 1196: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1197: "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
! 1198: "Interface IPv6 config commands\n"
! 1199: "Neighbor discovery\n"
! 1200: "Prefix information\n"
! 1201: "IPv6 prefix\n"
! 1202: "Valid lifetime in seconds\n"
! 1203: "Infinite valid lifetime\n"
! 1204: "Preferred lifetime in seconds\n"
! 1205: "Infinite preferred lifetime\n"
! 1206: "Do not use prefix for onlink determination\n"
! 1207: "Do not use prefix for autoconfiguration\n")
! 1208:
! 1209: ALIAS (ipv6_nd_prefix,
! 1210: ipv6_nd_prefix_val_rev_cmd,
! 1211: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1212: "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
! 1213: "Interface IPv6 config commands\n"
! 1214: "Neighbor discovery\n"
! 1215: "Prefix information\n"
! 1216: "IPv6 prefix\n"
! 1217: "Valid lifetime in seconds\n"
! 1218: "Infinite valid lifetime\n"
! 1219: "Preferred lifetime in seconds\n"
! 1220: "Infinite preferred lifetime\n"
! 1221: "Do not use prefix for autoconfiguration\n"
! 1222: "Do not use prefix for onlink determination\n")
! 1223:
! 1224: ALIAS (ipv6_nd_prefix,
! 1225: ipv6_nd_prefix_val_rev_rtaddr_cmd,
! 1226: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1227: "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
! 1228: "Interface IPv6 config commands\n"
! 1229: "Neighbor discovery\n"
! 1230: "Prefix information\n"
! 1231: "IPv6 prefix\n"
! 1232: "Valid lifetime in seconds\n"
! 1233: "Infinite valid lifetime\n"
! 1234: "Preferred lifetime in seconds\n"
! 1235: "Infinite preferred lifetime\n"
! 1236: "Do not use prefix for autoconfiguration\n"
! 1237: "Do not use prefix for onlink determination\n"
! 1238: "Set Router Address flag\n")
! 1239:
! 1240: ALIAS (ipv6_nd_prefix,
! 1241: ipv6_nd_prefix_val_noauto_cmd,
! 1242: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1243: "(<0-4294967295>|infinite) (no-autoconfig|)",
! 1244: "Interface IPv6 config commands\n"
! 1245: "Neighbor discovery\n"
! 1246: "Prefix information\n"
! 1247: "IPv6 prefix\n"
! 1248: "Valid lifetime in seconds\n"
! 1249: "Infinite valid lifetime\n"
! 1250: "Preferred lifetime in seconds\n"
! 1251: "Infinite preferred lifetime\n"
! 1252: "Do not use prefix for autoconfiguration")
! 1253:
! 1254: ALIAS (ipv6_nd_prefix,
! 1255: ipv6_nd_prefix_val_offlink_cmd,
! 1256: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1257: "(<0-4294967295>|infinite) (off-link|)",
! 1258: "Interface IPv6 config commands\n"
! 1259: "Neighbor discovery\n"
! 1260: "Prefix information\n"
! 1261: "IPv6 prefix\n"
! 1262: "Valid lifetime in seconds\n"
! 1263: "Infinite valid lifetime\n"
! 1264: "Preferred lifetime in seconds\n"
! 1265: "Infinite preferred lifetime\n"
! 1266: "Do not use prefix for onlink determination\n")
! 1267:
! 1268: ALIAS (ipv6_nd_prefix,
! 1269: ipv6_nd_prefix_val_rtaddr_cmd,
! 1270: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1271: "(<0-4294967295>|infinite) (router-address|)",
! 1272: "Interface IPv6 config commands\n"
! 1273: "Neighbor discovery\n"
! 1274: "Prefix information\n"
! 1275: "IPv6 prefix\n"
! 1276: "Valid lifetime in seconds\n"
! 1277: "Infinite valid lifetime\n"
! 1278: "Preferred lifetime in seconds\n"
! 1279: "Infinite preferred lifetime\n"
! 1280: "Set Router Address flag\n")
! 1281:
! 1282: ALIAS (ipv6_nd_prefix,
! 1283: ipv6_nd_prefix_val_cmd,
! 1284: "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
! 1285: "(<0-4294967295>|infinite)",
! 1286: "Interface IPv6 config commands\n"
! 1287: "Neighbor discovery\n"
! 1288: "Prefix information\n"
! 1289: "IPv6 prefix\n"
! 1290: "Valid lifetime in seconds\n"
! 1291: "Infinite valid lifetime\n"
! 1292: "Preferred lifetime in seconds\n"
! 1293: "Infinite preferred lifetime\n")
! 1294:
! 1295: ALIAS (ipv6_nd_prefix,
! 1296: ipv6_nd_prefix_noval_cmd,
! 1297: "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
! 1298: "Interface IPv6 config commands\n"
! 1299: "Neighbor discovery\n"
! 1300: "Prefix information\n"
! 1301: "IPv6 prefix\n"
! 1302: "Do not use prefix for autoconfiguration\n"
! 1303: "Do not use prefix for onlink determination\n")
! 1304:
! 1305: ALIAS (ipv6_nd_prefix,
! 1306: ipv6_nd_prefix_noval_rev_cmd,
! 1307: "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
! 1308: "Interface IPv6 config commands\n"
! 1309: "Neighbor discovery\n"
! 1310: "Prefix information\n"
! 1311: "IPv6 prefix\n"
! 1312: "Do not use prefix for onlink determination\n"
! 1313: "Do not use prefix for autoconfiguration\n")
! 1314:
! 1315: ALIAS (ipv6_nd_prefix,
! 1316: ipv6_nd_prefix_noval_noauto_cmd,
! 1317: "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
! 1318: "Interface IPv6 config commands\n"
! 1319: "Neighbor discovery\n"
! 1320: "Prefix information\n"
! 1321: "IPv6 prefix\n"
! 1322: "Do not use prefix for autoconfiguration\n")
! 1323:
! 1324: ALIAS (ipv6_nd_prefix,
! 1325: ipv6_nd_prefix_noval_offlink_cmd,
! 1326: "ipv6 nd prefix X:X::X:X/M (off-link|)",
! 1327: "Interface IPv6 config commands\n"
! 1328: "Neighbor discovery\n"
! 1329: "Prefix information\n"
! 1330: "IPv6 prefix\n"
! 1331: "Do not use prefix for onlink determination\n")
! 1332:
! 1333: ALIAS (ipv6_nd_prefix,
! 1334: ipv6_nd_prefix_noval_rtaddr_cmd,
! 1335: "ipv6 nd prefix X:X::X:X/M (router-address|)",
! 1336: "Interface IPv6 config commands\n"
! 1337: "Neighbor discovery\n"
! 1338: "Prefix information\n"
! 1339: "IPv6 prefix\n"
! 1340: "Set Router Address flag\n")
! 1341:
! 1342: ALIAS (ipv6_nd_prefix,
! 1343: ipv6_nd_prefix_prefix_cmd,
! 1344: "ipv6 nd prefix X:X::X:X/M",
! 1345: "Interface IPv6 config commands\n"
! 1346: "Neighbor discovery\n"
! 1347: "Prefix information\n"
! 1348: "IPv6 prefix\n")
! 1349:
! 1350: DEFUN (no_ipv6_nd_prefix,
! 1351: no_ipv6_nd_prefix_cmd,
! 1352: "no ipv6 nd prefix IPV6PREFIX",
! 1353: NO_STR
! 1354: "Interface IPv6 config commands\n"
! 1355: "Neighbor discovery\n"
! 1356: "Prefix information\n"
! 1357: "IPv6 prefix\n")
! 1358: {
! 1359: int ret;
! 1360: struct interface *ifp;
! 1361: struct zebra_if *zebra_if;
! 1362: struct rtadv_prefix rp;
! 1363:
! 1364: ifp = (struct interface *) vty->index;
! 1365: zebra_if = ifp->info;
! 1366:
! 1367: ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
! 1368: if (!ret)
! 1369: {
! 1370: vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
! 1371: return CMD_WARNING;
! 1372: }
! 1373:
! 1374: ret = rtadv_prefix_reset (zebra_if, &rp);
! 1375: if (!ret)
! 1376: {
! 1377: vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
! 1378: return CMD_WARNING;
! 1379: }
! 1380:
! 1381: return CMD_SUCCESS;
! 1382: }
! 1383:
! 1384: DEFUN (ipv6_nd_router_preference,
! 1385: ipv6_nd_router_preference_cmd,
! 1386: "ipv6 nd router-preference (high|medium|low)",
! 1387: "Interface IPv6 config commands\n"
! 1388: "Neighbor discovery\n"
! 1389: "Default router preference\n"
! 1390: "High default router preference\n"
! 1391: "Low default router preference\n"
! 1392: "Medium default router preference (default)\n")
! 1393: {
! 1394: struct interface *ifp;
! 1395: struct zebra_if *zif;
! 1396: int i = 0;
! 1397:
! 1398: ifp = (struct interface *) vty->index;
! 1399: zif = ifp->info;
! 1400:
! 1401: while (0 != rtadv_pref_strs[i])
! 1402: {
! 1403: if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
! 1404: {
! 1405: zif->rtadv.DefaultPreference = i;
! 1406: return CMD_SUCCESS;
! 1407: }
! 1408: i++;
! 1409: }
! 1410:
! 1411: return CMD_ERR_NO_MATCH;
! 1412: }
! 1413:
! 1414: DEFUN (no_ipv6_nd_router_preference,
! 1415: no_ipv6_nd_router_preference_cmd,
! 1416: "no ipv6 nd router-preference",
! 1417: NO_STR
! 1418: "Interface IPv6 config commands\n"
! 1419: "Neighbor discovery\n"
! 1420: "Default router preference\n")
! 1421: {
! 1422: struct interface *ifp;
! 1423: struct zebra_if *zif;
! 1424:
! 1425: ifp = (struct interface *) vty->index;
! 1426: zif = ifp->info;
! 1427:
! 1428: zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
! 1429:
! 1430: return CMD_SUCCESS;
! 1431: }
! 1432:
! 1433: /* Write configuration about router advertisement. */
! 1434: void
! 1435: rtadv_config_write (struct vty *vty, struct interface *ifp)
! 1436: {
! 1437: struct zebra_if *zif;
! 1438: struct listnode *node;
! 1439: struct rtadv_prefix *rprefix;
! 1440: u_char buf[INET6_ADDRSTRLEN];
! 1441: int interval;
! 1442:
! 1443: if (! rtadv)
! 1444: return;
! 1445:
! 1446: zif = ifp->info;
! 1447:
! 1448: if (! if_is_loopback (ifp))
! 1449: {
! 1450: if (zif->rtadv.AdvSendAdvertisements)
! 1451: vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
! 1452: else
! 1453: vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
! 1454: }
! 1455:
! 1456:
! 1457: interval = zif->rtadv.MaxRtrAdvInterval;
! 1458: if (interval % 1000)
! 1459: vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
! 1460: VTY_NEWLINE);
! 1461: else
! 1462: if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
! 1463: vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
! 1464: VTY_NEWLINE);
! 1465:
! 1466: if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
! 1467: vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
! 1468: VTY_NEWLINE);
! 1469:
! 1470: if (zif->rtadv.AdvReachableTime)
! 1471: vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
! 1472: VTY_NEWLINE);
! 1473:
! 1474: if (zif->rtadv.AdvManagedFlag)
! 1475: vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
! 1476:
! 1477: if (zif->rtadv.AdvOtherConfigFlag)
! 1478: vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
! 1479:
! 1480: if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
! 1481: vty_out (vty, " ipv6 nd router-preference %s%s",
! 1482: rtadv_pref_strs[zif->rtadv.DefaultPreference],
! 1483: VTY_NEWLINE);
! 1484:
! 1485: for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
! 1486: {
! 1487: vty_out (vty, " ipv6 nd prefix %s/%d",
! 1488: inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
! 1489: (char *) buf, INET6_ADDRSTRLEN),
! 1490: rprefix->prefix.prefixlen);
! 1491: if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
! 1492: (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
! 1493: {
! 1494: if (rprefix->AdvValidLifetime == UINT32_MAX)
! 1495: vty_out (vty, " infinite");
! 1496: else
! 1497: vty_out (vty, " %u", rprefix->AdvValidLifetime);
! 1498: if (rprefix->AdvPreferredLifetime == UINT32_MAX)
! 1499: vty_out (vty, " infinite");
! 1500: else
! 1501: vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
! 1502: }
! 1503: if (!rprefix->AdvOnLinkFlag)
! 1504: vty_out (vty, " off-link");
! 1505: if (!rprefix->AdvAutonomousFlag)
! 1506: vty_out (vty, " no-autoconfig");
! 1507: if (rprefix->AdvRouterAddressFlag)
! 1508: vty_out (vty, " router-address");
! 1509: vty_out (vty, "%s", VTY_NEWLINE);
! 1510: }
! 1511: }
! 1512:
! 1513:
! 1514: static void
! 1515: rtadv_event (enum rtadv_event event, int val)
! 1516: {
! 1517: switch (event)
! 1518: {
! 1519: case RTADV_START:
! 1520: if (! rtadv->ra_read)
! 1521: rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
! 1522: if (! rtadv->ra_timer)
! 1523: rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
! 1524: NULL, 0);
! 1525: break;
! 1526: case RTADV_STOP:
! 1527: if (rtadv->ra_timer)
! 1528: {
! 1529: thread_cancel (rtadv->ra_timer);
! 1530: rtadv->ra_timer = NULL;
! 1531: }
! 1532: if (rtadv->ra_read)
! 1533: {
! 1534: thread_cancel (rtadv->ra_read);
! 1535: rtadv->ra_read = NULL;
! 1536: }
! 1537: break;
! 1538: case RTADV_TIMER:
! 1539: if (! rtadv->ra_timer)
! 1540: rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
! 1541: val);
! 1542: break;
! 1543: case RTADV_TIMER_MSEC:
! 1544: if (! rtadv->ra_timer)
! 1545: rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
! 1546: NULL, val);
! 1547: break;
! 1548: case RTADV_READ:
! 1549: if (! rtadv->ra_read)
! 1550: rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
! 1551: break;
! 1552: default:
! 1553: break;
! 1554: }
! 1555: return;
! 1556: }
! 1557:
! 1558: void
! 1559: rtadv_init (void)
! 1560: {
! 1561: int sock;
! 1562:
! 1563: sock = rtadv_make_socket ();
! 1564: if (sock < 0)
! 1565: return;
! 1566:
! 1567: rtadv = rtadv_new ();
! 1568: rtadv->sock = sock;
! 1569:
! 1570: install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
! 1571: install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
! 1572: install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
! 1573: install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
! 1574: install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
! 1575: install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
! 1576: install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
! 1577: install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
! 1578: install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
! 1579: install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
! 1580: install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
! 1581: install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
! 1582: install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
! 1583: install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
! 1584: install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
! 1585: install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
! 1586: install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
! 1587: install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
! 1588: install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
! 1589: install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
! 1590: install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
! 1591: install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
! 1592: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
! 1593: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
! 1594: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
! 1595: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
! 1596: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
! 1597: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
! 1598: install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
! 1599: install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
! 1600: install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
! 1601: install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
! 1602: install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
! 1603: install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
! 1604: install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
! 1605: install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
! 1606: install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
! 1607: install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
! 1608: }
! 1609:
! 1610: static int
! 1611: if_join_all_router (int sock, struct interface *ifp)
! 1612: {
! 1613: int ret;
! 1614:
! 1615: struct ipv6_mreq mreq;
! 1616:
! 1617: memset (&mreq, 0, sizeof (struct ipv6_mreq));
! 1618: inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
! 1619: mreq.ipv6mr_interface = ifp->ifindex;
! 1620:
! 1621: ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
! 1622: (char *) &mreq, sizeof mreq);
! 1623: if (ret < 0)
! 1624: zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
! 1625:
! 1626: zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
! 1627:
! 1628: return 0;
! 1629: }
! 1630:
! 1631: static int
! 1632: if_leave_all_router (int sock, struct interface *ifp)
! 1633: {
! 1634: int ret;
! 1635:
! 1636: struct ipv6_mreq mreq;
! 1637:
! 1638: memset (&mreq, 0, sizeof (struct ipv6_mreq));
! 1639: inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
! 1640: mreq.ipv6mr_interface = ifp->ifindex;
! 1641:
! 1642: ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
! 1643: (char *) &mreq, sizeof mreq);
! 1644: if (ret < 0)
! 1645: zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
! 1646:
! 1647: zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
! 1648:
! 1649: return 0;
! 1650: }
! 1651:
! 1652: #else
! 1653: void
! 1654: rtadv_init (void)
! 1655: {
! 1656: /* Empty.*/;
! 1657: }
! 1658: #endif /* RTADV && HAVE_IPV6 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>