Diff for /embedaddon/quagga/zebra/rtadv.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2012/02/21 17:26:11 version 1.1.1.3, 2016/11/02 10:09:10
Line 31 Line 31
 #include "linklist.h"  #include "linklist.h"
 #include "command.h"  #include "command.h"
 #include "privs.h"  #include "privs.h"
   #include "vrf.h"
   
 #include "zebra/interface.h"  #include "zebra/interface.h"
 #include "zebra/rtadv.h"  #include "zebra/rtadv.h"
Line 40 Line 41
   
 extern struct zebra_privs_t zserv_privs;  extern struct zebra_privs_t zserv_privs;
   
#if defined (HAVE_IPV6) && defined (RTADV)#if defined (HAVE_IPV6) && defined (HAVE_RTADV)
   
 #ifdef OPEN_BSD  #ifdef OPEN_BSD
 #include <netinet/icmp6.h>  #include <netinet/icmp6.h>
Line 62  extern struct zebra_t zebrad; Line 63  extern struct zebra_t zebrad;
 enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,   enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, 
                   RTADV_TIMER_MSEC, RTADV_READ};                    RTADV_TIMER_MSEC, RTADV_READ};
   
static void rtadv_event (enum rtadv_event, int);static void rtadv_event (struct zebra_vrf *, enum rtadv_event, int);
   
 static int if_join_all_router (int, struct interface *);  static int if_join_all_router (int, struct interface *);
 static int if_leave_all_router (int, struct interface *);  static int if_leave_all_router (int, struct interface *);
   
 /* Structure which hold status of router advertisement. */  
 struct rtadv  
 {  
   int sock;  
   
   int adv_if_count;  
   int adv_msec_if_count;  
   
   struct thread *ra_read;  
   struct thread *ra_timer;  
 };  
   
 struct rtadv *rtadv = NULL;  
   
 static struct rtadv *  
 rtadv_new (void)  
 {  
   return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));  
 }  
   
 static int  static int
 rtadv_recv_packet (int sock, u_char *buf, int buflen,  rtadv_recv_packet (int sock, u_char *buf, int buflen,
                   struct sockaddr_in6 *from, unsigned int *ifindex,                   struct sockaddr_in6 *from, ifindex_t *ifindex,
                    int *hoplimit)                     int *hoplimit)
 {  {
   int ret;    int ret;
Line 163  rtadv_send_packet (int sock, struct interface *ifp) Line 144  rtadv_send_packet (int sock, struct interface *ifp)
   struct rtadv_prefix *rprefix;    struct rtadv_prefix *rprefix;
   u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};    u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
   struct listnode *node;    struct listnode *node;
     u_int16_t pkt_RouterLifetime;
   
   /*    /*
    * Allocate control message bufffer.  This is dynamic because     * Allocate control message bufffer.  This is dynamic because
Line 190  rtadv_send_packet (int sock, struct interface *ifp) Line 172  rtadv_send_packet (int sock, struct interface *ifp)
   addr.sin6_len = sizeof (struct sockaddr_in6);    addr.sin6_len = sizeof (struct sockaddr_in6);
 #endif /* SIN6_LEN */  #endif /* SIN6_LEN */
   addr.sin6_port = htons (IPPROTO_ICMPV6);    addr.sin6_port = htons (IPPROTO_ICMPV6);
  memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));  IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
   
   /* Fetch interface information. */    /* Fetch interface information. */
   zif = ifp->info;    zif = ifp->info;
