File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / rtadv.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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