src/node/ipv6-address.cc
author vincent@clarinet.u-strasbg.fr
Fri Nov 07 11:36:15 2008 -0800 (2008-11-07)
changeset 3852 9cf7ad0cac85
child 4311 abf229efd655
permissions -rw-r--r--
Initial IPv6 capability
vincent@3852
     1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
vincent@3852
     2
/*
vincent@3852
     3
 * Copyright (c) 2007-2008 Louis Pasteur University
vincent@3852
     4
 *
vincent@3852
     5
 * This program is free software; you can redistribute it and/or modify
vincent@3852
     6
 * it under the terms of the GNU General Public License version 2 as
vincent@3852
     7
 * published by the Free Software Foundation;
vincent@3852
     8
 *
vincent@3852
     9
 * This program is distributed in the hope that it will be useful,
vincent@3852
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
vincent@3852
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
vincent@3852
    12
 * GNU General Public License for more details.
vincent@3852
    13
 *
vincent@3852
    14
 * You should have received a copy of the GNU General Public License
vincent@3852
    15
 * along with this program; if not, write to the Free Software
vincent@3852
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
vincent@3852
    17
 *
vincent@3852
    18
 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
vincent@3852
    19
 */
vincent@3852
    20
vincent@3852
    21
#include <string.h>
vincent@3852
    22
vincent@3852
    23
#include "ns3/log.h"
vincent@3852
    24
#include "ipv6-address.h"
vincent@3852
    25
#include "ns3/assert.h"
vincent@3852
    26
#include "mac48-address.h"
vincent@3852
    27
vincent@3852
    28
#include <iomanip>
vincent@3852
    29
vincent@3852
    30
NS_LOG_COMPONENT_DEFINE ("Ipv6Address");
vincent@3852
    31
vincent@3852
    32
namespace ns3 {
vincent@3852
    33
vincent@3852
    34
#ifdef __cplusplus
vincent@3852
    35
extern "C"
vincent@3852
    36
{
vincent@3852
    37
#endif
vincent@3852
    38
vincent@3852
    39
  /**
vincent@3852
    40
   * \brief Get a hash key.
vincent@3852
    41
   * \param k the key
vincent@3852
    42
   * \param length the length of the key
vincent@3852
    43
   * \param level the previous hash, or an arbitrary value
vincent@3852
    44
   * \return hash
vincent@3852
    45
   * \note Adpated from Jens Jakobsen implementation (chillispot).
vincent@3852
    46
   */
vincent@3852
    47
  static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level)
vincent@3852
    48
  {
vincent@3852
    49
#define mix(a,b,c) \
vincent@3852
    50
    { \
vincent@3852
    51
      a -= b; a -= c; a ^= (c>>13); \
vincent@3852
    52
      b -= c; b -= a; b ^= (a<<8); \
vincent@3852
    53
      c -= a; c -= b; c ^= (b>>13); \
vincent@3852
    54
      a -= b; a -= c; a ^= (c>>12);  \
vincent@3852
    55
      b -= c; b -= a; b ^= (a<<16); \
vincent@3852
    56
      c -= a; c -= b; c ^= (b>>5); \
vincent@3852
    57
      a -= b; a -= c; a ^= (c>>3);  \
vincent@3852
    58
      b -= c; b -= a; b ^= (a<<10); \
vincent@3852
    59
      c -= a; c -= b; c ^= (b>>15); \
vincent@3852
    60
    }
vincent@3852
    61
vincent@3852
    62
    typedef uint32_t  ub4;   /* unsigned 4-byte quantities */
vincent@3852
    63
    typedef unsigned  char ub1;   /* unsigned 1-byte quantities */
vincent@3852
    64
    uint32_t a,b,c,len;
vincent@3852
    65
vincent@3852
    66
    /* Set up the internal state */
vincent@3852
    67
    len = length;
vincent@3852
    68
    a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
vincent@3852
    69
    c = level;           /* the previous hash value */
vincent@3852
    70
vincent@3852
    71
    /*---------------------------------------- handle most of the key */
vincent@3852
    72
    while (len >= 12)
vincent@3852
    73
    {
vincent@3852
    74
      a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
vincent@3852
    75
      b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
vincent@3852
    76
      c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
vincent@3852
    77
      mix(a,b,c);
vincent@3852
    78
      k += 12; len -= 12;
vincent@3852
    79
    }
vincent@3852
    80
vincent@3852
    81
    /*------------------------------------- handle the last 11 bytes */
vincent@3852
    82
    c += length;
vincent@3852
    83
    switch(len)              /* all the case statements fall through */
vincent@3852
    84
    {
vincent@3852
    85
      case 11: c+=((ub4)k[10]<<24);
vincent@3852
    86
      case 10: c+=((ub4)k[9]<<16);
vincent@3852
    87
      case 9 : c+=((ub4)k[8]<<8);
vincent@3852
    88
               /* the first byte of c is reserved for the length */
vincent@3852
    89
      case 8 : b+=((ub4)k[7]<<24);
vincent@3852
    90
      case 7 : b+=((ub4)k[6]<<16);
vincent@3852
    91
      case 6 : b+=((ub4)k[5]<<8);
vincent@3852
    92
      case 5 : b+=k[4];
vincent@3852
    93
      case 4 : a+=((ub4)k[3]<<24);
vincent@3852
    94
      case 3 : a+=((ub4)k[2]<<16);
vincent@3852
    95
      case 2 : a+=((ub4)k[1]<<8);
vincent@3852
    96
      case 1 : a+=k[0];
vincent@3852
    97
               /* case 0: nothing left to add */
vincent@3852
    98
    }
vincent@3852
    99
    mix(a,b,c);
vincent@3852
   100
    /*-------------------------------------------- report the result */
vincent@3852
   101
    return c;
vincent@3852
   102
  }
vincent@3852
   103
#ifdef __cplusplus
vincent@3852
   104
}
vincent@3852
   105