Line 215  rtadv_send_packet (int sock, struct interface *ifp) Line 197  rtadv_send_packet (int sock, struct interface *ifp)
     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;      rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
   if (zif->rtadv.AdvHomeAgentFlag)    if (zif->rtadv.AdvHomeAgentFlag)
     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;      rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
  rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);  /* Note that according to Neighbor Discovery (RFC 4861 [18]),
    * AdvDefaultLifetime is by default based on the value of
    * MaxRtrAdvInterval.  AdvDefaultLifetime is used in the Router Lifetime
    * field of Router Advertisements.  Given that this field is expressed
    * in seconds, a small MaxRtrAdvInterval value can result in a zero
    * value for this field.  To prevent this, routers SHOULD keep
    * AdvDefaultLifetime in at least one second, even if the use of
    * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
   pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
     zif->rtadv.AdvDefaultLifetime :
     MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
   rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
   rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);    rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
   rtadv->nd_ra_retransmit = htonl (0);    rtadv->nd_ra_retransmit = htonl (0);
   
   len = sizeof (struct nd_router_advert);    len = sizeof (struct nd_router_advert);
   
  if (zif->rtadv.AdvHomeAgentFlag)  /* If both the Home Agent Preference and Home Agent Lifetime are set to
    * their default values specified above, this option SHOULD NOT be
    * included in the Router Advertisement messages sent by this home
    * agent. -- RFC6275, 7.4 */
   if
   (
     zif->rtadv.AdvHomeAgentFlag &&
     (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
   )
     {      {
       struct nd_opt_homeagent_info *ndopt_hai =         struct nd_opt_homeagent_info *ndopt_hai = 
         (struct nd_opt_homeagent_info *)(buf + len);          (struct nd_opt_homeagent_info *)(buf + len);
Line 229  rtadv_send_packet (int sock, struct interface *ifp) Line 230  rtadv_send_packet (int sock, struct interface *ifp)
       ndopt_hai->nd_opt_hai_len = 1;        ndopt_hai->nd_opt_hai_len = 1;
       ndopt_hai->nd_opt_hai_reserved = 0;        ndopt_hai->nd_opt_hai_reserved = 0;
       ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);        ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
      ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);      /* 16-bit unsigned integer.  The lifetime associated with the home
        * agent in units of seconds.  The default value is the same as the
        * Router Lifetime, as specified in the main body of the Router
        * Advertisement.  The maximum value corresponds to 18.2 hours.  A
        * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
       ndopt_hai->nd_opt_hai_lifetime = htons
       (
         zif->rtadv.HomeAgentLifetime != -1 ?
         zif->rtadv.HomeAgentLifetime :
         MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
       );
       len += sizeof(struct nd_opt_homeagent_info);        len += sizeof(struct nd_opt_homeagent_info);
     }      }
   
Line 267  rtadv_send_packet (int sock, struct interface *ifp) Line 278  rtadv_send_packet (int sock, struct interface *ifp)
       pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);        pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
       pinfo->nd_opt_pi_reserved2 = 0;        pinfo->nd_opt_pi_reserved2 = 0;
   
      memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,      IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
              sizeof (struct in6_addr)); 
   
 #ifdef DEBUG  #ifdef DEBUG
       {        {
Line 284  rtadv_send_packet (int sock, struct interface *ifp) Line 294  rtadv_send_packet (int sock, struct interface *ifp)
     }      }
   
   /* Hardware address. */    /* Hardware address. */
 #ifdef HAVE_STRUCT_SOCKADDR_DL  
   sdl = &ifp->sdl;  
   if (sdl != NULL && sdl->sdl_alen != 0)  
     {  
       buf[len++] = ND_OPT_SOURCE_LINKADDR;  
   
       /* Option length should be rounded up to next octet if  
          the link address does not end on an octet boundary. */  
       buf[len++] = (sdl->sdl_alen + 9) >> 3;  
   
       memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);  
       len += sdl->sdl_alen;  
   
       /* Pad option to end on an octet boundary. */  
       memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);  
       len += -(sdl->sdl_alen + 2) & 0x7;  
     }  
 #else  
   if (ifp->hw_addr_len != 0)    if (ifp->hw_addr_len != 0)
     {      {
       buf[len++] = ND_OPT_SOURCE_LINKADDR;        buf[len++] = ND_OPT_SOURCE_LINKADDR;
Line 317  rtadv_send_packet (int sock, struct interface *ifp) Line 309  rtadv_send_packet (int sock, struct interface *ifp)
       memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);        memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
       len += -(ifp->hw_addr_len + 2) & 0x7;        len += -(ifp->hw_addr_len + 2) & 0x7;
     }      }
 #endif /* HAVE_STRUCT_SOCKADDR_DL */  
   
     /* MTU */
     if (zif->rtadv.AdvLinkMTU)
       {
         struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
         opt->nd_opt_mtu_type = ND_OPT_MTU;
         opt->nd_opt_mtu_len = 1;
         opt->nd_opt_mtu_reserved = 0;
         opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
         len += sizeof (struct nd_opt_mtu);
       }
   
   msg.msg_name = (void *) &addr;    msg.msg_name = (void *) &addr;
   msg.msg_namelen = sizeof (struct sockaddr_in6);    msg.msg_namelen = sizeof (struct sockaddr_in6);
   msg.msg_iov = &iov;    msg.msg_iov = &iov;
Line 349  rtadv_send_packet (int sock, struct interface *ifp) Line 351  rtadv_send_packet (int sock, struct interface *ifp)
 static int  static int
 rtadv_timer (struct thread *thread)  rtadv_timer (struct thread *thread)
 {  {
     struct zebra_vrf *zvrf = THREAD_ARG (thread);
   struct listnode *node, *nnode;    struct listnode *node, *nnode;
   struct interface *ifp;    struct interface *ifp;
   struct zebra_if *zif;    struct zebra_if *zif;
   int period;    int period;
   
  rtadv->ra_timer = NULL;  zvrf->rtadv.ra_timer = NULL;
  if (rtadv->adv_msec_if_count == 0)  if (zvrf->rtadv.adv_msec_if_count == 0)
     {      {
       period = 1000; /* 1 s */        period = 1000; /* 1 s */
      rtadv_event (RTADV_TIMER, 1 /* 1 s */);      rtadv_event (zvrf, RTADV_TIMER, 1 /* 1 s */);
     }       } 
   else    else
     {      {
       period = 10; /* 10 ms */        period = 10; /* 10 ms */
      rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);      rtadv_event (zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
     }      }
   
  for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))  for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf->vrf_id), node, nnode, ifp))
     {      {
      if (if_is_loopback (ifp))      if (if_is_loopback (ifp) || ! if_is_operative (ifp))
         continue;          continue;
   
       zif = ifp->info;        zif = ifp->info;
Line 378  rtadv_timer (struct thread *thread) Line 381  rtadv_timer (struct thread *thread)
           zif->rtadv.AdvIntervalTimer -= period;            zif->rtadv.AdvIntervalTimer -= period;
           if (zif->rtadv.AdvIntervalTimer <= 0)            if (zif->rtadv.AdvIntervalTimer <= 0)
             {              {
                 /* FIXME: using MaxRtrAdvInterval each time isn't what section
                    6.2.4 of RFC4861 tells to do. */
               zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;                zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
              rtadv_send_packet (rtadv->sock, ifp);              rtadv_send_packet (zvrf->rtadv.sock, ifp);
             }              }
         }          }
     }      }
