File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / rtadv.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

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