#endif
vincent@3852
   106
vincent@3852
   107
/**
vincent@3852
   108
 * \brief Convert an IPv6 C-string into a 128-bit representation.
vincent@3852
   109
 * \return 1 if OK, 0 if failure (bad format, ...)
vincent@3852
   110
 * \note This function is strongly inspired by inet_pton6() from Paul Vixie.
vincent@3852
   111
 * \todo Handle IPv6 address with decimal value for last four bytes.
vincent@3852
   112
 */
vincent@3852
   113
static int AsciiToIpv6Host (char const *address, uint8_t addr[16])
vincent@3852
   114
{
vincent@3852
   115
  static const char xdigits_l[] = "0123456789abcdef",
vincent@3852
   116
               xdigits_u[] = "0123456789ABCDEF";
vincent@3852
   117
  unsigned char tmp[16 /*NS_IN6ADDRSZ*/], *tp, *endp, *colonp;
vincent@3852
   118
  const char *xdigits, *curtok;
vincent@3852
   119
  int ch, seen_xdigits;
vincent@3852
   120
  unsigned int val;
vincent@3852
   121
vincent@3852
   122
  memset((tp = tmp), '\0', 16 /* NS_IN6ADDRSZ*/);
vincent@3852
   123
  endp = tp + 16 /*NS_IN6ADDRSZ*/;
vincent@3852
   124
  colonp = NULL;
vincent@3852
   125
  /* Leading :: requires some special handling. */
vincent@3852
   126
  if (*address == ':')
vincent@3852
   127
    if (*++address != ':')
vincent@3852
   128
      return (0);
vincent@3852
   129
  curtok = address;
vincent@3852
   130
  seen_xdigits = 0;
vincent@3852
   131
  val = 0;
vincent@3852
   132
  while ((ch = *address++) != '\0')
vincent@3852
   133
  {
vincent@3852
   134
    const char *pch;
vincent@3852
   135
vincent@3852
   136
    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
vincent@3852
   137
      pch = strchr((xdigits = xdigits_u), ch);
vincent@3852
   138
    if (pch != NULL)
vincent@3852
   139
    {
vincent@3852
   140
      val <<= 4;
vincent@3852
   141
      val |= (pch - xdigits);
vincent@3852
   142
      if (++seen_xdigits > 4)
vincent@3852
   143
        return (0);
vincent@3852
   144
      continue;
vincent@3852
   145
    }
vincent@3852
   146
    if (ch == ':')
vincent@3852
   147
    {
vincent@3852
   148
      curtok = address;
vincent@3852
   149
      if (!seen_xdigits)
vincent@3852
   150
      {
vincent@3852
   151
        if (colonp)
vincent@3852
   152
          return (0);
vincent@3852
   153
        colonp = tp;
vincent@3852
   154
        continue;
vincent@3852
   155
      }
vincent@3852
   156
      if (tp + 2 /*NS_INT16SZ*/ > endp)
vincent@3852
   157
        return (0);
vincent@3852
   158
      *tp++ = (unsigned char) (val >> 8) & 0xff;
vincent@3852
   159
      *tp++ = (unsigned char) val & 0xff;
vincent@3852
   160
      seen_xdigits = 0;
vincent@3852
   161
      val = 0;
vincent@3852
   162
      continue;
vincent@3852
   163
    }
vincent@3852
   164
vincent@3852
   165
    /* TODO Handle address like 2001::xxx.xxx.xxx.xxxx */
vincent@3852
   166
#if 0
vincent@3852
   167
    if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) &&
vincent@3852
   168
        inet_pton4(curtok, tp) > 0)
