src/node/ipv6-address.cc
changeset 3852 9cf7ad0cac85
child 4311 abf229efd655
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/node/ipv6-address.cc	Fri Nov 07 11:36:15 2008 -0800
     1.3 @@ -0,0 +1,686 @@
     1.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
     1.5 +/*
     1.6 + * Copyright (c) 2007-2008 Louis Pasteur University
     1.7 + *
     1.8 + * This program is free software; you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License version 2 as
    1.10 + * published by the Free Software Foundation;
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program; if not, write to the Free Software
    1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.20 + *
    1.21 + * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
    1.22 + */
    1.23 +
    1.24 +#include <string.h>
    1.25 +
    1.26 +#include "ns3/log.h"
    1.27 +#include "ipv6-address.h"
    1.28 +#include "ns3/assert.h"
    1.29 +#include "mac48-address.h"
    1.30 +
    1.31 +#include <iomanip>
    1.32 +
    1.33 +NS_LOG_COMPONENT_DEFINE ("Ipv6Address");
    1.34 +
    1.35 +namespace ns3 {
    1.36 +
    1.37 +#ifdef __cplusplus
    1.38 +extern "C"
    1.39 +{
    1.40 +#endif
    1.41 +
    1.42 +  /**
    1.43 +   * \brief Get a hash key.
    1.44 +   * \param k the key
    1.45 +   * \param length the length of the key
    1.46 +   * \param level the previous hash, or an arbitrary value
    1.47 +   * \return hash
    1.48 +   * \note Adpated from Jens Jakobsen implementation (chillispot).
    1.49 +   */
    1.50 +  static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level)
    1.51 +  {
    1.52 +#define mix(a,b,c) \
    1.53 +    { \
    1.54 +      a -= b; a -= c; a ^= (c>>13); \
    1.55 +      b -= c; b -= a; b ^= (a<<8); \
    1.56 +      c -= a; c -= b; c ^= (b>>13); \
    1.57 +      a -= b; a -= c; a ^= (c>>12);  \
    1.58 +      b -= c; b -= a; b ^= (a<<16); \
    1.59 +      c -= a; c -= b; c ^= (b>>5); \
    1.60 +      a -= b; a -= c; a ^= (c>>3);  \
    1.61 +      b -= c; b -= a; b ^= (a<<10); \
    1.62 +      c -= a; c -= b; c ^= (b>>15); \
    1.63 +    }
    1.64 +
    1.65 +    typedef uint32_t  ub4;   /* unsigned 4-byte quantities */
    1.66 +    typedef unsigned  char ub1;   /* unsigned 1-byte quantities */
    1.67 +    uint32_t a,b,c,len;
    1.68 +
    1.69 +    /* Set up the internal state */
    1.70 +    len = length;
    1.71 +    a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
    1.72 +    c = level;           /* the previous hash value */
    1.73 +
    1.74 +    /*---------------------------------------- handle most of the key */
    1.75 +    while (len >= 12)
    1.76 +    {
    1.77 +      a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
    1.78 +      b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
    1.79 +      c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
    1.80 +      mix(a,b,c);
    1.81 +      k += 12; len -= 12;
    1.82 +    }
    1.83 +
    1.84 +    /*------------------------------------- handle the last 11 bytes */
    1.85 +    c += length;
    1.86 +    switch(len)              /* all the case statements fall through */
    1.87 +    {
    1.88 +      case 11: c+=((ub4)k[10]<<24);
    1.89 +      case 10: c+=((ub4)k[9]<<16);
    1.90 +      case 9 : c+=((ub4)k[8]<<8);
    1.91 +               /* the first byte of c is reserved for the length */
    1.92 +      case 8 : b+=((ub4)k[7]<<24);
    1.93 +      case 7 : b+=((ub4)k[6]<<16);
    1.94 +      case 6 : b+=((ub4)k[5]<<8);
    1.95 +      case 5 : b+=k[4];
    1.96 +      case 4 : a+=((ub4)k[3]<<24);
    1.97 +      case 3 : a+=((ub4)k[2]<<16);
    1.98 +      case 2 : a+=((ub4)k[1]<<8);
    1.99 +      case 1 : a+=k[0];
   1.100 +               /* case 0: nothing left to add */
   1.101 +    }
   1.102 +    mix(a,b,c);
   1.103 +    /*-------------------------------------------- report the result */
   1.104 +    return c;
   1.105 +  }
   1.106 +#ifdef __cplusplus
   1.107 +}
   1.108 +#endif
   1.109 +
   1.110 +/**
   1.111 + * \brief Convert an IPv6 C-string into a 128-bit representation.
   1.112 + * \return 1 if OK, 0 if failure (bad format, ...)
   1.113 + * \note This function is strongly inspired by inet_pton6() from Paul Vixie.
   1.114 + * \todo Handle IPv6 address with decimal value for last four bytes.
   1.115 + */
   1.116 +static int AsciiToIpv6Host (char const *address, uint8_t addr[16])
   1.117 +{
   1.118 +  static const char xdigits_l[] = "0123456789abcdef",
   1.119 +               xdigits_u[] = "0123456789ABCDEF";
   1.120 +  unsigned char tmp[16 /*NS_IN6ADDRSZ*/], *tp, *endp, *colonp;
   1.121 +  const char *xdigits, *curtok;
   1.122 +  int ch, seen_xdigits;
   1.123 +  unsigned int val;
   1.124 +
   1.125 +  memset((tp = tmp), '\0', 16 /* NS_IN6ADDRSZ*/);
   1.126 +  endp = tp + 16 /*NS_IN6ADDRSZ*/;
   1.127 +  colonp = NULL;
   1.128 +  /* Leading :: requires some special handling. */
   1.129 +  if (*address == ':')
   1.130 +    if (*++address != ':')
   1.131 +      return (0);
   1.132 +  curtok = address;
   1.133 +  seen_xdigits = 0;
   1.134 +  val = 0;
   1.135 +  while ((ch = *address++) != '\0')
   1.136 +  {
   1.137 +    const char *pch;
   1.138 +
   1.139 +    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
   1.140 +      pch = strchr((xdigits = xdigits_u), ch);
   1.141 +    if (pch != NULL)
   1.142 +    {
   1.143 +      val <<= 4;
   1.144 +      val |= (pch - xdigits);
   1.145 +      if (++seen_xdigits > 4)
   1.146 +        return (0);
   1.147 +      continue;
   1.148 +    }
   1.149 +    if (ch == ':')
   1.150 +    {
   1.151 +      curtok = address;
   1.152 +      if (!seen_xdigits)
   1.153 +      {
   1.154 +        if (colonp)
   1.155 +          return (0);
   1.156 +        colonp = tp;
   1.157 +        continue;
   1.158 +      }
   1.159 +      if (tp + 2 /*NS_INT16SZ*/ > endp)
   1.160 +        return (0);
   1.161 +      *tp++ = (unsigned char) (val >> 8) & 0xff;
   1.162 +      *tp++ = (unsigned char) val & 0xff;
   1.163 +      seen_xdigits = 0;
   1.164 +      val = 0;
   1.165 +      continue;
   1.166 +    }
   1.167 +
   1.168 +    /* TODO Handle address like 2001::xxx.xxx.xxx.xxxx */
   1.169 +#if 0
   1.170 +    if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) &&
   1.171 +        inet_pton4(curtok, tp) > 0)
   1.172 +    {
   1.173 +      tp += 4 /*NS_INADDRSZ*/;
   1.174 +      seen_xdigits = 0;
   1.175 +      break;/* '\0' was seen by inet_pton4(). */
   1.176 +    }
   1.177 +#endif
   1.178 +    return (0);
   1.179 +  }
   1.180 +  if (seen_xdigits)
   1.181 +  {
   1.182 +    if (tp + 2/* NS_INT16SZ*/ > endp)
   1.183 +      return (0);
   1.184 +    *tp++ = (unsigned char) (val >> 8) & 0xff;
   1.185 +    *tp++ = (unsigned char) val & 0xff;
   1.186 +  }
   1.187 +  if (colonp != NULL)
   1.188 +  {
   1.189 +    /*
   1.190 +     * Since some memmove()'s erroneously fail to handle
   1.191 +     * overlapping regions, we'll do the shift by hand.
   1.192 +     */
   1.193 +    const int n = tp - colonp;
   1.194 +    int i;
   1.195 +
   1.196 +    if (tp == endp)
   1.197 +      return (0);
   1.198 +    for (i = 1; i <= n; i++)
   1.199 +    {
   1.200 +      endp[- i] = colonp[n - i];
   1.201 +      colonp[n - i] = 0;
   1.202 +    }
   1.203 +    tp = endp;
   1.204 +  }
   1.205 +  if (tp != endp)
   1.206 +    return (0);
   1.207 +
   1.208 +  /* memcpy(dst, tmp, NS_IN6ADDRSZ);  */
   1.209 +  memcpy(addr, tmp, 16);
   1.210 +  return (1);
   1.211 +}
   1.212 +
   1.213 +Ipv6Address::Ipv6Address ()
   1.214 +{
   1.215 +  memset(m_address, 0x00, 16);
   1.216 +}
   1.217 +
   1.218 +Ipv6Address::Ipv6Address (Ipv6Address const& addr)
   1.219 +{
   1.220 +  memcpy(m_address, addr.m_address, 16);
   1.221 +}
   1.222 +
   1.223 +Ipv6Address::Ipv6Address (Ipv6Address const* addr)
   1.224 +{
   1.225 +  memcpy(m_address, addr->m_address, 16);
   1.226 +}
   1.227 +
   1.228 +Ipv6Address::Ipv6Address (char const* address)
   1.229 +{
   1.230 +  AsciiToIpv6Host (address, m_address);
   1.231 +}
   1.232 +
   1.233 +Ipv6Address::Ipv6Address (uint8_t address[16])
   1.234 +{
   1.235 +  /* 128 bit => 16 bytes */
   1.236 +  memcpy(m_address, address, 16);
   1.237 +}
   1.238 +
   1.239 +Ipv6Address::~Ipv6Address ()
   1.240 +{
   1.241 +  /* do nothing */
   1.242 +}
   1.243 +
   1.244 +void Ipv6Address::Set (char const* address)
   1.245 +{
   1.246 +  AsciiToIpv6Host (address, m_address);
   1.247 +}
   1.248 +
   1.249 +void Ipv6Address::Set (uint8_t address[16])
   1.250 +{
   1.251 +  /* 128 bit => 16 bytes */
   1.252 +  memcpy(m_address, address, 16);
   1.253 +}
   1.254 +
   1.255 +void Ipv6Address::Serialize (uint8_t buf[16]) const
   1.256 +{
   1.257 +  memcpy(buf, m_address, 16);
   1.258 +}
   1.259 +
   1.260 +Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16])
   1.261 +{
   1.262 +  Ipv6Address ipv6((uint8_t*)buf);
   1.263 +  return ipv6;
   1.264 +}
   1.265 +
   1.266 +Ipv6Address Ipv6Address::MakeAutoconfiguredAddress (Mac48Address addr, Ipv6Address prefix)
   1.267 +{
   1.268 +  Ipv6Address ret;
   1.269 +  uint8_t buf[16];
   1.270 +  uint8_t buf2[16];
   1.271 +
   1.272 +  addr.CopyTo(buf);
   1.273 +  prefix.GetBytes(buf2);
   1.274 +
   1.275 +  memcpy(buf2 + 8, buf, 3);
   1.276 +  buf2[11] = 0xff;
   1.277 +  buf2[12] = 0xfe;
   1.278 +  memcpy(buf2 + 13, buf + 3, 3);
   1.279 +  buf2[8] |= 0x02;
   1.280 +
   1.281 +  ret.Set(buf2);
   1.282 +  return ret;
   1.283 +}
   1.284 +
   1.285 +Ipv6Address Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address addr)
   1.286 +{
   1.287 +  Ipv6Address ret;
   1.288 +  uint8_t buf[16];
   1.289 +  uint8_t buf2[16];
   1.290 +
   1.291 +  addr.CopyTo(buf);
   1.292 +
   1.293 +  memset(buf2, 0x00, sizeof(buf2));
   1.294 +  buf2[0] = 0xfe;
   1.295 +  buf2[1] = 0x80;
   1.296 +  memcpy(buf2 + 8, buf, 3);
   1.297 +  buf2[11] = 0xff;
   1.298 +  buf2[12] = 0xfe;
   1.299 +  memcpy(buf2 + 13, buf + 3, 3);
   1.300 +  buf2[8] |= 0x02;
   1.301 +
   1.302 +  ret.Set(buf2);
   1.303 +  return ret;
   1.304 +}
   1.305 +
   1.306 +Ipv6Address Ipv6Address::MakeSolicitedAddress (Ipv6Address addr)
   1.307 +{
   1.308 +  uint8_t buf[16];
   1.309 +  uint8_t buf2[16];
   1.310 +  Ipv6Address ret;
   1.311 +
   1.312 +  addr.Serialize(buf2);
   1.313 +
   1.314 +  memset(buf, 0x00, sizeof(buf));
   1.315 +  buf[0] = 0xff;
   1.316 +  buf[1] = 0x02;
   1.317 +  buf[11] = 0x01;
   1.318 +  buf[12] = 0xff;
   1.319 +  buf[13] = buf2[13];
   1.320 +  buf[14] = buf2[14];
   1.321 +  buf[15] = buf2[15];
   1.322 +
   1.323 +  ret.Set(buf);
   1.324 +  return ret;
   1.325 +}
   1.326 +
   1.327 +void Ipv6Address::Print (std::ostream& os) const
   1.328 +{
   1.329 +  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[0]
   1.330 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[1] << ":"
   1.331 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[2] 
   1.332 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[3] << ":"
   1.333 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[4]
   1.334 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[5] << ":"
   1.335 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[6]
   1.336 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[7] << ":"
   1.337 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[8]
   1.338 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[9] << ":"
   1.339 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[10]
   1.340 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[11] << ":"
   1.341 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[12]
   1.342 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[13] << ":"
   1.343 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[14]
   1.344 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[15];
   1.345 +}
   1.346 +
   1.347 +bool Ipv6Address::IsLocalhost () const
   1.348 +{
   1.349 +  static Ipv6Address localhost("::1");
   1.350 +  return (*this == localhost);
   1.351 +}
   1.352 +
   1.353 +bool Ipv6Address::IsMulticast () const
   1.354 +{
   1.355 +  if(m_address[0] == 0xff)
   1.356 +  {
   1.357 +    return true;
   1.358 +  }
   1.359 +  return false;
   1.360 +}
   1.361 +
   1.362 +Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const & prefix)
   1.363 +{
   1.364 +  Ipv6Address ipv6;
   1.365 +  uint8_t addr[16];
   1.366 +  uint8_t pref[16];
   1.367 +  unsigned int i = 0;
   1.368 +
   1.369 +  memcpy(addr, m_address, 16);
   1.370 +  ((Ipv6Prefix)prefix).GetBytes(pref);
   1.371 +
   1.372 +  /* a little bit ugly... */
   1.373 +  for(i = 0 ; i < 16 ; i++)
   1.374 +  {
   1.375 +    addr[i] = addr[i] & pref[i];
   1.376 +  }
   1.377 +  ipv6.Set(addr);
   1.378 +  return ipv6;
   1.379 +}
   1.380 +
   1.381 +bool Ipv6Address::IsSolicitedMulticast () const
   1.382 +{
   1.383 +  uint8_t buf[16];
   1.384 +
   1.385 +  Serialize(buf);
   1.386 +
   1.387 +  if(buf[0] == 0xff && 
   1.388 +      buf[1] == 0x02 &&
   1.389 +      buf[11] == 0x01 &&
   1.390 +      buf[12] == 0xff)
   1.391 +  {
   1.392 +    return true;
   1.393 +  }
   1.394 +  return false;
   1.395 +}
   1.396 +
   1.397 +bool Ipv6Address::IsAllNodesMulticast () const
   1.398 +{
   1.399 +  static Ipv6Address allnodes("ff02::1");
   1.400 +  return (*this == allnodes);
   1.401 +}
   1.402 +
   1.403 +bool Ipv6Address::IsAllRoutersMulticast () const
   1.404 +{
   1.405 +  static Ipv6Address allrouters("ff02::2");
   1.406 +  return (*this == allrouters);
   1.407 +}
   1.408 +
   1.409 +bool Ipv6Address::IsAllHostsMulticast () const
   1.410 +{
   1.411 +  static Ipv6Address allhosts("ff02::3");
   1.412 +  return (*this == allhosts);
   1.413 +}
   1.414 +
   1.415 +bool Ipv6Address::IsAny () const
   1.416 +{
   1.417 +  static Ipv6Address any("::");
   1.418 +  return (*this == any);
   1.419 +}
   1.420 +
   1.421 +bool Ipv6Address::IsMatchingType (const Address& address)
   1.422 +{
   1.423 +  return address.CheckCompatible(GetType(), 16);
   1.424 +}
   1.425 +
   1.426 +Ipv6Address::operator Address () const
   1.427 +{
   1.428 +  return ConvertTo ();
   1.429 +}
   1.430 +
   1.431 +Address Ipv6Address::ConvertTo (void) const
   1.432 +{
   1.433 +  uint8_t buf[16];
   1.434 +  Serialize (buf);
   1.435 +  return Address(GetType(), buf, 16);
   1.436 +}
   1.437 +
   1.438 +Ipv6Address Ipv6Address::ConvertFrom (const Address &address)
   1.439 +{
   1.440 +  NS_ASSERT (address.CheckCompatible (GetType (), 16));
   1.441 +  uint8_t buf[16];
   1.442 +  address.CopyTo (buf);
   1.443 +  return Deserialize (buf);
   1.444 +}
   1.445 +
   1.446 +uint8_t Ipv6Address::GetType (void)
   1.447 +{
   1.448 +  static uint8_t type = Address::Register();
   1.449 +  return type;
   1.450 +}
   1.451 +
   1.452 +Ipv6Address Ipv6Address::GetZero ()
   1.453 +{
   1.454 +  Ipv6Address zero("::");
   1.455 +  return zero;
   1.456 +}
   1.457 +
   1.458 +Ipv6Address Ipv6Address::GetAny ()
   1.459 +{
   1.460 +  Ipv6Address any("::");
   1.461 +  return any;
   1.462 +}
   1.463 +
   1.464 +Ipv6Address Ipv6Address::GetAllNodesMulticast ()
   1.465 +{
   1.466 +  Ipv6Address nmc("ff02::1");
   1.467 +  return nmc;
   1.468 +}
   1.469 +
   1.470 +Ipv6Address Ipv6Address::GetAllRoutersMulticast ()
   1.471 +{
   1.472 +  Ipv6Address rmc("ff02::2");
   1.473 +  return rmc;
   1.474 +}
   1.475 +
   1.476 +Ipv6Address Ipv6Address::GetAllHostsMulticast ()
   1.477 +{
   1.478 +  Ipv6Address hmc("ff02::3");
   1.479 +  return hmc;
   1.480 +}
   1.481 +
   1.482 +Ipv6Address Ipv6Address::GetLoopback ()
   1.483 +{
   1.484 +  static Ipv6Address loopback("::1");
   1.485 +  return loopback;
   1.486 +}
   1.487 +
   1.488 +void Ipv6Address::GetBytes (uint8_t buf[16]) const
   1.489 +{
   1.490 +  memcpy(buf, m_address, 16);
   1.491 +}
   1.492 +
   1.493 +bool Ipv6Address::IsLinkLocal () const
   1.494 +{
   1.495 +  Ipv6Address linkLocal("fe80::0");
   1.496 +  if(!IsMulticast() && ((Ipv6Address*)this)->CombinePrefix(Ipv6Prefix(64))==linkLocal)
   1.497 +  {
   1.498 +    return true;
   1.499 +  }
   1.500 +  return false;
   1.501 +}
   1.502 +
   1.503 +bool Ipv6Address::IsEqual (const Ipv6Address& other) const
   1.504 +{
   1.505 +  if(!memcmp(m_address, other.m_address, 16))
   1.506 +  {
   1.507 +    return true;
   1.508 +  }
   1.509 +  return false;
   1.510 +}
   1.511 +
   1.512 +std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
   1.513 +{
   1.514 +  address.Print(os);
   1.515 +  return os;
   1.516 +}
   1.517 +
   1.518 +std::istream& operator >> (std::istream& is, Ipv6Address& address)
   1.519 +{
   1.520 +  std::string str;
   1.521 +  is >> str;
   1.522 +  address = Ipv6Address (str.c_str ());
   1.523 +  return is;
   1.524 +}
   1.525 +
   1.526 +Ipv6Prefix::Ipv6Prefix ()
   1.527 +{
   1.528 +  memset(m_prefix, 0x00, 16);
   1.529 +}
   1.530 +
   1.531 +Ipv6Prefix::Ipv6Prefix (char const* prefix)
   1.532 +{
   1.533 +  AsciiToIpv6Host(prefix, m_prefix);
   1.534 +}
   1.535 +
   1.536 +Ipv6Prefix::Ipv6Prefix (uint8_t prefix[16])
   1.537 +{
   1.538 +  memcpy(m_prefix, prefix, 16);
   1.539 +}
   1.540 +
   1.541 +Ipv6Prefix::Ipv6Prefix (uint8_t prefix)
   1.542 +{
   1.543 +  unsigned int nb=0;
   1.544 +  unsigned int mod=0;
   1.545 +  unsigned int i=0;
   1.546 +
   1.547 +  memset(m_prefix, 0x00, 16);
   1.548 +
   1.549 +  NS_ASSERT(prefix <= 128);
   1.550 +
   1.551 +  nb = prefix / 8;
   1.552 +  mod = prefix % 8;
   1.553 +
   1.554 +  memset(m_prefix, 0xff, nb);
   1.555 +
   1.556 +  if(mod)
   1.557 +  {
   1.558 +    m_prefix[nb] = 0xff << (8-mod);
   1.559 +  }
   1.560 +
   1.561 +  if(nb < 16)
   1.562 +  {
   1.563 +    nb++;
   1.564 +    for(i = nb; i < 16 ; i++)
   1.565 +    {
   1.566 +      m_prefix[i] = 0x00;
   1.567 +    }
   1.568 +  }
   1.569 +}
   1.570 +
   1.571 +Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix)
   1.572 +{
   1.573 +  memcpy(m_prefix, prefix.m_prefix, 16);
   1.574 +}
   1.575 +
   1.576 +Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const* prefix)
   1.577 +{
   1.578 +  memcpy(m_prefix, prefix->m_prefix, 16);
   1.579 +}
   1.580 +
   1.581 +Ipv6Prefix::~Ipv6Prefix ()
   1.582 +{
   1.583 +  /* do nothing */
   1.584 +}
   1.585 +
   1.586 +bool Ipv6Prefix::IsMatch (Ipv6Address a, Ipv6Address b) const
   1.587 +{
   1.588 +  uint8_t addrA[16];
   1.589 +  uint8_t addrB[16];
   1.590 +  unsigned int i = 0;
   1.591 +
   1.592 +  a.GetBytes(addrA);
   1.593 +  b.GetBytes(addrB);
   1.594 +
   1.595 +  /* a little bit ugly... */
   1.596 +  for(i = 0 ; i < 16 ; i++)
   1.597 +  {
   1.598 +    if((addrA[i] & m_prefix[i]) !=	(addrB[i] & m_prefix[i]))
   1.599 +    {
   1.600 +      return false;
   1.601 +    }
   1.602 +  }
   1.603 +  return true;
   1.604 +}
   1.605 +
   1.606 +void Ipv6Prefix::Print (std::ostream &os) const
   1.607 +{
   1.608 +  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[0]
   1.609 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[1] << ":"
   1.610 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[2]
   1.611 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[3] << ":"
   1.612 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[4]
   1.613 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[5] << ":"
   1.614 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[6]
   1.615 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[7] << ":"
   1.616 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[8]
   1.617 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[9] << ":"
   1.618 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[10]
   1.619 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[11] << ":"
   1.620 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[12]
   1.621 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[13] << ":"
   1.622 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[14]
   1.623 +    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[15];
   1.624 +}
   1.625 +
   1.626 +Ipv6Prefix Ipv6Prefix::GetLoopback ()
   1.627 +{
   1.628 +  Ipv6Prefix prefix((uint8_t)128);
   1.629 +  return prefix;
   1.630 +}
   1.631 +
   1.632 +Ipv6Prefix Ipv6Prefix::GetZero ()
   1.633 +{
   1.634 +  Ipv6Prefix prefix((uint8_t)0);
   1.635 +  return prefix;
   1.636 +}
   1.637 +
   1.638 +void Ipv6Prefix::GetBytes (uint8_t buf[16]) const
   1.639 +{
   1.640 +  memcpy(buf, m_prefix, 16);
   1.641 +}
   1.642 +
   1.643 +bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
   1.644 +{
   1.645 +  if(!memcmp(m_prefix, other.m_prefix, 16))
   1.646 +  {
   1.647 +    return true;
   1.648 +  }
   1.649 +  return false;
   1.650 +}
   1.651 +
   1.652 +std::ostream& operator<< (std::ostream& os, Ipv6Prefix const& prefix)
   1.653 +{
   1.654 +  prefix.Print (os);
   1.655 +  return os;
   1.656 +}
   1.657 +
   1.658 +std::istream& operator >> (std::istream& is, Ipv6Prefix& prefix)
   1.659 +{
   1.660 +  std::string str;
   1.661 +  is >> str;
   1.662 +  prefix = Ipv6Prefix (str.c_str ());
   1.663 +  return is;
   1.664 +}
   1.665 +
   1.666 +bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b)
   1.667 +{
   1.668 +  return a.IsEqual (b);
   1.669 +}
   1.670 +
   1.671 +bool operator != (Ipv6Prefix const &a, Ipv6Prefix const &b)
   1.672 +{
   1.673 +  return !a.IsEqual (b);
   1.674 +}
   1.675 +
   1.676 +size_t Ipv6AddressHash::operator() (Ipv6Address const &x) const
   1.677 +{
   1.678 +  uint8_t buf[16];
   1.679 +
   1.680 +  x.GetBytes(buf);
   1.681 +
   1.682 +  return lookuphash(buf, sizeof(buf), 0);
   1.683 +}
   1.684 +
   1.685 +ATTRIBUTE_HELPER_CPP (Ipv6Address);
   1.686 +ATTRIBUTE_HELPER_CPP (Ipv6Prefix);
   1.687 +
   1.688 +} /* namespace ns3 */
   1.689 +