A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv6-address.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2008 Louis Pasteur University
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  */
20 
21 #include <iomanip>
22 #include <memory.h>
23 
24 #include "ns3/log.h"
25 #include "ns3/assert.h"
26 
27 #include "mac48-address.h"
28 #include "ipv6-address.h"
29 
30 NS_LOG_COMPONENT_DEFINE ("Ipv6Address");
31 
32 namespace ns3 {
33 
34 #ifdef __cplusplus
35 extern "C"
36 { /* } */
37 #endif
38 
47 static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level)
48 {
49 #define mix(a, b, c) \
50  ({ \
51  (a) -= (b); (a) -= (c); (a) ^= ((c) >> 13); \
52  (b) -= (c); (b) -= (a); (b) ^= ((a) << 8); \
53  (c) -= (a); (c) -= (b); (c) ^= ((b) >> 13); \
54  (a) -= (b); (a) -= (c); (a) ^= ((c) >> 12); \
55  (b) -= (c); (b) -= (a); (b) ^= ((a) << 16); \
56  (c) -= (a); (c) -= (b); (c) ^= ((b) >> 5); \
57  (a) -= (b); (a) -= (c); (a) ^= ((c) >> 3); \
58  (b) -= (c); (b) -= (a); (b) ^= ((a) << 10); \
59  (c) -= (a); (c) -= (b); (c) ^= ((b) >> 15); \
60  })
61 
62  typedef uint32_t ub4; /* unsigned 4-byte quantities */
63  typedef unsigned char ub1; /* unsigned 1-byte quantities */
64  uint32_t a = 0;
65  uint32_t b = 0;
66  uint32_t c = 0;
67  uint32_t len = 0;
68 
69  /* Set up the internal state */
70  len = length;
71  a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
72  c = level; /* the previous hash value */
73 
74  /* handle most of the key */
75  while (len >= 12)
76  {
77  a += (k[0] + ((ub4)k[1] << 8) + ((ub4)k[2] << 16) + ((ub4)k[3] << 24));
78  b += (k[4] + ((ub4)k[5] << 8) + ((ub4)k[6] << 16) + ((ub4)k[7] << 24));
79  c += (k[8] + ((ub4)k[9] << 8) + ((ub4)k[10] << 16) + ((ub4)k[11] << 24));
80  mix (a, b, c);
81  k += 12;
82  len -= 12;
83  }
84 
85  /* handle the last 11 bytes */
86  c += length;
87  switch (len) /* all the case statements fall through */
88  {
89  case 11: c += ((ub4)k[10] << 24);
90  case 10: c += ((ub4)k[9] << 16);
91  case 9: c += ((ub4)k[8] << 8); /* the first byte of c is reserved for the length */
92  case 8: b += ((ub4)k[7] << 24);
93  case 7: b += ((ub4)k[6] << 16);
94  case 6: b += ((ub4)k[5] << 8);
95  case 5: b += k[4];
96  case 4: a += ((ub4)k[3] << 24);
97  case 3: a += ((ub4)k[2] << 16);
98  case 2: a += ((ub4)k[1] << 8);
99  case 1: a += k[0];
100  /* case 0: nothing left to add */
101  }
102  mix (a, b, c);
103 
104 #undef mix
105 
106  /* report the result */
107  return c;
108 }
109 
110 #ifdef __cplusplus
111 }
112 #endif
113 
120 static bool AsciiToIpv6Host (const char *address, uint8_t addr[16])
121 {
122  static const char xdigits_l[] = "0123456789abcdef";
123  static const char xdigits_u[] = "0123456789ABCDEF";
124  unsigned char tmp[16];
125  unsigned char* tp = tmp;
126  unsigned char* endp = 0;
127  unsigned char* colonp = 0;
128  const char* xdigits = 0;
129 #if 0
130  const char* curtok = 0;
131 #endif
132  int ch = 0;
133  int seen_xdigits = 0;
134  unsigned int val = 0;
135 
136  memset (tp, 0x00, 16);
137  endp = tp + 16;
138 
139  /* Leading :: requires some special handling. */
140  if (*address == ':')
141  {
142  if (*++address != ':')
143  {
144  return (0);
145  }
146  }
147 #if 0
148  curtok = address;
149 #endif
150  while ((ch = *address++) != '\0')
151  {
152  const char *pch = 0;
153 
154  if ((pch = strchr ((xdigits = xdigits_l), ch)) == 0)
155  {
156  pch = strchr ((xdigits = xdigits_u), ch);
157  }
158 
159  if (pch != 0)
160  {
161  val <<= 4;
162  val |= (pch - xdigits);
163 
164  if (++seen_xdigits > 4)
165  {
166  return (0);
167  }
168  continue;
169  }
170  if (ch == ':')
171  {
172 #if 0
173  curtok = address;
174 #endif
175 
176  if (!seen_xdigits)
177  {
178  if (colonp)
179  return (0);
180  colonp = tp;
181  continue;
182  }
183 
184  if (tp + 2 > endp)
185  {
186  return (0);
187  }
188 
189  *tp++ = (unsigned char)(val >> 8) & 0xff;
190  *tp++ = (unsigned char) val & 0xff;
191  seen_xdigits = 0;
192  val = 0;
193  continue;
194  }
195 
196  /* TODO Handle IPv4 mapped address (2001::192.168.0.1) */
197 #if 0
198  if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) &&
199  inet_pton4 (curtok, tp) > 0)
200  {
201  tp += 4 /*NS_INADDRSZ*/;
202  seen_xdigits = 0;
203  break; /* '\0' was seen by inet_pton4(). */
204  }
205 #endif
206  return (0);
207  }
208 
209  if (seen_xdigits)
210  {
211  if (tp + 2 > endp)
212  {
213  return (0);
214  }
215  *tp++ = (unsigned char)(val >> 8) & 0xff;
216  *tp++ = (unsigned char) val & 0xff;
217  }
218 
219  if (colonp != 0)
220  {
221  /*
222  * Since some memmove ()'s erroneously fail to handle
223  * overlapping regions, we'll do the shift by hand.
224  */
225  const int n = tp - colonp;
226  int i = 0;
227 
228  if (tp == endp)
229  {
230  return (0);
231  }
232 
233  for (i = 1; i <= n; i++)
234  {
235  endp[-i] = colonp[n - i];
236  colonp[n - i] = 0;
237  }
238 
239  tp = endp;
240  }
241 
242  if (tp != endp)
243  {
244  return (0);
245  }
246 
247  memcpy (addr, tmp, 16);
248  return (1);
249 }
250 
252 {
253  memset (m_address, 0x00, 16);
254 }
255 
257 {
258  memcpy (m_address, addr.m_address, 16);
259 }
260 
262 {
263  memcpy (m_address, addr->m_address, 16);
264 }
265 
266 Ipv6Address::Ipv6Address (char const* address)
267 {
268  AsciiToIpv6Host (address, m_address);
269 }
270 
271 Ipv6Address::Ipv6Address (uint8_t address[16])
272 {
273  /* 128 bit => 16 bytes */
274  memcpy (m_address, address, 16);
275 }
276 
278 {
279  /* do nothing */
280 }
281 
282 void Ipv6Address::Set (char const* address)
283 {
284  AsciiToIpv6Host (address, m_address);
285 }
286 
287 void Ipv6Address::Set (uint8_t address[16])
288 {
289  /* 128 bit => 16 bytes */
290  memcpy (m_address, address, 16);
291 }
292 
293 void Ipv6Address::Serialize (uint8_t buf[16]) const
294 {
295  memcpy (buf, m_address, 16);
296 }
297 
298 Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16])
299 {
300  Ipv6Address ipv6 ((uint8_t*)buf);
301  return ipv6;
302 }
303 
305 {
306  uint8_t buf[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307  0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
308  addr.Serialize (&buf[12]);
309  return (Ipv6Address (buf));
310 }
311 
313 {
314  uint8_t buf[16];
315  Ipv4Address v4Addr;
316 
317  Serialize (buf);
318  v4Addr = Ipv4Address::Deserialize (&buf[12]);
319  return (v4Addr);
320 }
321 
323 {
324  Ipv6Address ret;
325  uint8_t buf[16];
326  uint8_t buf2[16];
327 
328  addr.CopyTo (buf);
329  prefix.GetBytes (buf2);
330 
331  memcpy (buf2 + 8, buf, 3);
332  buf2[11] = 0xff;
333  buf2[12] = 0xfe;
334  memcpy (buf2 + 13, buf + 3, 3);
335  buf2[8] |= 0x02;
336 
337  ret.Set (buf2);
338  return ret;
339 }
340 
342 {
343  Ipv6Address ret;
344  uint8_t buf[16];
345  uint8_t buf2[16];
346 
347  addr.CopyTo (buf);
348 
349  memset (buf2, 0x00, sizeof (buf2));
350  buf2[0] = 0xfe;
351  buf2[1] = 0x80;
352  memcpy (buf2 + 8, buf, 3);
353  buf2[11] = 0xff;
354  buf2[12] = 0xfe;
355  memcpy (buf2 + 13, buf + 3, 3);
356  buf2[8] |= 0x02;
357 
358  ret.Set (buf2);
359  return ret;
360 }
361 
363 {
364  uint8_t buf[16];
365  uint8_t buf2[16];
366  Ipv6Address ret;
367 
368  addr.Serialize (buf2);
369 
370  memset (buf, 0x00, sizeof (buf));
371  buf[0] = 0xff;
372  buf[1] = 0x02;
373  buf[11] = 0x01;
374  buf[12] = 0xff;
375  buf[13] = buf2[13];
376  buf[14] = buf2[14];
377  buf[15] = buf2[15];
378 
379  ret.Set (buf);
380  return ret;
381 }
382 
383 void Ipv6Address::Print (std::ostream& os) const
384 {
385  os << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[0]
386  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[1] << ":"
387  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[2]
388  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[3] << ":"
389  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[4]
390  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[5] << ":"
391  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[6]
392  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[7] << ":"
393  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[8]
394  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[9] << ":"
395  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[10]
396  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[11] << ":"
397  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[12]
398  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[13] << ":"
399  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[14]
400  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[15]
401  << std::dec << std::setfill (' ');
402 }
403 
405 {
406  static Ipv6Address localhost ("::1");
407  return (*this == localhost);
408 }
409 
411 {
412  if (m_address[0] == 0xff)
413  {
414  return true;
415  }
416  return false;
417 }
418 
420 {
421  if (m_address[0] == 0xff && m_address[1] == 0x02)
422  {
423  return true;
424  }
425  return false;
426 }
427 
429 {
430  uint8_t v4MappedPrefix[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431  0x00, 0x00, 0xff, 0xff };
432  if (memcmp(m_address, v4MappedPrefix, sizeof(v4MappedPrefix)) == 0)
433  {
434  return (true);
435  }
436  return (false);
437 }
438 
440 {
441  Ipv6Address ipv6;
442  uint8_t addr[16];
443  uint8_t pref[16];
444  unsigned int i = 0;
445 
446  memcpy (addr, m_address, 16);
447  ((Ipv6Prefix)prefix).GetBytes (pref);
448 
449  /* a little bit ugly... */
450  for (i = 0; i < 16; i++)
451  {
452  addr[i] = addr[i] & pref[i];
453  }
454  ipv6.Set (addr);
455  return ipv6;
456 }
457 
459 {
460  uint8_t buf[16];
461 
462  Serialize (buf);
463 
464  if (buf[0] == 0xff &&
465  buf[1] == 0x02 &&
466  buf[11] == 0x01 &&
467  buf[12] == 0xff)
468  {
469  return true;
470  }
471  return false;
472 }
473 
475 {
476  static Ipv6Address allnodes ("ff02::1");
477  return (*this == allnodes);
478 }
479 
481 {
482  static Ipv6Address allrouters ("ff02::2");
483  return (*this == allrouters);
484 }
485 
487 {
488  static Ipv6Address allhosts ("ff02::3");
489  return (*this == allhosts);
490 }
491 
492 bool Ipv6Address::IsAny () const
493 {
494  static Ipv6Address any ("::");
495  return (*this == any);
496 }
497 
499 {
500  return address.CheckCompatible (GetType (), 16);
501 }
502 
503 Ipv6Address::operator Address () const
504 {
505  return ConvertTo ();
506 }
507 
509 {
510  uint8_t buf[16];
511  Serialize (buf);
512  return Address (GetType (), buf, 16);
513 }
514 
516 {
517  NS_ASSERT (address.CheckCompatible (GetType (), 16));
518  uint8_t buf[16];
519  address.CopyTo (buf);
520  return Deserialize (buf);
521 }
522 
523 uint8_t Ipv6Address::GetType (void)
524 {
525  static uint8_t type = Address::Register ();
526  return type;
527 }
528 
530 {
531  static Ipv6Address nmc ("ff02::1");
532  return nmc;
533 }
534 
536 {
537  static Ipv6Address rmc ("ff02::2");
538  return rmc;
539 }
540 
542 {
543  static Ipv6Address hmc ("ff02::3");
544  return hmc;
545 }
546 
548 {
549  static Ipv6Address loopback ("::1");
550  return loopback;
551 }
552 
554 {
555  static Ipv6Address zero ("::");
556  return zero;
557 }
558 
560 {
561  static Ipv6Address any ("::");
562  return any;
563 }
564 
566 {
567  static Ipv6Address ones ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
568  return ones;
569 }
570 
571 void Ipv6Address::GetBytes (uint8_t buf[16]) const
572 {
573  memcpy (buf, m_address, 16);
574 }
575 
577 {
578  Ipv6Address linkLocal ("fe80::0");
579  if (!IsMulticast () && ((Ipv6Address*)this)->CombinePrefix (Ipv6Prefix (64)) == linkLocal)
580  {
581  return true;
582  }
583  return false;
584 }
585 
586 bool Ipv6Address::IsEqual (const Ipv6Address& other) const
587 {
588  if (!memcmp (m_address, other.m_address, 16))
589  {
590  return true;
591  }
592  return false;
593 }
594 
595 std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
596 {
597  address.Print (os);
598  return os;
599 }
600 
601 std::istream& operator >> (std::istream& is, Ipv6Address& address)
602 {
603  std::string str;
604  is >> str;
605  address = Ipv6Address (str.c_str ());
606  return is;
607 }
608 
610 {
611  memset (m_prefix, 0x00, 16);
612 }
613 
614 Ipv6Prefix::Ipv6Prefix (char const* prefix)
615 {
616  AsciiToIpv6Host (prefix, m_prefix);
617 }
618 
619 Ipv6Prefix::Ipv6Prefix (uint8_t prefix[16])
620 {
621  memcpy (m_prefix, prefix, 16);
622 }
623 
624 Ipv6Prefix::Ipv6Prefix (uint8_t prefix)
625 {
626  unsigned int nb=0;
627  unsigned int mod=0;
628  unsigned int i=0;
629 
630  memset (m_prefix, 0x00, 16);
631 
632  NS_ASSERT (prefix <= 128);
633 
634  nb = prefix / 8;
635  mod = prefix % 8;
636 
637  // protect memset with 'nb > 0' check to suppress
638  // __warn_memset_zero_len compiler errors in some gcc>4.5.x
639  if (nb > 0)
640  {
641  memset (m_prefix, 0xff, nb);
642  }
643  if (mod)
644  {
645  m_prefix[nb] = 0xff << (8-mod);
646  }
647 
648  if (nb < 16)
649  {
650  nb++;
651  for (i = nb; i < 16; i++)
652  {
653  m_prefix[i] = 0x00;
654  }
655  }
656 }
657 
659 {
660  memcpy (m_prefix, prefix.m_prefix, 16);
661 }
662 
664 {
665  memcpy (m_prefix, prefix->m_prefix, 16);
666 }
667 
669 {
670  /* do nothing */
671 }
672 
674 {
675  uint8_t addrA[16];
676  uint8_t addrB[16];
677  unsigned int i = 0;
678 
679  a.GetBytes (addrA);
680  b.GetBytes (addrB);
681 
682  /* a little bit ugly... */
683  for (i = 0; i < 16; i++)
684  {
685  if ((addrA[i] & m_prefix[i]) != (addrB[i] & m_prefix[i]))
686  {
687  return false;
688  }
689  }
690  return true;
691 }
692 
693 void Ipv6Prefix::Print (std::ostream &os) const
694 {
695  os << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[0]
696  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[1] << ":"
697  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[2]
698  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[3] << ":"
699  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[4]
700  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[5] << ":"
701  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[6]
702  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[7] << ":"
703  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[8]
704  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[9] << ":"
705  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[10]
706  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[11] << ":"
707  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[12]
708  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[13] << ":"
709  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[14]
710  << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[15];
711 }
712 
714 {
715  static Ipv6Prefix prefix ((uint8_t)128);
716  return prefix;
717 }
718 
720 {
721  static Ipv6Prefix ones ((uint8_t)128);
722  return ones;
723 }
724 
726 {
727  static Ipv6Prefix prefix ((uint8_t)0);
728  return prefix;
729 }
730 
731 void Ipv6Prefix::GetBytes (uint8_t buf[16]) const
732 {
733  memcpy (buf, m_prefix, 16);
734 }
735 
737 {
738  uint8_t i = 0;
739  uint8_t prefixLength = 0;
740 
741  for(i = 0; i < 16; i++)
742  {
743  uint8_t mask = m_prefix[i];
744 
745  while(mask != 0)
746  {
747  mask = mask << 1;
748  prefixLength++;
749  }
750  }
751 
752  return prefixLength;
753 }
754 
755 bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
756 {
757  if (!memcmp (m_prefix, other.m_prefix, 16))
758  {
759  return true;
760  }
761  return false;
762 }
763 
764 std::ostream& operator << (std::ostream& os, Ipv6Prefix const& prefix)
765 {
766  prefix.Print (os);
767  return os;
768 }
769 
770 std::istream& operator >> (std::istream& is, Ipv6Prefix& prefix)
771 {
772  std::string str;
773  is >> str;
774  prefix = Ipv6Prefix (str.c_str ());
775  return is;
776 }
777 
778 bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b)
779 {
780  return a.IsEqual (b);
781 }
782 
783 bool operator != (Ipv6Prefix const &a, Ipv6Prefix const &b)
784 {
785  return !a.IsEqual (b);
786 }
787 
789 {
790  uint8_t buf[16];
791 
792  x.GetBytes (buf);
793 
794  return lookuphash (buf, sizeof (buf), 0);
795 }
796 
799 
800 } /* namespace ns3 */
801