Line 389  rtadv_timer (struct thread *thread) Line 394  rtadv_timer (struct thread *thread)
 static void  static void
 rtadv_process_solicit (struct interface *ifp)  rtadv_process_solicit (struct interface *ifp)
 {  {
  zlog_info ("Router solicitation received on %s", ifp->name);  struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
   
  rtadv_send_packet (rtadv->sock, ifp);  zlog_info ("Router solicitation received on %s vrf %u", ifp->name, zvrf->vrf_id);
 
   rtadv_send_packet (zvrf->rtadv.sock, ifp);
 }  }
   
 static void  static void
Line 401  rtadv_process_advert (void) Line 408  rtadv_process_advert (void)
 }  }
   
 static void  static void
rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex,
     int hoplimit, vrf_id_t vrf_id)
 {  {
   struct icmp6_hdr *icmph;    struct icmp6_hdr *icmph;
   struct interface *ifp;    struct interface *ifp;
   struct zebra_if *zif;    struct zebra_if *zif;
   
   /* Interface search. */    /* Interface search. */
  ifp = if_lookup_by_index (ifindex);  ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
   if (ifp == NULL)    if (ifp == NULL)
     {      {
      zlog_warn ("Unknown interface index: %d", ifindex);      zlog_warn ("Unknown interface index: %d, vrf %u", ifindex, vrf_id);
       return;        return;
     }      }
   
Line 464  rtadv_read (struct thread *thread) Line 472  rtadv_read (struct thread *thread)
   int len;    int len;
   u_char buf[RTADV_MSG_SIZE];    u_char buf[RTADV_MSG_SIZE];
   struct sockaddr_in6 from;    struct sockaddr_in6 from;
  unsigned int ifindex = 0;  ifindex_t ifindex = 0;
   int hoplimit = -1;    int hoplimit = -1;
     struct zebra_vrf *zvrf = THREAD_ARG (thread);
   
   sock = THREAD_FD (thread);    sock = THREAD_FD (thread);
  rtadv->ra_read = NULL;  zvrf->rtadv.ra_read = NULL;
   
   /* Register myself. */    /* Register myself. */
  rtadv_event (RTADV_READ, sock);  rtadv_event (zvrf, RTADV_READ, sock);
   
   len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);    len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
   
Line 481  rtadv_read (struct thread *thread) Line 490  rtadv_read (struct thread *thread)
       return len;        return len;
     }      }
   
  rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);  rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, zvrf->vrf_id);
   
   return 0;    return 0;
 }  }
   
 static int  static int
rtadv_make_socket (void)rtadv_make_socket (vrf_id_t vrf_id)
 {  {
   int sock;    int sock;
   int ret;    int ret;
Line 497  rtadv_make_socket (void) Line 506  rtadv_make_socket (void)
        zlog_err ("rtadv_make_socket: could not raise privs, %s",         zlog_err ("rtadv_make_socket: could not raise privs, %s",
                   safe_strerror (errno) );                    safe_strerror (errno) );
                                       
  sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);  sock = vrf_socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, vrf_id);
   
   if ( zserv_privs.change (ZPRIVS_LOWER) )    if ( zserv_privs.change (ZPRIVS_LOWER) )
        zlog_err ("rtadv_make_socket: could not lower privs, %s",         zlog_err ("rtadv_make_socket: could not lower privs, %s",
Line 506  rtadv_make_socket (void) Line 515  rtadv_make_socket (void)
   /* When we can't make ICMPV6 socket simply back.  Router    /* When we can't make ICMPV6 socket simply back.  Router
      advertisement feature will not be supported. */       advertisement feature will not be supported. */
   if (sock < 0)    if (sock < 0)
    return -1;    {
       close (sock);
       return -1;
     }
   
   ret = setsockopt_ipv6_pktinfo (sock, 1);    ret = setsockopt_ipv6_pktinfo (sock, 1);
   if (ret < 0)    if (ret < 0)
    return ret;    {
       close (sock);
       return ret;
     }
   ret = setsockopt_ipv6_multicast_loop (sock, 0);    ret = setsockopt_ipv6_multicast_loop (sock, 0);
   if (ret < 0)    if (ret < 0)
    return ret;    {
       close (sock);
       return ret;
     }
   ret = setsockopt_ipv6_unicast_hops (sock, 255);    ret = setsockopt_ipv6_unicast_hops (sock, 255);
   if (ret < 0)    if (ret < 0)
    return ret;    {
       close (sock);
       return ret;
     }
   ret = setsockopt_ipv6_multicast_hops (sock, 255);    ret = setsockopt_ipv6_multicast_hops (sock, 255);
   if (ret < 0)    if (ret < 0)
    return ret;    {
       close (sock);
       return ret;
     }
   ret = setsockopt_ipv6_hoplimit (sock, 1);    ret = setsockopt_ipv6_hoplimit (sock, 1);
   if (ret < 0)    if (ret < 0)
    return ret;    {
       close (sock);
       return ret;
     }
   
   ICMP6_FILTER_SETBLOCKALL(&filter);    ICMP6_FILTER_SETBLOCKALL(&filter);
   ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);    ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
Line 538  rtadv_make_socket (void) Line 565  rtadv_make_socket (void)
   
   return sock;    return sock;
 }  }
 static struct rtadv_prefix *  static struct rtadv_prefix *
 rtadv_prefix_new (void)  rtadv_prefix_new (void)
 {  {
Line 552  rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix) Line 579  rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
 }  }
   
 static struct rtadv_prefix *  static struct rtadv_prefix *