vincent@3852
   169
    {
vincent@3852
   170
      tp += 4 /*NS_INADDRSZ*/;
vincent@3852
   171
      seen_xdigits = 0;
vincent@3852
   172
      break;/* '\0' was seen by inet_pton4(). */
vincent@3852
   173
    }
vincent@3852
   174
#endif
vincent@3852
   175
    return (0);
vincent@3852
   176
  }
vincent@3852
   177
  if (seen_xdigits)
vincent@3852
   178
  {
vincent@3852
   179
    if (tp + 2/* NS_INT16SZ*/ > endp)
vincent@3852
   180
      return (0);
vincent@3852
   181
    *tp++ = (unsigned char) (val >> 8) & 0xff;
vincent@3852
   182
    *tp++ = (unsigned char) val & 0xff;
vincent@3852
   183
  }
vincent@3852
   184
  if (colonp != NULL)
vincent@3852
   185
  {
vincent@3852
   186
    /*
vincent@3852
   187
     * Since some memmove()'s erroneously fail to handle
vincent@3852
   188
     * overlapping regions, we'll do the shift by hand.
vincent@3852
   189
     */
vincent@3852
   190
    const int n = tp - colonp;
vincent@3852
   191
    int i;
vincent@3852
   192
vincent@3852
   193
    if (tp == endp)
vincent@3852
   194
      return (0);
vincent@3852
   195
    for (i = 1; i <= n; i++)
vincent@3852
   196
    {
vincent@3852
   197
      endp[- i] = colonp[n - i];
vincent@3852
   198
      colonp[n - i] = 0;
vincent@3852
   199
    }
vincent@3852
   200
    tp = endp;
vincent@3852
   201
  }
vincent@3852
   202
  if (tp != endp)
vincent@3852
   203
    return (0);
vincent@3852
   204
vincent@3852
   205
  /* memcpy(dst, tmp, NS_IN6ADDRSZ);  */
vincent@3852
   206
  memcpy(addr, tmp, 16);
vincent@3852
   207
  return (1);
vincent@3852
   208
}
vincent@3852
   209
vincent@3852
   210
Ipv6Address::Ipv6Address ()
vincent@3852
   211
{
vincent@3852
   212
  memset(m_address, 0x00, 16);
vincent@3852
   213
}
vincent@3852
   214
vincent@3852
   215
Ipv6Address::Ipv6Address (Ipv6Address const& addr)
vincent@3852
   216
{
vincent@3852
   217
  memcpy(m_address, addr.m_address, 16);
vincent@3852
   218
}
vincent@3852
   219
vincent@3852
   220
Ipv6Address::Ipv6Address (Ipv6Address const* addr)
vincent@3852
   221
{
vincent@3852
   222
  memcpy(m_address, addr->m_address, 16);
vincent@3852
   223
}
vincent@3852
   224
vincent@3852
   225
Ipv6Address::Ipv6Address (char const* address)
vincent@3852
   226
{
vincent@3852
   227
  AsciiToIpv6Host (address, m_address);
vincent@3852
   228
}
vincent@3852
   229
vincent@3852
   230
Ipv6Address::Ipv6Address (uint8_t address[16])
vincent@3852
   231
{
vincent@3852
   232
  /* 128 bit => 16 bytes */
vincent@3852
   233
  memcpy(m_address, address, 16);
vincent@3852
   234
}
vincent@3852
   235
vincent@3852
   236
