[BACK]Return to nd6_nbr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/netinet6/nd6_nbr.c between version 1.61 and 1.62

version 1.61, 2006/03/03 14:07:06 version 1.62, 2006/03/05 23:47:08
Line 58  __KERNEL_RCSID(0, "$NetBSD$");
Line 58  __KERNEL_RCSID(0, "$NetBSD$");
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/in_var.h>  #include <netinet/in_var.h>
 #include <netinet6/in6_var.h>  #include <netinet6/in6_var.h>
   #include <netinet6/in6_ifattach.h>
 #include <netinet/ip6.h>  #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>  #include <netinet6/ip6_var.h>
 #include <netinet6/scope6_var.h>  #include <netinet6/scope6_var.h>
Line 173  nd6_ns_input(m, off, icmp6len)
Line 174  nd6_ns_input(m, off, icmp6len)
          * Attaching target link-layer address to the NA?           * Attaching target link-layer address to the NA?
          * (RFC 2461 7.2.4)           * (RFC 2461 7.2.4)
          *           *
          * NS IP dst is unicast/anycast                 MUST NOT add           * NS IP dst is multicast                       MUST add
          * NS IP dst is solicited-node multicast        MUST add           * Otherwise                                    MAY be omitted
          *           *
          * In implementation, we add target link-layer address by default.           * In this implementation, we omit the target link-layer address
          * We do not add one in MUST NOT cases.           * in the "MAY" case.
          */           */
 #if 0 /* too much! */  #if 0 /* too much! */
         ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6);          ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6);
