src/node/ipv6-address.cc
changeset 5891 09a575cdf8db
parent 5796 cd4576c14476
equal deleted inserted replaced
5890:9c48446a0946 5891:09a575cdf8db
    44  * \note Adapted from Jens Jakobsen implementation (chillispot).
    44  * \note Adapted from Jens Jakobsen implementation (chillispot).
    45  */
    45  */
    46 static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level)
    46 static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level)
    47 {
    47 {
    48 #define mix(a, b, c) \
    48 #define mix(a, b, c) \
    49 ({ \
    49   ({ \
    50     (a) -= (b); (a) -= (c); (a) ^= ((c) >> 13); \
    50    (a) -= (b); (a) -= (c); (a) ^= ((c) >> 13); \
    51     (b) -= (c); (b) -= (a); (b) ^= ((a) << 8);  \
    51    (b) -= (c); (b) -= (a); (b) ^= ((a) << 8);  \
    52     (c) -= (a); (c) -= (b); (c) ^= ((b) >> 13); \
    52    (c) -= (a); (c) -= (b); (c) ^= ((b) >> 13); \
    53     (a) -= (b); (a) -= (c); (a) ^= ((c) >> 12); \
    53    (a) -= (b); (a) -= (c); (a) ^= ((c) >> 12); \
    54     (b) -= (c); (b) -= (a); (b) ^= ((a) << 16); \
    54    (b) -= (c); (b) -= (a); (b) ^= ((a) << 16); \
    55     (c) -= (a); (c) -= (b); (c) ^= ((b) >> 5);  \
    55    (c) -= (a); (c) -= (b); (c) ^= ((b) >> 5);  \
    56     (a) -= (b); (a) -= (c); (a) ^= ((c) >> 3);  \
    56    (a) -= (b); (a) -= (c); (a) ^= ((c) >> 3);  \
    57     (b) -= (c); (b) -= (a); (b) ^= ((a) << 10); \
    57    (b) -= (c); (b) -= (a); (b) ^= ((a) << 10); \
    58     (c) -= (a); (c) -= (b); (c) ^= ((b) >> 15); \
    58    (c) -= (a); (c) -= (b); (c) ^= ((b) >> 15); \
    59 })
    59    })
    60 
    60 
    61   typedef uint32_t  ub4;   /* unsigned 4-byte quantities */
    61   typedef uint32_t  ub4;   /* unsigned 4-byte quantities */
    62   typedef unsigned  char ub1;   /* unsigned 1-byte quantities */
    62   typedef unsigned  char ub1;   /* unsigned 1-byte quantities */
    63   uint32_t a = 0;
    63   uint32_t a = 0;
    64   uint32_t b = 0;
    64   uint32_t b = 0;
    70   a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
    70   a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
    71   c = level;           /* the previous hash value */
    71   c = level;           /* the previous hash value */
    72 
    72 
    73   /* handle most of the key */
    73   /* handle most of the key */
    74   while (len >= 12)
    74   while (len >= 12)
    75   {
    75     {
    76     a += (k[0] + ((ub4)k[1] << 8) + ((ub4)k[2] << 16) + ((ub4)k[3] << 24));
    76       a += (k[0] + ((ub4)k[1] << 8) + ((ub4)k[2] << 16) + ((ub4)k[3] << 24));
    77     b += (k[4] + ((ub4)k[5] << 8) + ((ub4)k[6] << 16) + ((ub4)k[7] << 24));
    77       b += (k[4] + ((ub4)k[5] << 8) + ((ub4)k[6] << 16) + ((ub4)k[7] << 24));
    78     c += (k[8] + ((ub4)k[9] << 8) + ((ub4)k[10] << 16) + ((ub4)k[11] << 24));
    78       c += (k[8] + ((ub4)k[9] << 8) + ((ub4)k[10] << 16) + ((ub4)k[11] << 24));
    79     mix (a, b, c);
    79       mix (a, b, c);
    80     k += 12; 
    80       k += 12; 
    81     len -= 12;
    81       len -= 12;
    82   }
    82     }
    83 
    83 
    84   /* handle the last 11 bytes */
    84   /* handle the last 11 bytes */
    85   c += length;
    85   c += length;
    86   switch (len) /* all the case statements fall through */
    86   switch (len) /* all the case statements fall through */
    87   {
    87     {
    88     case 11: c += ((ub4)k[10] << 24);
    88     case 11: c += ((ub4)k[10] << 24);
    89     case 10: c += ((ub4)k[9] << 16);
    89     case 10: c += ((ub4)k[9] << 16);
    90     case 9 : c += ((ub4)k[8] << 8); /* the first byte of c is reserved for the length */
    90     case 9 : c += ((ub4)k[8] << 8); /* the first byte of c is reserved for the length */
    91     case 8 : b += ((ub4)k[7] << 24);
    91     case 8 : b += ((ub4)k[7] << 24);
    92     case 7 : b += ((ub4)k[6] << 16);
    92     case 7 : b += ((ub4)k[6] << 16);
    94     case 5 : b += k[4];
    94     case 5 : b += k[4];
    95     case 4 : a += ((ub4)k[3] << 24);
    95     case 4 : a += ((ub4)k[3] << 24);
    96     case 3 : a += ((ub4)k[2] << 16);
    96     case 3 : a += ((ub4)k[2] << 16);
    97     case 2 : a += ((ub4)k[1] << 8);
    97     case 2 : a += ((ub4)k[1] << 8);
    98     case 1 : a += k[0];
    98     case 1 : a += k[0];
    99     /* case 0: nothing left to add */
    99              /* case 0: nothing left to add */
   100   }
   100     }
   101   mix (a, b, c);
   101   mix (a, b, c);
   102   
   102 
   103 #undef mix
   103 #undef mix
   104 
   104 
   105   /* report the result */
   105   /* report the result */
   106   return c;
   106   return c;
   107 }
   107 }
   133   memset (tp, 0x00, 16);
   133   memset (tp, 0x00, 16);
   134   endp = tp + 16;
   134   endp = tp + 16;
   135 
   135 
   136   /* Leading :: requires some special handling. */
   136   /* Leading :: requires some special handling. */
   137   if (*address == ':')
   137   if (*address == ':')
   138   {
   138     {
   139     if (*++address != ':')
   139       if (*++address != ':')
   140     {
   140         {
       
   141           return (0);
       
   142         }
       
   143     }
       
   144   curtok = address;
       
   145 
       
   146   while ((ch = *address++) != '\0')
       
   147     {
       
   148       const char *pch = 0;
       
   149 
       
   150       if ((pch = strchr ((xdigits = xdigits_l), ch)) == 0)
       
   151         {
       
   152           pch = strchr ((xdigits = xdigits_u), ch);
       
   153         }
       
   154 
       
   155       if (pch != 0)
       
   156         {
       
   157           val <<= 4;
       
   158           val |= (pch - xdigits);
       
   159 
       
   160           if (++seen_xdigits > 4)
       
   161             {
       
   162               return (0);
       
   163             }
       
   164           continue;
       
   165         }
       
   166       if (ch == ':')
       
   167         {
       
   168           curtok = address;
       
   169 
       
   170           if (!seen_xdigits)
       
   171             {
       
   172               if (colonp)
       
   173                 return (0);
       
   174               colonp = tp;
       
   175               continue;
       
   176             }
       
   177 
       
   178           if (tp + 2 > endp)
       
   179             {
       
   180               return (0);
       
   181             }
       
   182 
       
   183           *tp++ = (unsigned char) (val >> 8) & 0xff;
       
   184           *tp++ = (unsigned char) val & 0xff;
       
   185           seen_xdigits = 0;
       
   186           val = 0;
       
   187           continue;
       
   188         }
       
   189 
       
   190       /* TODO Handle IPv4 mapped address (2001::192.168.0.1) */
       
   191 #if 0
       
   192       if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) &&
       
   193           inet_pton4(curtok, tp) > 0)
       
   194         {
       
   195           tp += 4 /*NS_INADDRSZ*/;
       
   196           seen_xdigits = 0;
       
   197           break;/* '\0' was seen by inet_pton4(). */
       
   198         }
       
   199 #endif
   141       return (0);
   200       return (0);
   142     }
   201     }
   143   }
   202 
   144   curtok = address;
   203   if (seen_xdigits)
   145 
   204     {
   146   while ((ch = *address++) != '\0')
   205       if (tp + 2 > endp)
   147   {
   206         {
   148     const char *pch = 0;
       
   149 
       
   150     if ((pch = strchr ((xdigits = xdigits_l), ch)) == 0)
       
   151     {
       
   152       pch = strchr ((xdigits = xdigits_u), ch);
       
   153     }
       
   154 
       
   155     if (pch != 0)
       
   156     {
       
   157       val <<= 4;
       
   158       val |= (pch - xdigits);
       
   159 
       
   160       if (++seen_xdigits > 4)
       
   161       {
       
   162         return (0);
       
   163       }
       
   164       continue;
       
   165     }
       
   166     if (ch == ':')
       
   167     {
       
   168       curtok = address;
       
   169 
       
   170       if (!seen_xdigits)
       
   171       {
       
   172         if (colonp)
       
   173           return (0);
   207           return (0);
   174         colonp = tp;
   208         }
   175         continue;
       
   176       }
       
   177 
       
   178       if (tp + 2 > endp)
       
   179       {
       
   180         return (0);
       
   181       }
       
   182 
       
   183       *tp++ = (unsigned char) (val >> 8) & 0xff;
   209       *tp++ = (unsigned char) (val >> 8) & 0xff;
   184       *tp++ = (unsigned char) val & 0xff;
   210       *tp++ = (unsigned char) val & 0xff;
   185       seen_xdigits = 0;
   211     }
   186       val = 0;
   212 
   187       continue;
   213   if (colonp != 0)
   188     }
   214     {
   189 
   215       /*
   190     /* TODO Handle IPv4 mapped address (2001::192.168.0.1) */
   216        * Since some memmove ()'s erroneously fail to handle
   191 #if 0
   217        * overlapping regions, we'll do the shift by hand.
   192     if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) &&
   218        */
   193         inet_pton4(curtok, tp) > 0)
   219       const int n = tp - colonp;
   194     {
   220       int i = 0;
   195       tp += 4 /*NS_INADDRSZ*/;
   221 
   196       seen_xdigits = 0;
   222       if (tp == endp)
   197       break;/* '\0' was seen by inet_pton4(). */
   223         {
   198     }
   224           return (0);
   199 #endif
   225         }
   200     return (0);
   226 
   201   }
   227       for (i = 1; i <= n; i++)
   202 
   228         {
   203   if (seen_xdigits)
   229           endp[- i] = colonp[n - i];
   204   {
   230           colonp[n - i] = 0;
   205     if (tp + 2 > endp)
   231         }
       
   232 
       
   233       tp = endp;
       
   234     }
       
   235 
       
   236   if (tp != endp)
   206     {
   237     {
   207       return (0);
   238       return (0);
   208     }
   239     }
   209     *tp++ = (unsigned char) (val >> 8) & 0xff;
       
   210     *tp++ = (unsigned char) val & 0xff;
       
   211   }
       
   212 
       
   213   if (colonp != 0)
       
   214   {
       
   215     /*
       
   216      * Since some memmove ()'s erroneously fail to handle
       
   217      * overlapping regions, we'll do the shift by hand.
       
   218      */
       
   219     const int n = tp - colonp;
       
   220     int i = 0;
       
   221 
       
   222     if (tp == endp)
       
   223     {
       
   224       return (0);
       
   225     }
       
   226 
       
   227     for (i = 1; i <= n; i++)
       
   228     {
       
   229       endp[- i] = colonp[n - i];
       
   230       colonp[n - i] = 0;
       
   231     }
       
   232 
       
   233     tp = endp;
       
   234   }
       
   235 
       
   236   if (tp != endp)
       
   237   {
       
   238     return (0);
       
   239   }
       
   240 
   240 
   241   memcpy (addr, tmp, 16);
   241   memcpy (addr, tmp, 16);
   242   return (1);
   242   return (1);
   243 }
   243 }
   244 
   244 
   384 }
   384 }
   385 
   385 
   386 bool Ipv6Address::IsMulticast () const
   386 bool Ipv6Address::IsMulticast () const
   387 {
   387 {
   388   if (m_address[0] == 0xff)
   388   if (m_address[0] == 0xff)
   389   {
   389     {
   390     return true;
   390       return true;
   391   }
   391     }
   392   return false;
   392   return false;
   393 }
   393 }
   394 
   394 
   395 Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const& prefix)
   395 Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const& prefix)
   396 {
   396 {
   402   memcpy (addr, m_address, 16);
   402   memcpy (addr, m_address, 16);
   403   ((Ipv6Prefix)prefix).GetBytes (pref);
   403   ((Ipv6Prefix)prefix).GetBytes (pref);
   404 
   404 
   405   /* a little bit ugly... */
   405   /* a little bit ugly... */
   406   for (i = 0 ; i < 16 ; i++)
   406   for (i = 0 ; i < 16 ; i++)
   407   {
   407     {
   408     addr[i] = addr[i] & pref[i];
   408       addr[i] = addr[i] & pref[i];
   409   }
   409     }
   410   ipv6.Set (addr);
   410   ipv6.Set (addr);
   411   return ipv6;
   411   return ipv6;
   412 }
   412 }
   413 
   413 
   414 bool Ipv6Address::IsSolicitedMulticast () const
   414 bool Ipv6Address::IsSolicitedMulticast () const
   419 
   419 
   420   if (buf[0] == 0xff && 
   420   if (buf[0] == 0xff && 
   421       buf[1] == 0x02 &&
   421       buf[1] == 0x02 &&
   422       buf[11] == 0x01 &&
   422       buf[11] == 0x01 &&
   423       buf[12] == 0xff)
   423       buf[12] == 0xff)
   424   {
   424     {
   425     return true;
   425       return true;
   426   }
   426     }
   427   return false;
   427   return false;
   428 }
   428 }
   429 
   429 
   430 bool Ipv6Address::IsAllNodesMulticast () const
   430 bool Ipv6Address::IsAllNodesMulticast () const
   431 {
   431 {
   531 
   531 
   532 bool Ipv6Address::IsLinkLocal () const
   532 bool Ipv6Address::IsLinkLocal () const
   533 {
   533 {
   534   Ipv6Address linkLocal ("fe80::0");
   534   Ipv6Address linkLocal ("fe80::0");
   535   if (!IsMulticast () && ((Ipv6Address*)this)->CombinePrefix (Ipv6Prefix (64)) == linkLocal)
   535   if (!IsMulticast () && ((Ipv6Address*)this)->CombinePrefix (Ipv6Prefix (64)) == linkLocal)
   536   {
   536     {
   537     return true;
   537       return true;
   538   }
   538     }
   539   return false;
   539   return false;
   540 }
   540 }
   541 
   541 
   542 bool Ipv6Address::IsEqual (const Ipv6Address& other) const
   542 bool Ipv6Address::IsEqual (const Ipv6Address& other) const
   543 {
   543 {
   544   if (!memcmp (m_address, other.m_address, 16))
   544   if (!memcmp (m_address, other.m_address, 16))
   545   {
   545     {
   546     return true;
   546       return true;
   547   }
   547     }
   548   return false;
   548   return false;
   549 }
   549 }
   550 
   550 
   551 std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
   551 std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
   552 {
   552 {
   591   mod = prefix % 8;
   591   mod = prefix % 8;
   592 
   592 
   593   memset (m_prefix, 0xff, nb);
   593   memset (m_prefix, 0xff, nb);
   594 
   594 
   595   if (mod)
   595   if (mod)
   596   {
   596     {
   597     m_prefix[nb] = 0xff << (8-mod);
   597       m_prefix[nb] = 0xff << (8-mod);
   598   }
   598     }
   599 
   599 
   600   if (nb < 16)
   600   if (nb < 16)
   601   {
   601     {
   602     nb++;
   602       nb++;
   603     for (i = nb; i < 16 ; i++)
   603       for (i = nb; i < 16 ; i++)
   604     {
   604         {
   605       m_prefix[i] = 0x00;
   605           m_prefix[i] = 0x00;
   606     }
   606         }
   607   }
   607     }
   608 }
   608 }
   609 
   609 
   610 Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix)
   610 Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix)
   611 {
   611 {
   612   memcpy (m_prefix, prefix.m_prefix, 16);
   612   memcpy (m_prefix, prefix.m_prefix, 16);
   631   a.GetBytes (addrA);
   631   a.GetBytes (addrA);
   632   b.GetBytes (addrB);
   632   b.GetBytes (addrB);
   633 
   633 
   634   /* a little bit ugly... */
   634   /* a little bit ugly... */
   635   for (i = 0 ; i < 16 ; i++)
   635   for (i = 0 ; i < 16 ; i++)
   636   {
   636     {
   637     if ((addrA[i] & m_prefix[i]) != (addrB[i] & m_prefix[i]))
   637       if ((addrA[i] & m_prefix[i]) != (addrB[i] & m_prefix[i]))
   638     {
   638         {
   639       return false;
   639           return false;
   640     }
   640         }
   641   }
   641     }
   642   return true;
   642   return true;
   643 }
   643 }
   644 
   644 
   645 void Ipv6Prefix::Print (std::ostream &os) const
   645 void Ipv6Prefix::Print (std::ostream &os) const
   646 {
   646 {
   689 {
   689 {
   690   uint8_t i = 0;
   690   uint8_t i = 0;
   691   uint8_t prefixLength = 0;
   691   uint8_t prefixLength = 0;
   692 
   692 
   693   for(i = 0 ; i < 16 ; i++)
   693   for(i = 0 ; i < 16 ; i++)
   694   {
   694     {
   695     uint8_t mask = m_prefix[i];
   695       uint8_t mask = m_prefix[i];
   696 
   696 
   697     while(mask != 0)
   697       while(mask != 0)
   698     {
   698         {
   699       mask = mask << 1;
   699           mask = mask << 1;
   700       prefixLength++;
   700           prefixLength++;
   701     }
   701         }
   702   }
   702     }
   703 
   703 
   704   return prefixLength;
   704   return prefixLength;
   705 }
   705 }
   706 
   706 
   707 bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
   707 bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
   708 {
   708 {
   709   if (!memcmp (m_prefix, other.m_prefix, 16))
   709   if (!memcmp (m_prefix, other.m_prefix, 16))
   710   {
   710     {
   711     return true;
   711       return true;
   712   }
   712     }
   713   return false;
   713   return false;
   714 }
   714 }
   715 
   715 
   716 std::ostream& operator << (std::ostream& os, Ipv6Prefix const& prefix)
   716 std::ostream& operator << (std::ostream& os, Ipv6Prefix const& prefix)
   717 {
   717 {