Ipv6Address::~Ipv6Address ()
vincent@3852
   237
{
vincent@3852
   238
  /* do nothing */
vincent@3852
   239
}
vincent@3852
   240
vincent@3852
   241
void Ipv6Address::Set (char const* address)
vincent@3852
   242
{
vincent@3852
   243
  AsciiToIpv6Host (address, m_address);
vincent@3852
   244
}
vincent@3852
   245
vincent@3852
   246
void Ipv6Address::Set (uint8_t address[16])
vincent@3852
   247
{
vincent@3852
   248
  /* 128 bit => 16 bytes */
vincent@3852
   249
  memcpy(m_address, address, 16);
vincent@3852
   250
}
vincent@3852
   251
vincent@3852
   252
void Ipv6Address::Serialize (uint8_t buf[16]) const
vincent@3852
   253
{
vincent@3852
   254
  memcpy(buf, m_address, 16);
vincent@3852
   255
}
vincent@3852
   256
vincent@3852
   257
Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16])
vincent@3852
   258
{
vincent@3852
   259
  Ipv6Address ipv6((uint8_t*)buf);
vincent@3852
   260
  return ipv6;
vincent@3852
   261
}
vincent@3852
   262
vincent@3852
   263
Ipv6Address Ipv6Address::MakeAutoconfiguredAddress (Mac48Address addr, Ipv6Address prefix)
vincent@3852
   264
{
vincent@3852
   265
  Ipv6Address ret;
vincent@3852
   266
  uint8_t buf[16];
vincent@3852
   267
  uint8_t buf2[16];
vincent@3852
   268
vincent@3852
   269
  addr.CopyTo(buf);
vincent@3852
   270
  prefix.GetBytes(buf2);
vincent@3852
   271
vincent@3852
   272
  memcpy(buf2 + 8, buf, 3);
vincent@3852
   273
  buf2[11] = 0xff;
vincent@3852
   274
  buf2[12] = 0xfe;
vincent@3852
   275
  memcpy(buf2 + 13, buf + 3, 3);
vincent@3852
   276
  buf2[8] |= 0x02;
vincent@3852
   277
vincent@3852
   278
  ret.Set(buf2);
vincent@3852
   279
  return ret;
vincent@3852
   280
}
vincent@3852
   281
vincent@3852
   282
Ipv6Address Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address addr)
vincent@3852
   283
{
vincent@3852
   284
  Ipv6Address ret;
vincent@3852
   285
  uint8_t buf[16];
vincent@3852
   286
  uint8_t buf2[16];
vincent@3852
   287
vincent@3852
   288
  addr.CopyTo(buf);
vincent@3852
   289
vincent@3852
   290
  memset(buf2, 0x00, sizeof(buf2));
vincent@3852
   291
  buf2[0] = 0xfe;
vincent@3852
   292
  buf2[1] = 0x80;
vincent@3852
   293
  memcpy(buf2 + 8, buf, 3);
vincent@3852
   294
  buf2[11] = 0xff;
vincent@3852
   295
  buf2[12] = 0xfe;
vincent@3852
   296
  memcpy(buf2 + 13, buf + 3, 3);
vincent@3852
   297
  buf2[8] |= 0x02;
vincent@3852
   298
vincent@3852
   299
  ret.Set(buf2);
vincent@3852
   300
  return ret;
vincent@3852
   301
}
vincent@3852
   302
vincent@3852
   303
Ipv6Address Ipv6Address::MakeSolicitedAddress (Ipv6Address addr)
vincent@3852
   304
{
vincent@3852
   305
  uint8_t buf[16];
vincent@3852
   306
  uint8_t buf2[16];
vincent@3852
   307
  Ipv6Address ret;
vincent@3852
   308
vincent@3852
   309
  addr.Serialize(buf2);
vincent@3852
   310
vincent@3852
   311
  memset(buf, 0x00, sizeof(buf));
vincent@3852
   312
  buf[0] = 0xff;
vincent@3852
   313
  buf[1] = 0x02;
vincent@3852
   314
  buf[11] = 0x01;
vincent@3852
   315
  buf[12] = 0xff;
vincent@3852
   316
  buf[13] = buf2[13];
vincent@3852
   317
  buf[14] = buf2[14];
vincent@3852
   318
  buf[15] = buf2[15];
vincent@3852
   319
vincent@3852
   320
  ret.Set(buf);
vincent@3852
   321
  return ret;
vincent@3852
   322
}
vincent@3852
   323