Line 200  nd6_ns_input(m, off, icmp6len)
Line 201  nd6_ns_input(m, off, icmp6len)
         ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);          ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
   
         /* (2) check. */          /* (2) check. */
         if (!ifa) {          if (ifa == NULL) {
                 struct rtentry *rt;                  struct rtentry *rt;
                 struct sockaddr_in6 tsin6;                  struct sockaddr_in6 tsin6;
   
                 bzero(&tsin6, sizeof tsin6);                  memset(&tsin6, 0, sizeof(tsin6));
                 tsin6.sin6_len = sizeof(struct sockaddr_in6);                  tsin6.sin6_len = sizeof(struct sockaddr_in6);
                 tsin6.sin6_family = AF_INET6;                  tsin6.sin6_family = AF_INET6;
                 tsin6.sin6_addr = taddr6;                  tsin6.sin6_addr = taddr6;
Line 226  nd6_ns_input(m, off, icmp6len)
Line 227  nd6_ns_input(m, off, icmp6len)
                 if (rt)                  if (rt)
                         rtfree(rt);                          rtfree(rt);
         }          }
         if (!ifa) {          if (ifa == NULL) {
                 /*                  /*
                  * We've got an NS packet, and we don't have that address                   * We've got an NS packet, and we don't have that address
                  * assigned for us.  We MUST silently ignore it.                   * assigned for us.  We MUST silently ignore it.
Line 424  nd6_ns_output(ifp, daddr6, taddr6, ln, d
Line 425  nd6_ns_output(ifp, daddr6, taddr6, ln, d
                 struct in6_addr *hsrc = NULL;                  struct in6_addr *hsrc = NULL;
   
                 if (ln && ln->ln_hold) {                  if (ln && ln->ln_hold) {
                           /*
                            * assuming every packet in ln_hold has the same IP
                            * header
                            */
                         hip6 = mtod(ln->ln_hold, struct ip6_hdr *);                          hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
                         /* XXX pullup? */                          /* XXX pullup? */
                         if (sizeof(*hip6) < ln->ln_hold->m_len)                          if (sizeof(*hip6) < ln->ln_hold->m_len)
Line 685  nd6_na_input(m, off, icmp6len)
Line 690  nd6_na_input(m, off, icmp6len)
                 /*                  /*
                  * Check if the link-layer address has changed or not.                   * Check if the link-layer address has changed or not.
                  */                   */
                 if (!lladdr)                  if (lladdr == NULL)
                         llchange = 0;                          llchange = 0;
                 else {                  else {
                         if (sdl->sdl_alen) {                          if (sdl->sdl_alen) {
Line 716  nd6_na_input(m, off, icmp6len)
Line 721  nd6_na_input(m, off, icmp6len)
                  *      1       1       y       n       (2a) L *->REACHABLE                   *      1       1       y       n       (2a) L *->REACHABLE
                  *      1       1       y       y       (2a) L *->REACHABLE                   *      1       1       y       y       (2a) L *->REACHABLE
                  */                   */
                 if (!is_override && (lladdr && llchange)) {        /* (1) */                  if (!is_override && lladdr != NULL && llchange) { /* (1) */
                         /*                          /*
                          * If state is REACHABLE, make it STALE.                           * If state is REACHABLE, make it STALE.
                          * no other updates should be done.                           * no other updates should be done.
Line 727  nd6_na_input(m, off, icmp6len)
Line 732  nd6_na_input(m, off, icmp6len)
                         }                          }
                         goto freeit;                          goto freeit;
                 } else if (is_override                             /* (2a) */                  } else if (is_override                             /* (2a) */
                         || (!is_override && (lladdr && !llchange)) /* (2b) */                      || (!is_override && lladdr != NULL && !llchange) /* (2b) */
                         || !lladdr) {                              /* (2c) */                      || lladdr == NULL) {                           /* (2c) */
                         /*                          /*
                          * Update link-local address, if any.                           * Update link-local address, if any.
                          */                           */
                         if (lladdr) {                          if (lladdr != NULL) {
                                 sdl->sdl_alen = ifp->if_addrlen;                                  sdl->sdl_alen = ifp->if_addrlen;
                                 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);                                  bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
                         }                          }
Line 797  nd6_na_input(m, off, icmp6len)
Line 802  nd6_na_input(m, off, icmp6len)
         rt->rt_flags &= ~RTF_REJECT;          rt->rt_flags &= ~RTF_REJECT;
         ln->ln_asked = 0;          ln->ln_asked = 0;
         if (ln->ln_hold) {          if (ln->ln_hold) {
                 /*                  struct mbuf *m_hold, *m_hold_next;
                  * we assume ifp is not a loopback here, so just set the 2nd  
                  * argument as the 1st one.                  for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) {
                  */                          struct mbuf *mpkt = NULL;
                 nd6_output(ifp, ifp, ln->ln_hold,  
                     (struct sockaddr_in6 *)rt_key(rt), rt);                          m_hold_next = m_hold->m_nextpkt;
                 ln->ln_hold = NULL;                          mpkt = m_copym(m_hold, 0, M_COPYALL, M_DONTWAIT);
                           if (mpkt == NULL) {
                                   m_freem(m_hold);
                                   break;
                           }
                           mpkt->m_nextpkt = NULL;
                           /*
                            * we assume ifp is not a loopback here, so just set
                            * the 2nd argument as the 1st one.
                            */
                           nd6_output(ifp, ifp, mpkt,
                               (struct sockaddr_in6 *)rt_key(rt), rt);
                   }
                   ln->ln_hold = NULL;
         }          }
   
  freeit:   freeit:
Line 1056  nd6_dad_stoptimer(dp)
Line 1074  nd6_dad_stoptimer(dp)
  * Start Duplicate Address Detection (DAD) for specified interface address.   * Start Duplicate Address Detection (DAD) for specified interface address.
  */   */
 void  void
 nd6_dad_start(ifa, xtick)  nd6_dad_start(ifa, delay)
         struct ifaddr *ifa;          struct ifaddr *ifa;
         int *xtick;     /* minimum delay ticks for IFF_UP event */          int delay;      /* minimum delay ticks for IFF_UP event */
 {  {
         struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;          struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
         struct dadq *dp;          struct dadq *dp;
Line 1090  nd6_dad_start(ifa, xtick)
Line 1108  nd6_dad_start(ifa, xtick)
                 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;                  ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
                 return;                  return;
         }          }
         if (!ifa->ifa_ifp)          if (ifa->ifa_ifp == NULL)
                 panic("nd6_dad_start: ifa->ifa_ifp == NULL");                  panic("nd6_dad_start: ifa->ifa_ifp == NULL");
         if (!(ifa->ifa_ifp->if_flags & IFF_UP))          if (!(ifa->ifa_ifp->if_flags & IFF_UP))
                 return;                  return;
Line 1125  nd6_dad_start(ifa, xtick)
Line 1143  nd6_dad_start(ifa, xtick)
         dp->dad_count = ip6_dad_count;          dp->dad_count = ip6_dad_count;
         dp->dad_ns_icount = dp->dad_na_icount = 0;          dp->dad_ns_icount = dp->dad_na_icount = 0;
         dp->dad_ns_ocount = dp->dad_ns_tcount = 0;          dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
         if (xtick == NULL) {          if (delay == 0) {
                 nd6_dad_ns_output(dp, ifa);                  nd6_dad_ns_output(dp, ifa);
                 nd6_dad_starttimer(dp,                  nd6_dad_starttimer(dp,
                     (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);                      (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
         } else {          } else
                 int ntick;                  nd6_dad_starttimer(dp, delay);
   
                 if (*xtick == 0)  
                         ntick = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);  
                 else  
                         ntick = *xtick + arc4random() % (hz / 2);  
                 *xtick = ntick;  
                 nd6_dad_starttimer(dp, ntick);  
         }  
 }  }
   
 /*  /*
Line 1153  nd6_dad_stop(ifa)
Line 1163  nd6_dad_stop(ifa)
         if (!dad_init)          if (!dad_init)
                 return;                  return;
         dp = nd6_dad_find(ifa);          dp = nd6_dad_find(ifa);
         if (!dp) {          if (dp == NULL) {
                 /* DAD wasn't started yet */                  /* DAD wasn't started yet */
                 return;                  return;
         }          }
Line 1275  nd6_dad_duplicated(ifa)
Line 1285  nd6_dad_duplicated(ifa)
         struct ifaddr *ifa;          struct ifaddr *ifa;
 {  {
         struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;          struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
           struct ifnet *ifp;
         struct dadq *dp;          struct dadq *dp;
   
         dp = nd6_dad_find(ifa);          dp = nd6_dad_find(ifa);
Line 1283  nd6_dad_duplicated(ifa)
Line 1294  nd6_dad_duplicated(ifa)
                 return;                  return;
         }          }
   
           ifp = ifa->ifa_ifp;
         log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "          log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
             "NS in/out=%d/%d, NA in=%d\n",              "NS in/out=%d/%d, NA in=%d\n",
             if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr),              if_name(ifp), ip6_sprintf(&ia->ia_addr.sin6_addr),
             dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount);              dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount);
   
         ia->ia6_flags &= ~IN6_IFF_TENTATIVE;          ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
Line 1295  nd6_dad_duplicated(ifa)
Line 1307  nd6_dad_duplicated(ifa)
         nd6_dad_stoptimer(dp);          nd6_dad_stoptimer(dp);
   
         log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",          log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
             if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));              if_name(ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
         log(LOG_ERR, "%s: manual intervention required\n",          log(LOG_ERR, "%s: manual intervention required\n",
             if_name(ifa->ifa_ifp));              if_name(ifp));
   
           /*
            * If the address is a link-local address formed from an interface
            * identifier based on the hardware address which is supposed to be
            * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
            * operation on the interface SHOULD be disabled.
            * [rfc2462bis-03 Section 5.4.5]
            */
           if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
                   struct in6_addr in6;
   
                   /*
                    * To avoid over-reaction, we only apply this logic when we are
                    * very sure that hardware addresses are supposed to be unique.
                    */
                   switch (ifp->if_type) {
                   case IFT_ETHER:
                   case IFT_FDDI:
                   case IFT_ATM:
                   case IFT_IEEE1394:
   #ifdef IFT_IEEE80211
                   case IFT_IEEE80211:
   #endif
                           in6 = ia->ia_addr.sin6_addr;
                           if (in6_get_hw_ifid(ifp, &in6) == 0 &&
                               IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
                                   ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
                                   log(LOG_ERR, "%s: possible hardware address "
                                       "duplication detected, disable IPv6\n",
                                       if_name(ifp));
                           }
                           break;
                   }
           }
   
         TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);          TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
         free(dp, M_IP6NDP);          free(dp, M_IP6NDP);
