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 +