vincent@3852
   324
void Ipv6Address::Print (std::ostream& os) const
vincent@3852
   325
{
vincent@3852
   326
  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[0]
vincent@3852
   327
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[1] << ":"
vincent@3852
   328
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[2] 
vincent@3852
   329
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[3] << ":"
vincent@3852
   330
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[4]
vincent@3852
   331
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[5] << ":"
vincent@3852
   332
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[6]
vincent@3852
   333
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[7] << ":"
vincent@3852
   334
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[8]
vincent@3852
   335
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[9] << ":"
vincent@3852
   336
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[10]
vincent@3852
   337
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[11] << ":"
vincent@3852
   338
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[12]
vincent@3852
   339
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[13] << ":"
vincent@3852
   340
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[14]
vincent@3852
   341
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[15];
vincent@3852
   342
}
vincent@3852
   343
vincent@3852
   344
bool Ipv6Address::IsLocalhost () const
vincent@3852
   345
{
vincent@3852
   346
  static Ipv6Address localhost("::1");
vincent@3852
   347
  return (*this == localhost);
vincent@3852
   348
}
vincent@3852
   349
vincent@3852
   350
bool Ipv6Address::IsMulticast () const
vincent@3852
   351
{
vincent@3852
   352
  if(m_address[0] == 0xff)
vincent@3852
   353
  {
vincent@3852
   354
    return true;
vincent@3852
   355
  }
vincent@3852
   356
  return false;
vincent@3852
   357
}
vincent@3852
   358
vincent@3852
   359
Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const & prefix)
vincent@3852
   360
{
vincent@3852
   361
  Ipv6Address ipv6;
vincent@3852
   362
  uint8_t addr[16];
vincent@3852
   363
  uint8_t pref[16];
vincent@3852
   364
  unsigned int i = 0;
vincent@3852
   365
vincent@3852
   366
  memcpy(addr, m_address, 16);
vincent@3852
   367
  ((Ipv6Prefix)prefix).GetBytes(pref);
vincent@3852
   368
vincent@3852
   369
  /* a little bit ugly... */
vincent@3852
   370
  for(i = 0 ; i < 16 ; i++)
vincent@3852
   371
  {
vincent@3852
   372
    addr[i] = addr[i] & pref[i];
vincent@3852
   373
  }
vincent@3852
   374
  ipv6.Set(addr);
vincent@3852
   375
  return ipv6;
vincent@3852
   376
}
vincent@3852
   377
vincent@3852
   378
bool Ipv6Address::IsSolicitedMulticast () const
vincent@3852
   379
{
vincent@3852
   380
  uint8_t buf[16];
vincent@3852
   381
vincent@3852
   382
  Serialize(buf);
vincent@3852
   383
vincent@3852
   384
  if(buf[0] == 0xff && 
vincent@3852
   385
      buf[1] == 0x02 &&
vincent@3852
   386
      buf[11] == 0x01 &&
vincent@3852
   387
      buf[12] == 0xff)
vincent@3852
   388
  {
vincent@3852
   389
    return true;
vincent@3852
   390
  }
vincent@3852
   391
  return false;
vincent@3852
   392
}
vincent@3852
   393
vincent@3852
   394
bool Ipv6Address::IsAllNodesMulticast () const
vincent@3852
   395
{
vincent@3852
   396
  static Ipv6Address allnodes("ff02::1");
vincent@3852
   397
  return (*this == allnodes);
vincent@3852
   398
}
vincent@3852
   399
vincent@3852
   400
bool Ipv6Address::IsAllRoutersMulticast () const
vincent@3852
   401
{
vincent@3852
   402
  static Ipv6Address allrouters("ff02::2");
vincent@3852
   403
  return (*this == allrouters);
vincent@3852
   404
}
vincent@3852
   405
vincent@3852
   406
bool Ipv6Address::IsAllHostsMulticast () const
vincent@3852
   407
{
vincent@3852
   408
  static Ipv6Address allhosts("ff02::3");
vincent@3852
   409
  return (*this == allhosts);
vincent@3852
   410
}
vincent@3852
   411
vincent@3852
   412