Line 1340  nd6_dad_ns_input(ifa)
Line 1386  nd6_dad_ns_input(ifa)
         struct dadq *dp;          struct dadq *dp;
         int duplicate;          int duplicate;
   
         if (!ifa)          if (ifa == NULL)
                 panic("ifa == NULL in nd6_dad_ns_input");                  panic("ifa == NULL in nd6_dad_ns_input");
   
         ia = (struct in6_ifaddr *)ifa;          ia = (struct in6_ifaddr *)ifa;
Line 1361  nd6_dad_ns_input(ifa)
Line 1407  nd6_dad_ns_input(ifa)
          * if I'm yet to start DAD, someone else started using this address           * if I'm yet to start DAD, someone else started using this address
          * first.  I have a duplicate and you win.           * first.  I have a duplicate and you win.
          */           */
         if (!dp || dp->dad_ns_ocount == 0)          if (dp == NULL || dp->dad_ns_ocount == 0)
                 duplicate++;                  duplicate++;
   
         /* XXX more checks for loopback situation - see nd6_dad_timer too */          /* XXX more checks for loopback situation - see nd6_dad_timer too */
Line 1385  nd6_dad_na_input(ifa)
Line 1431  nd6_dad_na_input(ifa)
 {  {
         struct dadq *dp;          struct dadq *dp;
   
         if (!ifa)          if (ifa == NULL)
                 panic("ifa == NULL in nd6_dad_na_input");                  panic("ifa == NULL in nd6_dad_na_input");
   
         dp = nd6_dad_find(ifa);          dp = nd6_dad_find(ifa);

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.62

CVSweb <webmaster@jp.NetBSD.org>