File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / rtadv.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:29 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>