bool Ipv6Address::IsAny () const
vincent@3852
   413
{
vincent@3852
   414
  static Ipv6Address any("::");
vincent@3852
   415
  return (*this == any);
vincent@3852
   416
}
vincent@3852
   417
vincent@3852
   418
bool Ipv6Address::IsMatchingType (const Address& address)
vincent@3852
   419
{
vincent@3852
   420
  return address.CheckCompatible(GetType(), 16);
vincent@3852
   421
}
vincent@3852
   422
vincent@3852
   423
Ipv6Address::operator Address () const
vincent@3852
   424
{
vincent@3852
   425
  return ConvertTo ();
vincent@3852
   426
}
vincent@3852
   427
vincent@3852
   428
Address Ipv6Address::ConvertTo (void) const
vincent@3852
   429
{
vincent@3852
   430
  uint8_t buf[16];
vincent@3852
   431
  Serialize (buf);
vincent@3852
   432
  return Address(GetType(), buf, 16);
vincent@3852
   433
}
vincent@3852
   434
vincent@3852
   435
Ipv6Address Ipv6Address::ConvertFrom (const Address &address)
vincent@3852
   436
{
vincent@3852
   437
  NS_ASSERT (address.CheckCompatible (GetType (), 16));
vincent@3852
   438
  uint8_t buf[16];
vincent@3852
   439
  address.CopyTo (buf);
vincent@3852
   440
  return Deserialize (buf);
vincent@3852
   441
}
vincent@3852
   442
vincent@3852
   443
uint8_t Ipv6Address::GetType (void)
vincent@3852
   444
{
vincent@3852
   445
  static uint8_t type = Address::Register();
vincent@3852
   446
  return type;
vincent@3852
   447
}
vincent@3852
   448
vincent@3852
   449
Ipv6Address Ipv6Address::GetZero ()
vincent@3852
   450
{
vincent@3852
   451
  Ipv6Address zero("::");
vincent@3852
   452
  return zero;
vincent@3852
   453
}
vincent@3852
   454
vincent@3852
   455
Ipv6Address Ipv6Address::GetAny ()
vincent@3852
   456
{
vincent@3852
   457
  Ipv6Address any("::");
vincent@3852
   458
  return any;
vincent@3852
   459
}
vincent@3852
   460
vincent@3852
   461
Ipv6Address Ipv6Address::GetAllNodesMulticast ()
vincent@3852
   462
{
vincent@3852
   463
  Ipv6Address nmc("ff02::1");
vincent@3852
   464
  return nmc;
vincent@3852
   465
}
vincent@3852
   466
vincent@3852
   467
Ipv6Address Ipv6Address::GetAllRoutersMulticast ()
vincent@3852
   468
{
vincent@3852
   469
  Ipv6Address rmc("ff02::2");
vincent@3852
   470
  return rmc;
vincent@3852
   471
}
vincent@3852
   472
vincent@3852
   473
Ipv6Address Ipv6Address::GetAllHostsMulticast ()
vincent@3852
   474
{
vincent@3852
   475
  Ipv6Address hmc("ff02::3");
vincent@3852
   476
  return hmc;
vincent@3852
   477
}
vincent@3852
   478
vincent@3852
   479
Ipv6Address Ipv6Address::GetLoopback ()
vincent@3852
   480
{
vincent@3852
   481
  static Ipv6Address loopback("::1");
vincent@3852
   482
  return loopback;
vincent@3852
   483
}
vincent@3852
   484
vincent@3852
   485
void Ipv6Address::GetBytes (uint8_t buf[16]) const
vincent@3852
   486
{
vincent@3852
   487
  memcpy(buf, m_address, 16);
vincent@3852
   488
}
vincent@3852
   489
vincent@3852
   490
bool Ipv6Address::IsLinkLocal () const
vincent@3852
   491
{
vincent@3852
   492
  Ipv6Address linkLocal("fe80::0");
vincent@3852
   493
  if(!IsMulticast() && ((Ipv6Address*)this)->CombinePrefix(Ipv6Prefix(64))==linkLocal)
vincent@3852
   494
  {
vincent@3852
   495
    return true;
vincent@3852
   496
  }
vincent@3852
   497
  return false;
vincent@3852
   498
}
vincent@3852
   499
vincent@3852
   500
