libutil++  1.9.3
 All Classes Functions Variables
IPAddress.cpp
1 /*
2 ** libutil++
3 ** $Id: IPAddress.cpp 1875 2017-03-24 17:28:04Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: IPAddress.cpp 1875 2017-03-24 17:28:04Z sella $";
10 
11 #include "IPAddress.h"
12 #include "AddressException.h"
13 #include "../util/CommonMacro.h"
14 
15 #include <unistd.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <assert.h>
19 #include <net/if.h>
20 #include <arpa/inet.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 
24 #include <limits>
25 #include <string>
26 
27 #define HASH_ALGO_INT1
28 
29 union __sockaddr_union {
30  struct sockaddr_storage *ss;
31  struct sockaddr *sa;
32  struct sockaddr_in *sa_in;
33  struct sockaddr_in6 *sa_in6;
34 };
35 
36 using namespace sella::net;
37 
38 IPAddress::IPAddress(const std::string &text, int family, uint8_t cidr) throw (AddressException) :
39  family(family),
40  addr(),
41  scache(),
42  hcache(0)
43 {
44  char buffer[INET6_ADDRSTRLEN];
45 
46  switch (family) {
47  case IPv4Family:
48  case IPv4Required:
49  if (this->parse(this->family, this->addr.v4, text) == false) {
50  THROW(AddressException, "unable to parse address: '%s' does not represent a valid IPv4 address", text.c_str());
51  }
52  break;
53 
54  case IPv4Preferred:
55  if (this->parse(this->family, this->addr.v4, this->addr.v6, text) == false) {
56  THROW(AddressException, "unable to parse address: '%s' does not represent a valid IPv4 or IPv6 address", text.c_str());
57  }
58  break;
59 
60  case IPv6Family:
61  case IPv6Required:
62  if (this->parse(this->family, this->addr.v6, text) == false) {
63  THROW(AddressException, "unable to parse address: '%s' does not represent a valid IPv6 address", text.c_str());
64  }
65  break;
66 
67  case IPv6Preferred:
68  if (this->parse(this->family, this->addr.v6, this->addr.v4, text) == false) {
69  THROW(AddressException, "unable to parse address: '%s' does not represent a valid IPv4 or IPv6 address", text.c_str());
70  }
71  break;
72 
73  default:
74  THROW(AddressException, "unable to parse address: unknown family supplied for address '%s'", text.c_str());
75  }
76 
77  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
78  THROW(AddressException, "unable to parse address '%s'", text.c_str());
79  }
80 
81  if (cidr != 255) {
82  applyCIDR(cidr);
83  }
84 }
85 
86 IPAddress::IPAddress(int family) throw (AddressException) : family(family), hcache(0) {
87  char buffer[INET6_ADDRSTRLEN];
88 
89  switch (family) {
90  case IPv4Family:
91  case IPv4Preferred:
92  case IPv4Required:
93  if (this->parse(this->family, this->addr.v4, "0.0.0.0") == false) {
94  THROW(AddressException, "unable to parse address: '%s' does not represent a valid IPv4 address", "0.0.0.0");
95  }
96  break;
97 
98  case IPv6Family:
99  case IPv6Preferred:
100  case IPv6Required:
101  if (this->parse(this->family, this->addr.v6, "::") == false) {
102  THROW(AddressException, "unable to parse address: '%s' does not represent a valid IPv6 address", "::");
103  }
104  break;
105 
106  default:
107  THROW(AddressException, "unable to parse address: unknown family supplied for default address");
108  }
109 
110  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
111  THROW(AddressException, "unable to parse default address");
112  }
113 }
114 
115 IPAddress::IPAddress(const struct sockaddr_storage *ss, uint8_t cidr) throw (AddressException) : hcache(0) {
116  char buffer[INET6_ADDRSTRLEN];
117  union __sockaddr_union u;
118 
119  if (ss == NULL) {
120  THROW(AddressException, "passed sockaddr_storage is null");
121  }
122 
123  u.ss = (struct sockaddr_storage*) ss;
124  this->family = u.sa->sa_family;
125 
126  if (this->family == AF_INET) {
127  this->addr.v4 = u.sa_in->sin_addr;
128  } else if (this->family == AF_INET6) {
129  this->addr.v6 = u.sa_in6->sin6_addr;
130  } else {
131  THROW(AddressException, "unknown family '%d'", this->family);
132  }
133 
134  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
135  THROW(AddressException, "unable to convert sockaddr");
136  }
137 
138  if (cidr != 255) {
139  applyCIDR(cidr);
140  }
141 }
142 
143 IPAddress::IPAddress(const struct sockaddr *sa, uint8_t cidr) throw (AddressException) : hcache(0) {
144  char buffer[INET6_ADDRSTRLEN];
145  union __sockaddr_union u;
146 
147  if (sa == NULL) {
148  THROW(AddressException, "passed sockaddr is null");
149  }
150 
151  u.sa = (struct sockaddr*) sa;
152  this->family = sa->sa_family;
153 
154  if (this->family == AF_INET) {
155  this->addr.v4 = u.sa_in->sin_addr;
156  } else if (this->family == AF_INET6) {
157  this->addr.v6 = u.sa_in6->sin6_addr;
158  } else {
159  THROW(AddressException, "unknown family '%d'", this->family);
160  }
161 
162  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
163  THROW(AddressException, "unable to convert sockaddr");
164  }
165 
166  if (cidr != 255) {
167  applyCIDR(cidr);
168  }
169 }
170 
171 IPAddress::IPAddress(const struct in_addr *in, uint8_t cidr) throw (AddressException) : hcache(0) {
172  char buffer[INET6_ADDRSTRLEN];
173 
174  if (in == NULL) {
175  THROW(AddressException, "passed in_addr is null");
176  }
177 
178  this->family = AF_INET;
179  this->addr.v4 = *in;
180 
181  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
182  THROW(AddressException, "unable to convert in_addr");
183  }
184 
185  if (cidr != 255) {
186  applyCIDR(cidr);
187  }
188 }
189 
190 IPAddress::IPAddress(const struct in6_addr *in6, uint8_t cidr) throw (AddressException) {
191  char buffer[INET6_ADDRSTRLEN];
192 
193  if (in6 == NULL) {
194  THROW(AddressException, "passed in6_addr is null");
195  }
196 
197  this->family = AF_INET6;
198  this->addr.v6 = *in6;
199 
200  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
201  THROW(AddressException, "unable to convert in_addr");
202  }
203 
204  if (cidr != 255) {
205  applyCIDR(cidr);
206  }
207 }
208 
209 IPAddress::IPAddress(uint32_t address, uint8_t cidr) throw (AddressException) : hcache(0) {
210  this->family = AF_INET;
211  this->addr.v4.s_addr = htonl(address);
212 
213  if (cidr != 255) {
214  applyCIDR(cidr);
215  }
216 }
217 
218 IPAddress::IPAddress(unsigned char address[16], uint8_t cidr) throw (AddressException) : hcache(0) {
219  this->family = AF_INET6;
220  memcpy(&(this->addr.v6), address, sizeof(addr)); /* May need to htonl() */
221 
222  if (cidr != 255) {
223  applyCIDR(cidr);
224  }
225 }
226 
227 IPAddress::IPAddress(const IPAddress &other) throw () :
228  family(other.family),
229  addr(other.addr),
230  scache(other.scache),
231  hcache(other.hcache)
232 { }
233 
234 IPAddress::IPAddress(const IPAddress &&other) throw () :
235  family(other.family),
236  addr(other.addr),
237  scache(std::move(other.scache)),
238  hcache(other.hcache)
239 { }
240 
241 IPAddress::~IPAddress() throw () {
242  family = 0;
243 }
244 
245 IPAddress & IPAddress::operator=(const IPAddress &other) throw () {
246  assert(other.family != 0);
247 
248  if (this != &other) {
249  this->family = other.family;
250  this->addr = other.addr;
251  this->scache = other.scache;
252  this->hcache = other.hcache;
253  }
254 
255  return *this;
256 }
257 
258 IPAddress & IPAddress::operator=(const IPAddress &&other) throw () {
259  assert(other.family != 0);
260 
261  if (this != &other) {
262  this->family = other.family;
263  this->addr = other.addr;
264  this->scache = std::move(other.scache);
265  this->hcache = other.hcache;
266  }
267 
268  return *this;
269 }
270 
271 bool IPAddress::operator==(const IPAddress &other) const throw () {
272  assert(this->family != 0);
273 
274  if (this->family != other.family) {
275  return false;
276  }
277 
278  if (this->family == AF_INET) {
279  return (this->addr.v4.s_addr == other.addr.v4.s_addr);
280  } else {
281  const uint64_t *a = (const uint64_t*) this->addr.v6.s6_addr;
282  const uint64_t *b = (const uint64_t*) other.addr.v6.s6_addr;
283 
284  /* Ordered by most likely to be different. */
285  return (a[1] == b[1] && a[0] == b[0]);
286  }
287 }
288 
289 bool IPAddress::operator!=(const IPAddress &other) const throw () {
290  return !(*this == other);
291 }
292 
293 bool IPAddress::operator>=(const IPAddress &other) const throw () {
294  if (*this == other) {
295  return true;
296  }
297 
298  return (*this > other);
299 }
300 
301 bool IPAddress::operator<=(const IPAddress &other) const throw () {
302  if (*this == other) {
303  return true;
304  }
305 
306  return (*this < other);
307 }
308 
309 bool IPAddress::operator>(const IPAddress &other) const throw () {
310  if (this->family != other.family) {
311  return (this->family > other.family);
312  }
313 
314  if (this->family == AF_INET) {
315  return (ntohl(this->addr.v4.s_addr) > ntohl(other.addr.v4.s_addr));
316  } else {
317  const uint64_t *a = (const uint64_t*) this->addr.v6.s6_addr;
318  const uint64_t *b = (const uint64_t*) other.addr.v6.s6_addr;
319 
320  return (ntohll(a[0]) > ntohll(b[0]) || ntohll(a[1]) > ntohll(b[1]));
321  }
322 }
323 
324 bool IPAddress::operator<(const IPAddress &other) const throw () {
325  if (this->family != other.family) {
326  return (this->family < other.family);
327  }
328 
329  if (this->family == AF_INET) {
330  return (ntohl(this->addr.v4.s_addr) < ntohl(other.addr.v4.s_addr));
331  } else {
332  const uint64_t *a = (const uint64_t*) this->addr.v6.s6_addr;
333  const uint64_t *b = (const uint64_t*) other.addr.v6.s6_addr;
334 
335  return (ntohll(a[0]) < ntohll(b[0]) || ntohll(a[1]) < ntohll(b[1]));
336  }
337 }
338 
339 IPAddress IPAddress::operator&(const IPAddress &other) const throw (AddressException) {
340  if (this->family != other.family) {
341  THROW(AddressException, "mismatched family not supported");
342  }
343 
344  IPAddress res(other);
345 
346  res.hcache = 0;
347  res.scache.clear();
348 
349  if (this->family == AF_INET) {
350  res.addr.v4.s_addr &= this->addr.v4.s_addr;
351  } else {
352  uint64_t *a = (uint64_t*) this->addr.v6.s6_addr;
353  uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
354 
355  r[0] &= a[0];
356  r[1] &= a[1];
357  }
358 
359  return res;
360 }
361 
362 IPAddress IPAddress::operator|(const IPAddress &other) const throw (AddressException) {
363  if (this->family != other.family) {
364  THROW(AddressException, "mismatched family not supported");
365  }
366 
367  IPAddress res(other);
368 
369  res.hcache = 0;
370  res.scache.clear();
371 
372  if (this->family == AF_INET) {
373  res.addr.v4.s_addr |= this->addr.v4.s_addr;
374  } else {
375  uint64_t *a = (uint64_t*) this->addr.v6.s6_addr;
376  uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
377 
378  r[0] |= a[0];
379  r[1] |= a[1];
380  }
381 
382  return res;
383 }
384 
385 IPAddress IPAddress::operator^(const IPAddress &other) const throw (AddressException) {
386  if (this->family != other.family) {
387  THROW(AddressException, "mismatched family not supported");
388  }
389 
390  IPAddress res(other);
391 
392  res.hcache = 0;
393  res.scache.clear();
394 
395  if (this->family == AF_INET) {
396  res.addr.v4.s_addr ^= this->addr.v4.s_addr;
397  } else {
398  uint64_t *a = (uint64_t*) this->addr.v6.s6_addr;
399  uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
400 
401  r[0] ^= a[0];
402  r[1] ^= a[1];
403  }
404 
405  return res;
406 }
407 
408 IPAddress IPAddress::operator~() const throw () {
409  IPAddress res(*this);
410 
411  res.hcache = 0;
412  res.scache.clear();
413 
414  if (this->family == AF_INET) {
415  res.addr.v4.s_addr = ~(res.addr.v4.s_addr);
416  } else {
417  uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
418 
419  r[0] = ~r[0];
420  r[1] = ~r[1];
421  }
422 
423  return res;
424 }
425 
426 IPAddress& IPAddress::operator+=(uint32_t increment) throw () {
427  this->hcache = 0;
428  this->scache.clear();
429 
430  if (this->family == AF_INET) {
431  addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) + increment);
432  } else {
433  uint64_t t[2] { 0, 0 };
434  uint64_t *a = (uint64_t*) addr.v6.s6_addr;
435 
436  t[1] = ntohll(a[1]) + increment;
437 
438  if (t[1] < ntohll(a[1]) || t[1] < (uint64_t) increment) { /* Overflow */
439  t[0] = ntohll(a[0]) + t[1] + 1;
440  t[1] = 0;
441 
442  if (t[0] < ntohll(a[0])) { /* Overflow */
443  t[1] = t[0];
444  t[0] = 0;
445  }
446  } else {
447  t[0] = ntohll(a[0]);
448  }
449 
450  a[0] = htonll(t[0]);
451  a[1] = htonll(t[1]);
452  }
453 
454  return *this;
455 }
456 
457 IPAddress IPAddress::operator+(uint32_t increment) const throw () {
458  IPAddress res(*this);
459 
460  return (res += increment);
461 }
462 
463 IPAddress IPAddress::operator++(int) throw () {
464  IPAddress res(*this);
465  ++(*this);
466 
467  return res;
468 }
469 
470 IPAddress& IPAddress::operator++() throw () {
471  return (*this += 1);
472 }
473 
474 IPAddress& IPAddress::operator-=(uint32_t increment) throw () {
475  this->hcache = 0;
476  this->scache.clear();
477 
478  if (this->family == AF_INET) {
479  addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) - increment);
480  } else {
481  uint64_t t[2] { 0, 0 };
482  uint64_t *a = (uint64_t*) addr.v6.s6_addr;
483 
484  t[1] = ntohll(a[1]) - increment;
485 
486  if (t[1] > ntohll(a[1]) && t[1] > (uint64_t) increment) { /* Underflow */
487  t[0] = ntohll(a[0]) - (std::numeric_limits<uint64_t>::max() - t[1] + 1);
488  t[1] = std::numeric_limits<uint64_t>::max();
489 
490  if (t[0] > ntohll(a[0])) { /* Overflow */
491  t[1] = t[0];
492  t[0] = std::numeric_limits<uint64_t>::max();
493  }
494  } else {
495  t[0] = ntohll(a[0]);
496  }
497 
498  a[0] = htonll(t[0]);
499  a[1] = htonll(t[1]);
500  }
501 
502  return *this;
503 }
504 
505 IPAddress IPAddress::operator-(uint32_t increment) const throw () {
506  IPAddress res(*this);
507 
508  return (res -= increment);
509 }
510 
511 IPAddress IPAddress::operator--(int) throw () {
512  IPAddress res(*this);
513  --(*this);
514 
515  return res;
516 }
517 
518 IPAddress& IPAddress::operator--() throw () {
519  return (*this -= 1);
520 }
521 
522 bool IPAddress::parse(int &family, struct in6_addr &v6, struct in_addr &v4, const std::string &addr) throw () {
523  if (this->parse(family, v6, addr) == false) {
524  return this->parse(family, v4, addr);
525  }
526  return true;
527 }
528 
529 bool IPAddress::parse(int &family, struct in_addr &v4, struct in6_addr &v6, const std::string &addr) throw () {
530  if (this->parse(family, v4, addr) == false) {
531  return this->parse(family, v6, addr);
532  }
533  return true;
534 }
535 
536 bool IPAddress::parse(int &family, struct in_addr &v4, const std::string &addr) throw () {
537  bool result = false;
538 
539  struct ifreq interface[256];
540  struct sockaddr_in *sockaddr;
541  int s;
542 
543  assert(family != 0);
544 
545  if (inet_pton(AF_INET, addr.c_str(), &v4) != 1) {
546  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) > 1) {
547  strncpy(interface[0].ifr_name, addr.c_str(), IFNAMSIZ);
548  interface[0].ifr_addr.sa_family = AF_INET;
549 
550  if (ioctl(s, SIOCGIFADDR, interface) == 0) {
551  sockaddr = (struct sockaddr_in *)&(interface[0].ifr_ifru.ifru_addr);
552  memcpy(&v4, &(sockaddr->sin_addr), sizeof(addr));
553 
554  family = AF_INET;
555  result = true;
556  }
557  close(s);
558  }
559  } else {
560  family = AF_INET;
561  result = true;
562  }
563  return result;
564 }
565 
566 bool IPAddress::parse(int &famiy, struct in6_addr &v6, const std::string &addr) throw () {
567  bool result = false;
568 
569  struct ifreq interface[256];
570  struct sockaddr_in6 *sockaddr;
571  int s;
572 
573  assert(family != 0);
574 
575  if (inet_pton(AF_INET6, addr.c_str(), &v6) != 1) {
576  if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) > 1) {
577  strncpy(interface[0].ifr_name, addr.c_str(), IFNAMSIZ);
578  interface[0].ifr_addr.sa_family = AF_INET6;
579 
580  if (ioctl(s, SIOCGIFADDR, interface) == 0) {
581  sockaddr = (struct sockaddr_in6 *)&(interface[0].ifr_ifru.ifru_addr);
582  memcpy(&v6, &(sockaddr->sin6_addr), sizeof(addr));
583 
584  family = AF_INET6;
585  result = true;
586  }
587  close(s);
588  }
589  } else {
590  family = AF_INET6;
591  result = true;
592  }
593  return result;
594 }
595 
596 void IPAddress::applyCIDR(uint8_t cidr) throw (AddressException) {
597  assert(this->family != 0);
598 
599  if (this->family == AF_INET) {
600  if (cidr > 0) {
601  if (cidr > 32) {
602  cidr = 32;
603  }
604 
605  addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) >> (32 - cidr) << (32 - cidr));
606  } else { /* C/C++ inteprets shifting a 32 bit integer by 32 bits as shifting by 0. */
607  addr.v4.s_addr = 0;
608  }
609  } else {
610  if (cidr > 128) {
611  cidr = 128;
612  }
613 
614  for (int i = 15; i > cidr / 8 - 1; i--) {
615  if (i == cidr / 8) {
616  addr.v6.s6_addr[i] = addr.v6.s6_addr[i] >> (8 - cidr % 8) << (8 - cidr % 8);
617  } else {
618  addr.v6.s6_addr[i] = 0;
619  }
620  }
621  }
622 
623  scache.clear();
624  hcache = 0;
625 }
626 
627 int IPAddress::getFamily(void) const throw () {
628  assert(this->family != 0);
629 
630  return this->family;
631 }
632 
633 const struct in_addr& IPAddress::getIPv4AddressStructure(void) const throw (AddressException) {
634  if (this->family != IPv4Family) {
635  THROW(AddressException, "instance is not an IPv4 address");
636  }
637  return this->addr.v4;
638 }
639 
640 const struct in6_addr& IPAddress::getIPv6AddressStructure(void) const throw (AddressException) {
641  if (this->family != IPv6Family) {
642  THROW(AddressException, "instance is not an IPv6 address");
643  }
644  return this->addr.v6;
645 }
646 
647 size_t IPAddress::getAddressStructureSize(void) const throw () {
648  assert(this->family != 0);
649 
650  return (this->family == IPv4Family) ? sizeof(this->addr.v4) : sizeof(this->addr.v6);
651 }
652 
653 const std::string& IPAddress::str(void) const throw (AddressException) {
654  char buffer[INET6_ADDRSTRLEN];
655 
656  assert(this->family != 0);
657 
658  if (scache.empty()) {
659  if (inet_ntop(this->family, &(this->addr), buffer, sizeof(buffer)) == NULL) {
660  THROW(AddressException, "inet_ntop failure");
661  }
662 
663  scache = buffer;
664  }
665 
666  return scache;
667 }
668 
669 const char* IPAddress::c_str(void) const throw (AddressException) {
670  return str().c_str();
671 }
672 
673 uint32_t IPAddress::getU32(void) const throw () {
674  assert(this->family != 0);
675 
676  if (this->family == IPv4Family) {
677  return ntohl(this->addr.v4.s_addr);
678  }
679 
680  const uint32_t *a = (const uint32_t*) this->addr.v6.s6_addr;
681 
682  return ntohl(a[0] ^ ~a[1] ^ a[2] ^ ~a[3]);
683 }
684 
685 uint32_t IPAddress::getHash(void) const throw () {
686  if (hcache != 0) {
687  return hcache;
688  }
689 
690 #if defined HASH_ALGO_INT1 /* Fast. Nibble swap. */
691  uint32_t k = getU32();
692 
693  hcache = ((k & 0xF0F0F0F0) >> 4) | ((k & 0x0F0F0F0F) << 4);
694 #elif defined HASH_ALGO_INT2
695  uint32_t k = getU32();
696 
697  hcache = (k<<16)^(k>>16)^k; /* Fast. Mix by XOR shifting.. */
698 #elif defined HASH_ALGO_INT3 /* Very fast, but not very good. */
699  hcache = getU32();
700 #else
701  #error No hash algo selected.
702 #endif
703 
704  return hcache;
705 }
706 
707 bool IPAddress::empty(void) const throw () {
708  if (family == IPv4Family) {
709  return this->addr.v4.s_addr == 0;
710  }
711 
712  const uint64_t *a = (const uint64_t*) this->addr.v6.s6_addr;
713 
714  return (a[0] == 0 && a[1] == 0);
715 }
716 
717 void IPAddress::clear(void) throw () {
718  hcache = 0;
719  scache.clear();
720  family = IPv4Family;
721  memset(&addr, 0, sizeof(addr));
722 }
723 
724 const IPAddress::shared IPAddress::shared_ptr(const std::string &text, int family, uint8_t cidr) throw (AddressException) {
725  return std::make_shared<IPAddress>(text, family, cidr);
726 }
727 
728 const IPAddress::shared IPAddress::shared_ptr(int family, uint8_t cidr) throw (AddressException) {
729  return std::make_shared<IPAddress>(family, cidr);
730 }
731 
732 const IPAddress::shared IPAddress::shared_ptr(const struct sockaddr_storage *ss, uint8_t cidr) throw (AddressException) {
733  return std::make_shared<IPAddress>(ss, cidr);
734 }
735 
736 const IPAddress::shared IPAddress::shared_ptr(const struct sockaddr *sa, uint8_t cidr) throw (AddressException) {
737  return std::make_shared<IPAddress>(sa, cidr);
738 }
739 
740 const IPAddress::shared IPAddress::shared_ptr(const struct in_addr *in, uint8_t cidr) throw (AddressException) {
741  return std::make_shared<IPAddress>(in, cidr);
742 }
743 
744 const IPAddress::shared IPAddress::shared_ptr(const struct in6_addr *in6, uint8_t cidr) throw (AddressException) {
745  return std::make_shared<IPAddress>(in6, cidr);
746 }
747 
748 const IPAddress::shared IPAddress::shared_ptr(uint32_t address, uint8_t cidr) throw (AddressException) {
749  return std::make_shared<IPAddress>(address, cidr);
750 }
751 
752 const IPAddress::shared IPAddress::shared_ptr(unsigned char address[16], uint8_t cidr) throw (AddressException) {
753  return std::make_shared<IPAddress>(address, cidr);
754 }
755 
756 /*
757 ** vim: noet ts=3 sw=3
758 */