rtadv_prefix_lookup (struct list *rplist, struct prefix *p)rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
 {  {
   struct listnode *node;    struct listnode *node;
   struct rtadv_prefix *rprefix;    struct rtadv_prefix *rprefix;
   
   for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))    for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
    if (prefix_same (&rprefix->prefix, p))    if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
       return rprefix;        return rprefix;
   return NULL;    return NULL;
 }  }
   
 static struct rtadv_prefix *  static struct rtadv_prefix *
rtadv_prefix_get (struct list *rplist, struct prefix *p)rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
 {  {
   struct rtadv_prefix *rprefix;    struct rtadv_prefix *rprefix;
       
Line 573  rtadv_prefix_get (struct list *rplist, struct prefix * Line 600  rtadv_prefix_get (struct list *rplist, struct prefix *
     return rprefix;      return rprefix;
   
   rprefix = rtadv_prefix_new ();    rprefix = rtadv_prefix_new ();
  memcpy (&rprefix->prefix, p, sizeof (struct prefix));  memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
   listnode_add (rplist, rprefix);    listnode_add (rplist, rprefix);
   
   return rprefix;    return rprefix;
Line 619  DEFUN (ipv6_nd_suppress_ra, Line 646  DEFUN (ipv6_nd_suppress_ra,
 {  {
   struct interface *ifp;    struct interface *ifp;
   struct zebra_if *zif;    struct zebra_if *zif;
     struct zebra_vrf *zvrf;
   
   ifp = vty->index;    ifp = vty->index;
   zif = ifp->info;    zif = ifp->info;
     zvrf = vrf_info_lookup (ifp->vrf_id);
   
   if (if_is_loopback (ifp))    if (if_is_loopback (ifp))
     {      {
Line 633  DEFUN (ipv6_nd_suppress_ra, Line 662  DEFUN (ipv6_nd_suppress_ra,
     {      {
       zif->rtadv.AdvSendAdvertisements = 0;        zif->rtadv.AdvSendAdvertisements = 0;
       zif->rtadv.AdvIntervalTimer = 0;        zif->rtadv.AdvIntervalTimer = 0;
      rtadv->adv_if_count--;      zvrf->rtadv.adv_if_count--;
   
      if_leave_all_router (rtadv->sock, ifp);      if_leave_all_router (zvrf->rtadv.sock, ifp);
   
      if (rtadv->adv_if_count == 0)      if (zvrf->rtadv.adv_if_count == 0)
        rtadv_event (RTADV_STOP, 0);        rtadv_event (zvrf, RTADV_STOP, 0);
     }      }
   
   return CMD_SUCCESS;    return CMD_SUCCESS;
Line 654  DEFUN (no_ipv6_nd_suppress_ra, Line 683  DEFUN (no_ipv6_nd_suppress_ra,
 {  {
   struct interface *ifp;    struct interface *ifp;
   struct zebra_if *zif;    struct zebra_if *zif;
     struct zebra_vrf *zvrf;
   
   ifp = vty->index;    ifp = vty->index;
   zif = ifp->info;    zif = ifp->info;
     zvrf = vrf_info_lookup (ifp->vrf_id);
   
   if (if_is_loopback (ifp))    if (if_is_loopback (ifp))
     {      {
Line 668  DEFUN (no_ipv6_nd_suppress_ra, Line 699  DEFUN (no_ipv6_nd_suppress_ra,
     {      {
       zif->rtadv.AdvSendAdvertisements = 1;        zif->rtadv.AdvSendAdvertisements = 1;
       zif->rtadv.AdvIntervalTimer = 0;        zif->rtadv.AdvIntervalTimer = 0;
      rtadv->adv_if_count++;      zvrf->rtadv.adv_if_count++;
   
      if_join_all_router (rtadv->sock, ifp);      if_join_all_router (zvrf->rtadv.sock, ifp);
   
      if (rtadv->adv_if_count == 1)      if (zvrf->rtadv.adv_if_count == 1)
        rtadv_event (RTADV_START, rtadv->sock);        rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock);
     }      }
   
   return CMD_SUCCESS;    return CMD_SUCCESS;
Line 681  DEFUN (no_ipv6_nd_suppress_ra, Line 712  DEFUN (no_ipv6_nd_suppress_ra,
   
 DEFUN (ipv6_nd_ra_interval_msec,  DEFUN (ipv6_nd_ra_interval_msec,
        ipv6_nd_ra_interval_msec_cmd,         ipv6_nd_ra_interval_msec_cmd,
       "ipv6 nd ra-interval msec MILLISECONDS",       "ipv6 nd ra-interval msec <70-1800000>",
        "Interface IPv6 config commands\n"         "Interface IPv6 config commands\n"
        "Neighbor discovery\n"         "Neighbor discovery\n"
        "Router Advertisement interval\n"         "Router Advertisement interval\n"
        "Router Advertisement interval in milliseconds\n")         "Router Advertisement interval in milliseconds\n")
 {  {
  int interval;  unsigned interval;
  struct interface *ifp;  struct interface *ifp = (struct interface *) vty->index;
  struct zebra_if *zif;  struct zebra_if *zif = ifp->info;
   struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
   
  ifp = (struct interface *) vty->index;  VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
  zif = ifp->info;  if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
   {
     vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
     return CMD_WARNING;
   }
   
   interval = atoi (argv[0]);  
   
   if (interval <= 0)  
     {  
       vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);  
       return CMD_WARNING;  
     }  
   
   if (zif->rtadv.MaxRtrAdvInterval % 1000)    if (zif->rtadv.MaxRtrAdvInterval % 1000)
    rtadv->adv_msec_if_count--;    zvrf->rtadv.adv_msec_if_count--;
   
   if (interval % 1000)    if (interval % 1000)
    rtadv->adv_msec_if_count++;    zvrf->rtadv.adv_msec_if_count++;
       
   zif->rtadv.MaxRtrAdvInterval = interval;    zif->rtadv.MaxRtrAdvInterval = interval;
   zif->rtadv.MinRtrAdvInterval = 0.33 * interval;    zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
Line 717  DEFUN (ipv6_nd_ra_interval_msec, Line 745  DEFUN (ipv6_nd_ra_interval_msec,
   
 DEFUN (ipv6_nd_ra_interval,  DEFUN (ipv6_nd_ra_interval,
        ipv6_nd_ra_interval_cmd,         ipv6_nd_ra_interval_cmd,
       "ipv6 nd ra-interval SECONDS",       "ipv6 nd ra-interval <1-1800>",
        "Interface IPv6 config commands\n"         "Interface IPv6 config commands\n"
        "Neighbor discovery\n"         "Neighbor discovery\n"
        "Router Advertisement interval\n"         "Router Advertisement interval\n"
        "Router Advertisement interval in seconds\n")         "Router Advertisement interval in seconds\n")
 {  {
  int interval;  unsigned interval;
  struct interface *ifp;  struct interface *ifp = (struct interface *) vty->index;
  struct zebra_if *zif;  struct zebra_if *zif = ifp->info;
   struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
   
  ifp = (struct interface *) vty->index;  VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
  zif = ifp->info;  if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
   {
     vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
     return CMD_WARNING;
   }
   
   interval = atoi (argv[0]);  
   
   if (interval <= 0)  
     {  
       vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);  
       return CMD_WARNING;  
     }  
   
   if (zif->rtadv.MaxRtrAdvInterval % 1000)    if (zif->rtadv.MaxRtrAdvInterval % 1000)
    rtadv->adv_msec_if_count--;    zvrf->rtadv.adv_msec_if_count--;
                   
   /* convert to milliseconds */    /* convert to milliseconds */
   interval = interval * 1000;     interval = interval * 1000; 
Line 761  DEFUN (no_ipv6_nd_ra_interval, Line 786  DEFUN (no_ipv6_nd_ra_interval,
 {  {
   struct interface *ifp;    struct interface *ifp;
   struct zebra_if *zif;    struct zebra_if *zif;
     struct zebra_vrf *zvrf;
   
   ifp = (struct interface *) vty->index;    ifp = (struct interface *) vty->index;
   zif = ifp->info;    zif = ifp->info;
     zvrf = vrf_info_lookup (ifp->vrf_id);
   
   if (zif->rtadv.MaxRtrAdvInterval % 1000)    if (zif->rtadv.MaxRtrAdvInterval % 1000)
    rtadv->adv_msec_if_count--;    zvrf->rtadv.adv_msec_if_count--;
       
   zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;    zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
   zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;    zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
Line 775  DEFUN (no_ipv6_nd_ra_interval, Line 802  DEFUN (no_ipv6_nd_ra_interval,
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
   ALIAS (no_ipv6_nd_ra_interval,
          no_ipv6_nd_ra_interval_val_cmd,
          "no ipv6 nd ra-interval <1-1800>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Router Advertisement interval\n")
   
   ALIAS (no_ipv6_nd_ra_interval,
          no_ipv6_nd_ra_interval_msec_val_cmd,
          "no ipv6 nd ra-interval msec <1-1800000>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Router Advertisement interval\n"
          "Router Advertisement interval in milliseconds\n")
   
 DEFUN (ipv6_nd_ra_lifetime,  DEFUN (ipv6_nd_ra_lifetime,
        ipv6_nd_ra_lifetime_cmd,         ipv6_nd_ra_lifetime_cmd,
       "ipv6 nd ra-lifetime SECONDS",       "ipv6 nd ra-lifetime <0-9000>",
        "Interface IPv6 config commands\n"         "Interface IPv6 config commands\n"
        "Neighbor discovery\n"         "Neighbor discovery\n"
        "Router lifetime\n"         "Router lifetime\n"
       "Router lifetime in seconds\n")       "Router lifetime in seconds (0 stands for a non-default gw)\n")
 {  {
   int lifetime;    int lifetime;
   struct interface *ifp;    struct interface *ifp;
Line 790  DEFUN (ipv6_nd_ra_lifetime, Line 834  DEFUN (ipv6_nd_ra_lifetime,
   ifp = (struct interface *) vty->index;    ifp = (struct interface *) vty->index;
   zif = ifp->info;    zif = ifp->info;
   
  lifetime = atoi (argv[0]);  VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
   
  if (lifetime < 0 || lifetime > 0xffff)  /* The value to be placed in the Router Lifetime field
    * of Router Advertisements sent from the interface,
    * in seconds.  MUST be either zero or between
    * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
   if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
     {      {
      vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);      vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
       return CMD_WARNING;        return CMD_WARNING;
     }      }
   
Line 817  DEFUN (no_ipv6_nd_ra_lifetime, Line 865  DEFUN (no_ipv6_nd_ra_lifetime,
   ifp = (struct interface *) vty->index;    ifp = (struct interface *) vty->index;
   zif = ifp->info;    zif = ifp->info;
   
  zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;  zif->rtadv.AdvDefaultLifetime = -1;
   
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
   ALIAS (no_ipv6_nd_ra_lifetime,
          no_ipv6_nd_ra_lifetime_val_cmd,
          "no ipv6 nd ra-lifetime <0-9000>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Router lifetime\n"
          "Router lifetime in seconds (0 stands for a non-default gw)\n")
   
 DEFUN (ipv6_nd_reachable_time,  DEFUN (ipv6_nd_reachable_time,
        ipv6_nd_reachable_time_cmd,         ipv6_nd_reachable_time_cmd,
       "ipv6 nd reachable-time MILLISECONDS",       "ipv6 nd reachable-time <1-3600000>",
        "Interface IPv6 config commands\n"         "Interface IPv6 config commands\n"
        "Neighbor discovery\n"         "Neighbor discovery\n"
        "Reachable time\n"         "Reachable time\n"
        "Reachable time in milliseconds\n")         "Reachable time in milliseconds\n")
 {  {
  u_int32_t rtime;  struct interface *ifp = (struct interface *) vty->index;
  struct interface *ifp;  struct zebra_if *zif = ifp->info;
  struct zebra_if *zif;  VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
 
  ifp = (struct interface *) vty->index; 
  zif = ifp->info; 
 
  rtime = (u_int32_t) atol (argv[0]); 
 
  if (rtime > RTADV_MAX_REACHABLE_TIME) 
    { 
      vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE); 
      return CMD_WARNING; 
    } 
 
  zif->rtadv.AdvReachableTime = rtime; 
 
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
Line 869  DEFUN (no_ipv6_nd_reachable_time, Line 912  DEFUN (no_ipv6_nd_reachable_time,
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
   ALIAS (no_ipv6_nd_reachable_time,
          no_ipv6_nd_reachable_time_val_cmd,
          "no ipv6 nd reachable-time <1-3600000>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Reachable time\n"
          "Reachable time in milliseconds\n")
   
 DEFUN (ipv6_nd_homeagent_preference,  DEFUN (ipv6_nd_homeagent_preference,
        ipv6_nd_homeagent_preference_cmd,         ipv6_nd_homeagent_preference_cmd,
       "ipv6 nd home-agent-preference PREFERENCE",       "ipv6 nd home-agent-preference <0-65535>",
        "Interface IPv6 config commands\n"         "Interface IPv6 config commands\n"
        "Neighbor discovery\n"         "Neighbor discovery\n"
        "Home Agent preference\n"         "Home Agent preference\n"
       "Home Agent preference value 0..65535\n")       "preference value (default is 0, least preferred)\n")
 {  {
  u_int32_t hapref;  struct interface *ifp = (struct interface *) vty->index;
  struct interface *ifp;  struct zebra_if *zif = ifp->info;
  struct zebra_if *zif;  VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
 
  ifp = (struct interface *) vty->index; 
  zif = ifp->info; 
 
  hapref = (u_int32_t) atol (argv[0]); 
 
  if (hapref > 65535) 
    { 
      vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE); 
      return CMD_WARNING; 
    } 
 
  zif->rtadv.HomeAgentPreference = hapref; 
 
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
Line 916  DEFUN (no_ipv6_nd_homeagent_preference, Line 954  DEFUN (no_ipv6_nd_homeagent_preference,
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
   ALIAS (no_ipv6_nd_homeagent_preference,
          no_ipv6_nd_homeagent_preference_val_cmd,
          "no ipv6 nd home-agent-preference <0-65535>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Home Agent preference\n"
          "preference value (default is 0, least preferred)\n")
   
 DEFUN (ipv6_nd_homeagent_lifetime,  DEFUN (ipv6_nd_homeagent_lifetime,
        ipv6_nd_homeagent_lifetime_cmd,         ipv6_nd_homeagent_lifetime_cmd,
       "ipv6 nd home-agent-lifetime SECONDS",       "ipv6 nd home-agent-lifetime <0-65520>",
        "Interface IPv6 config commands\n"         "Interface IPv6 config commands\n"
        "Neighbor discovery\n"         "Neighbor discovery\n"
        "Home Agent lifetime\n"         "Home Agent lifetime\n"
       "Home Agent lifetime in seconds\n")       "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
 {  {
  u_int32_t ha_ltime;  struct interface *ifp = (struct interface *) vty->index;
  struct interface *ifp;  struct zebra_if *zif = ifp->info;
  struct zebra_if *zif;  VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
 
  ifp = (struct interface *) vty->index; 
  zif = ifp->info; 
 
  ha_ltime = (u_int32_t) atol (argv[0]); 
 
  if (ha_ltime > RTADV_MAX_HALIFETIME) 
    { 
      vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE); 
      return CMD_WARNING; 
    } 
 
  zif->rtadv.HomeAgentLifetime = ha_ltime; 
 
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
Line 958  DEFUN (no_ipv6_nd_homeagent_lifetime, Line 991  DEFUN (no_ipv6_nd_homeagent_lifetime,
   ifp = (struct interface *) vty->index;    ifp = (struct interface *) vty->index;
   zif = ifp->info;    zif = ifp->info;
   
  zif->rtadv.HomeAgentLifetime = 0;  zif->rtadv.HomeAgentLifetime = -1;
   
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
   ALIAS (no_ipv6_nd_homeagent_lifetime,
          no_ipv6_nd_homeagent_lifetime_val_cmd,
          "no ipv6 nd home-agent-lifetime <0-65520>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Home Agent lifetime\n"
          "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
   
 DEFUN (ipv6_nd_managed_config_flag,  DEFUN (ipv6_nd_managed_config_flag,
        ipv6_nd_managed_config_flag_cmd,         ipv6_nd_managed_config_flag_cmd,
        "ipv6 nd managed-config-flag",         "ipv6 nd managed-config-flag",
Line 1137  DEFUN (ipv6_nd_prefix, Line 1179  DEFUN (ipv6_nd_prefix,
   ifp = (struct interface *) vty->index;    ifp = (struct interface *) vty->index;
   zebra_if = ifp->info;    zebra_if = ifp->info;
   
  ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);  ret = str2prefix_ipv6 (argv[0], &rp.prefix);
   if (!ret)    if (!ret)
     {      {
       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);        vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
       return CMD_WARNING;        return CMD_WARNING;
     }      }
     apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
   rp.AdvOnLinkFlag = 1;    rp.AdvOnLinkFlag = 1;
   rp.AdvAutonomousFlag = 1;    rp.AdvAutonomousFlag = 1;
   rp.AdvRouterAddressFlag = 0;    rp.AdvRouterAddressFlag = 0;
Line 1151  DEFUN (ipv6_nd_prefix, Line 1194  DEFUN (ipv6_nd_prefix,
   
   if (argc > 1)    if (argc > 1)
     {      {
      if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)      if ((isdigit((unsigned char)argv[1][0]))
           || strncmp (argv[1], "i", 1) == 0)
         {          {
           if ( strncmp (argv[1], "i", 1) == 0)            if ( strncmp (argv[1], "i", 1) == 0)
             rp.AdvValidLifetime = UINT32_MAX;              rp.AdvValidLifetime = UINT32_MAX;
Line 1364  DEFUN (no_ipv6_nd_prefix, Line 1408  DEFUN (no_ipv6_nd_prefix,
   ifp = (struct interface *) vty->index;    ifp = (struct interface *) vty->index;
   zebra_if = ifp->info;    zebra_if = ifp->info;
   
  ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);  ret = str2prefix_ipv6 (argv[0], &rp.prefix);
   if (!ret)    if (!ret)
     {      {
       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);        vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
       return CMD_WARNING;        return CMD_WARNING;
     }      }
     apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
   
   ret = rtadv_prefix_reset (zebra_if, &rp);    ret = rtadv_prefix_reset (zebra_if, &rp);
   if (!ret)    if (!ret)
Line 1430  DEFUN (no_ipv6_nd_router_preference, Line 1475  DEFUN (no_ipv6_nd_router_preference,
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
   
   ALIAS (no_ipv6_nd_router_preference,
          no_ipv6_nd_router_preference_val_cmd,
          "no ipv6 nd router-preference (high|medium|low)",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Default router preference\n"
          "High default router preference\n"
          "Low default router preference\n"
          "Medium default router preference (default)\n")
   
   DEFUN (ipv6_nd_mtu,
          ipv6_nd_mtu_cmd,
          "ipv6 nd mtu <1-65535>",
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Advertised MTU\n"
          "MTU in bytes\n")
   {
     struct interface *ifp = (struct interface *) vty->index;
     struct zebra_if *zif = ifp->info;
     VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
     return CMD_SUCCESS;
   }
   
   DEFUN (no_ipv6_nd_mtu,
          no_ipv6_nd_mtu_cmd,
          "no ipv6 nd mtu",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Advertised MTU\n")
   {
     struct interface *ifp = (struct interface *) vty->index;
     struct zebra_if *zif = ifp->info;
     zif->rtadv.AdvLinkMTU = 0;
     return CMD_SUCCESS;
   }
   
   ALIAS (no_ipv6_nd_mtu,
          no_ipv6_nd_mtu_val_cmd,
          "no ipv6 nd mtu <1-65535>",
          NO_STR
          "Interface IPv6 config commands\n"
          "Neighbor discovery\n"
          "Advertised MTU\n"
          "MTU in bytes\n")
   
 /* Write configuration about router advertisement. */  /* Write configuration about router advertisement. */
 void  void
 rtadv_config_write (struct vty *vty, struct interface *ifp)  rtadv_config_write (struct vty *vty, struct interface *ifp)
Line 1437  rtadv_config_write (struct vty *vty, struct interface  Line 1530  rtadv_config_write (struct vty *vty, struct interface 
   struct zebra_if *zif;    struct zebra_if *zif;
   struct listnode *node;    struct listnode *node;
   struct rtadv_prefix *rprefix;    struct rtadv_prefix *rprefix;
  u_char buf[INET6_ADDRSTRLEN];  char buf[PREFIX_STRLEN];
   int interval;    int interval;
   
   if (! rtadv)  
     return;  
   
   zif = ifp->info;    zif = ifp->info;
   
   if (! if_is_loopback (ifp))    if (! if_is_loopback (ifp))
Line 1463  rtadv_config_write (struct vty *vty, struct interface  Line 1553  rtadv_config_write (struct vty *vty, struct interface 
       vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,        vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
              VTY_NEWLINE);               VTY_NEWLINE);
   
  if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)  if (zif->rtadv.AdvIntervalOption)
     vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
 
   if (zif->rtadv.AdvDefaultLifetime != -1)
     vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,      vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
              VTY_NEWLINE);               VTY_NEWLINE);
   
     if (zif->rtadv.HomeAgentPreference)
       vty_out (vty, " ipv6 nd home-agent-preference %u%s",
                zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
   
     if (zif->rtadv.HomeAgentLifetime != -1)
       vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
                zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
   
     if (zif->rtadv.AdvHomeAgentFlag)
       vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
   
   if (zif->rtadv.AdvReachableTime)    if (zif->rtadv.AdvReachableTime)
     vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,      vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
              VTY_NEWLINE);               VTY_NEWLINE);
Line 1482  rtadv_config_write (struct vty *vty, struct interface  Line 1586  rtadv_config_write (struct vty *vty, struct interface 
              rtadv_pref_strs[zif->rtadv.DefaultPreference],               rtadv_pref_strs[zif->rtadv.DefaultPreference],
              VTY_NEWLINE);               VTY_NEWLINE);
   
     if (zif->rtadv.AdvLinkMTU)
       vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
   
   for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))    for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
     {      {
      vty_out (vty, " ipv6 nd prefix %s/%d",      vty_out (vty, " ipv6 nd prefix %s",
               inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,                prefix2str (&rprefix->prefix, buf, sizeof(buf)));
                          (char *) buf, INET6_ADDRSTRLEN), 
               rprefix->prefix.prefixlen); 
       if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||         if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) || 
           (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))            (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
         {          {
Line 1512  rtadv_config_write (struct vty *vty, struct interface  Line 1617  rtadv_config_write (struct vty *vty, struct interface 
   
   
 static void  static void
rtadv_event (enum rtadv_event event, int val)rtadv_event (struct zebra_vrf *zvrf, enum rtadv_event event, int val)
 {  {
     struct rtadv *rtadv = &zvrf->rtadv;
   
   switch (event)    switch (event)
     {      {
     case RTADV_START:      case RTADV_START:
       if (! rtadv->ra_read)        if (! rtadv->ra_read)
        rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);        rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
       if (! rtadv->ra_timer)        if (! rtadv->ra_timer)
         rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,          rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
                                            NULL, 0);                                            zvrf, 0);
       break;        break;
     case RTADV_STOP:      case RTADV_STOP:
       if (rtadv->ra_timer)        if (rtadv->ra_timer)
Line 1537  rtadv_event (enum rtadv_event event, int val) Line 1644  rtadv_event (enum rtadv_event event, int val)
       break;        break;
     case RTADV_TIMER:      case RTADV_TIMER:
       if (! rtadv->ra_timer)        if (! rtadv->ra_timer)
        rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,        rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zvrf,
                                             val);                                              val);
       break;        break;
     case RTADV_TIMER_MSEC:      case RTADV_TIMER_MSEC:
       if (! rtadv->ra_timer)        if (! rtadv->ra_timer)
         rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,           rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer, 
                                            NULL, val);                                            zvrf, val);
       break;        break;
     case RTADV_READ:      case RTADV_READ:
       if (! rtadv->ra_read)        if (! rtadv->ra_read)
        rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);        rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
       break;        break;
     default:      default:
       break;        break;
Line 1556  rtadv_event (enum rtadv_event event, int val) Line 1663  rtadv_event (enum rtadv_event event, int val)
 }  }
   
 void  void
rtadv_init (void)rtadv_init (struct zebra_vrf *zvrf)
 {  {
  int sock;  zvrf->rtadv.sock = rtadv_make_socket (zvrf->vrf_id);
 }
   
  sock = rtadv_make_socket ();void
  if (sock < 0)rtadv_terminate (struct zebra_vrf *zvrf)
    return;{
   rtadv_event (zvrf, RTADV_STOP, 0);
   
  rtadv = rtadv_new ();  if (zvrf->rtadv.sock >= 0)
  rtadv->sock = sock;    {
       close (zvrf->rtadv.sock);
       zvrf->rtadv.sock = -1;
     }
   
     zvrf->rtadv.adv_if_count = 0;
     zvrf->rtadv.adv_msec_if_count = 0;
   }
   
   void
   rtadv_cmd_init (void)
   {
   install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
Line 1584  rtadv_init (void) Line 1707  rtadv_init (void)
   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
Line 1605  rtadv_init (void) Line 1730  rtadv_init (void)
   install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
   install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
     install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
     install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
 }  }
   
 static int  static int
Line 1651  if_leave_all_router (int sock, struct interface *ifp) Line 1780  if_leave_all_router (int sock, struct interface *ifp)
   
 #else  #else
 void  void
rtadv_init (void)rtadv_init (struct zebra_vrf *zvrf)
 {  {
   /* Empty.*/;    /* Empty.*/;
 }  }
#endif /* RTADV && HAVE_IPV6 */void
 rtadv_terminate (struct zebra_vrf *zvrf)
 {
   /* Empty.*/;
 }
 void
 rtadv_cmd_init (void)
 {
   /* Empty.*/;
 }
 #endif /* HAVE_RTADV && HAVE_IPV6 */

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


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