bool Ipv6Address::IsEqual (const Ipv6Address& other) const
vincent@3852
   501
{
vincent@3852
   502
  if(!memcmp(m_address, other.m_address, 16))
vincent@3852
   503
  {
vincent@3852
   504
    return true;
vincent@3852
   505
  }
vincent@3852
   506
  return false;
vincent@3852
   507
}
vincent@3852
   508
vincent@3852
   509
std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
vincent@3852
   510
{
vincent@3852
   511
  address.Print(os);
vincent@3852
   512
  return os;
vincent@3852
   513
}
vincent@3852
   514
vincent@3852
   515
std::istream& operator >> (std::istream& is, Ipv6Address& address)
vincent@3852
   516
{
vincent@3852
   517
  std::string str;
vincent@3852
   518
  is >> str;
vincent@3852
   519
  address = Ipv6Address (str.c_str ());
vincent@3852
   520
  return is;
vincent@3852
   521
}
vincent@3852
   522
vincent@3852
   523
Ipv6Prefix::Ipv6Prefix ()
vincent@3852
   524
{
vincent@3852
   525
  memset(m_prefix, 0x00, 16);
vincent@3852
   526
}
vincent@3852
   527
vincent@3852
   528
Ipv6Prefix::Ipv6Prefix (char const* prefix)
vincent@3852
   529
{
vincent@3852
   530
  AsciiToIpv6Host(prefix, m_prefix);
vincent@3852
   531
}
vincent@3852
   532
vincent@3852
   533
Ipv6Prefix::Ipv6Prefix (uint8_t prefix[16])
vincent@3852
   534
{
vincent@3852
   535
  memcpy(m_prefix, prefix, 16);
vincent@3852
   536
}
vincent@3852
   537
vincent@3852
   538
Ipv6Prefix::Ipv6Prefix (uint8_t prefix)
vincent@3852
   539
{
vincent@3852
   540
  unsigned int nb=0;
vincent@3852
   541
  unsigned int mod=0;
vincent@3852
   542
  unsigned int i=0;
vincent@3852
   543
vincent@3852
   544
  memset(m_prefix, 0x00, 16);
vincent@3852
   545
vincent@3852
   546
  NS_ASSERT(prefix <= 128);
vincent@3852
   547
vincent@3852
   548
  nb = prefix / 8;
vincent@3852
   549
  mod = prefix % 8;
vincent@3852
   550
vincent@3852
   551
  memset(m_prefix, 0xff, nb);
vincent@3852
   552
vincent@3852
   553
  if(mod)
vincent@3852
   554
  {
vincent@3852
   555
    m_prefix[nb] = 0xff << (8-mod);
vincent@3852
   556
  }
vincent@3852
   557
vincent@3852
   558
  if(nb < 16)
vincent@3852
   559
  {
vincent@3852
   560
    nb++;
vincent@3852
   561
    for(i = nb; i < 16 ; i++)
vincent@3852
   562
    {
vincent@3852
   563
      m_prefix[i] = 0x00;
vincent@3852
   564
    }
vincent@3852
   565
  }
vincent@3852
   566
}
vincent@3852
   567
vincent@3852
   568
Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix)
vincent@3852
   569
{
vincent@3852
   570
  memcpy(m_prefix, prefix.m_prefix, 16);
vincent@3852
   571
}
vincent@3852
   572
vincent@3852
   573
Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const* prefix)
vincent@3852
   574
{
vincent@3852
   575
  memcpy(m_prefix, prefix->m_prefix, 16);
vincent@3852
   576
}
vincent@3852
   577
vincent@3852
   578
Ipv6Prefix::~Ipv6Prefix ()
vincent@3852
   579
{
vincent@3852
   580
  /* do nothing */
vincent@3852
   581
}
vincent@3852
   582
vincent@3852
   583
bool Ipv6Prefix::IsMatch (Ipv6Address a, Ipv6Address b) const
vincent@3852
   584
{
vincent@3852
   585
  uint8_t addrA[16];
vincent@3852
   586
  uint8_t addrB[16];
vincent@3852
   587
  unsigned int i = 0;
vincent@3852
   588
vincent@3852
   589
  a.GetBytes(addrA);
vincent@3852
   590
  b.GetBytes(addrB);
vincent@3852
   591
vincent@3852
   592
  /* a little bit ugly... */
vincent@3852
   593
  for(i = 0 ; i < 16 ; i++)
vincent@3852
   594
  {
vincent@3852
   595
    if((addrA[i] & m_prefix[i]) !=	(addrB[i] & m_prefix[i]))
vincent@3852
   596
    {
vincent@3852
   597
      return false;
vincent@3852
   598
    }
vincent@3852
   599
  }
vincent@3852
   600
  return true;
vincent@3852
   601
}
vincent@3852
   602
vincent@3852
   603
void Ipv6Prefix::Print (std::ostream &os) const
vincent@3852
   604
{
vincent@3852
   605
  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[0]
vincent@3852
   606
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[1] << ":"
vincent@3852
   607
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[2]
vincent@3852
   608
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[3] << ":"
vincent@3852
   609
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[4]
vincent@3852
   610
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[5] << ":"
vincent@3852
   611
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[6]
vincent@3852
   612
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[7] << ":"
vincent@3852
   613
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[8]
vincent@3852
   614
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[9] << ":"
vincent@3852
   615
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[10]
vincent@3852
   616
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[11] << ":"
vincent@3852
   617
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[12]
vincent@3852
   618
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[13] << ":"
vincent@3852
   619
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[14]
vincent@3852
   620
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[15];
vincent@3852
   621
}
vincent@3852
   622
vincent@3852
   623
Ipv6Prefix Ipv6Prefix::GetLoopback ()
vincent@3852
   624
{
vincent@3852
   625
  Ipv6Prefix prefix((uint8_t)128);
vincent@3852
   626
  return prefix;
vincent@3852
   627
}
vincent@3852
   628
vincent@3852
   629
Ipv6Prefix Ipv6Prefix::GetZero ()
vincent@3852
   630
{
vincent@3852
   631
  Ipv6Prefix prefix((uint8_t)0);
vincent@3852
   632
  return prefix;
vincent@3852
   633
}
vincent@3852
   634
vincent@3852
   635
void Ipv6Prefix::GetBytes (uint8_t buf[16]) const
vincent@3852
   636
{
vincent@3852
   637
  memcpy(buf, m_prefix, 16);
vincent@3852
   638
}
vincent@3852
   639
vincent@3852
   640
bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
vincent@3852
   641
{
vincent@3852
   642
  if(!memcmp(m_prefix, other.m_prefix, 16))
vincent@3852
   643
  {
vincent@3852
   644
    return true;
vincent@3852
   645
  }
vincent@3852
   646
  return false;
vincent@3852
   647
}
vincent@3852
   648
vincent@3852
   649
std::ostream& operator<< (std::ostream& os, Ipv6Prefix const& prefix)
vincent@3852
   650
{
vincent@3852
   651
  prefix.Print (os);
vincent@3852
   652
  return os;
vincent@3852
   653
}
vincent@3852
   654
vincent@3852
   655
std::istream& operator >> (std::istream& is, Ipv6Prefix& prefix)
vincent@3852
   656
{
vincent@3852
   657
  std::string str;
vincent@3852
   658
  is >> str;
vincent@3852
   659
  prefix = Ipv6Prefix (str.c_str ());
vincent@3852
   660
  return is;
vincent@3852
   661
}
vincent@3852
   662
vincent@3852
   663
bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b)
vincent@3852
   664
{
vincent@3852
   665
  return a.IsEqual (b);
vincent@3852
   666
}
vincent@3852
   667
vincent@3852
   668
bool operator != (Ipv6Prefix const &a, Ipv6Prefix const &b)
vincent@3852
   669
{
vincent@3852
   670
  return !a.IsEqual (b);
vincent@3852
   671
}
vincent@3852
   672
vincent@3852
   673
size_t Ipv6AddressHash::operator() (Ipv6Address const &x) const
vincent@3852
   674
{
vincent@3852
   675
  uint8_t buf[16];
vincent@3852
   676
vincent@3852
   677
  x.GetBytes(buf);
vincent@3852
   678
vincent@3852
   679
  return lookuphash(buf, sizeof(buf), 0);
vincent@3852
   680
}
vincent@3852
   681
vincent@3852
   682
ATTRIBUTE_HELPER_CPP (Ipv6Address);
vincent@3852
   683
ATTRIBUTE_HELPER_CPP (Ipv6Prefix);
vincent@3852
   684
vincent@3852
   685
} /* namespace ns3 */
vincent@3852
   686