9 static const char rcsid[] __attribute__((used)) =
"$Id: IPAddress.cpp 1875 2017-03-24 17:28:04Z sella $";
11 #include "IPAddress.h"
12 #include "AddressException.h"
13 #include "../util/CommonMacro.h"
20 #include <arpa/inet.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
27 #define HASH_ALGO_INT1
30 struct sockaddr_storage *ss;
32 struct sockaddr_in *sa_in;
33 struct sockaddr_in6 *sa_in6;
36 using namespace sella::net;
38 IPAddress::IPAddress(
const std::string &text,
int family, uint8_t cidr)
throw (AddressException) :
44 char buffer[INET6_ADDRSTRLEN];
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());
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());
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());
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());
74 THROW(AddressException,
"unable to parse address: unknown family supplied for address '%s'", text.c_str());
77 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
78 THROW(AddressException,
"unable to parse address '%s'", text.c_str());
86 IPAddress::IPAddress(
int family)
throw (AddressException) : family(family), hcache(0) {
87 char buffer[INET6_ADDRSTRLEN];
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");
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",
"::");
107 THROW(AddressException,
"unable to parse address: unknown family supplied for default address");
110 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
111 THROW(AddressException,
"unable to parse default address");
115 IPAddress::IPAddress(
const struct sockaddr_storage *ss, uint8_t cidr)
throw (AddressException) : hcache(0) {
116 char buffer[INET6_ADDRSTRLEN];
120 THROW(AddressException,
"passed sockaddr_storage is null");
123 u.ss = (
struct sockaddr_storage*) ss;
124 this->family = u.sa->sa_family;
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;
131 THROW(AddressException,
"unknown family '%d'", this->family);
134 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
135 THROW(AddressException,
"unable to convert sockaddr");
143 IPAddress::IPAddress(
const struct sockaddr *sa, uint8_t cidr)
throw (AddressException) : hcache(0) {
144 char buffer[INET6_ADDRSTRLEN];
148 THROW(AddressException,
"passed sockaddr is null");
151 u.sa = (
struct sockaddr*) sa;
152 this->family = sa->sa_family;
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;
159 THROW(AddressException,
"unknown family '%d'", this->family);
162 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
163 THROW(AddressException,
"unable to convert sockaddr");
171 IPAddress::IPAddress(
const struct in_addr *in, uint8_t cidr)
throw (AddressException) : hcache(0) {
172 char buffer[INET6_ADDRSTRLEN];
175 THROW(AddressException,
"passed in_addr is null");
178 this->family = AF_INET;
181 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
182 THROW(AddressException,
"unable to convert in_addr");
190 IPAddress::IPAddress(
const struct in6_addr *in6, uint8_t cidr)
throw (AddressException) {
191 char buffer[INET6_ADDRSTRLEN];
194 THROW(AddressException,
"passed in6_addr is null");
197 this->family = AF_INET6;
198 this->addr.v6 = *in6;
200 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
201 THROW(AddressException,
"unable to convert in_addr");
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);
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));
227 IPAddress::IPAddress(
const IPAddress &other)
throw () :
228 family(other.family),
230 scache(other.scache),
234 IPAddress::IPAddress(
const IPAddress &&other) throw () :
235 family(other.family),
237 scache(std::move(other.scache)),
241 IPAddress::~IPAddress() throw () {
246 assert(other.family != 0);
248 if (
this != &other) {
249 this->family = other.family;
250 this->addr = other.addr;
251 this->scache = other.scache;
252 this->hcache = other.hcache;
259 assert(other.family != 0);
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;
271 bool IPAddress::operator==(
const IPAddress &other)
const throw () {
272 assert(this->family != 0);
274 if (this->family != other.family) {
278 if (this->family == AF_INET) {
279 return (this->addr.v4.s_addr == other.addr.v4.s_addr);
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;
285 return (a[1] == b[1] && a[0] == b[0]);
289 bool IPAddress::operator!=(
const IPAddress &other)
const throw () {
290 return !(*
this == other);
293 bool IPAddress::operator>=(
const IPAddress &other)
const throw () {
294 if (*
this == other) {
298 return (*
this > other);
301 bool IPAddress::operator<=(
const IPAddress &other)
const throw () {
302 if (*
this == other) {
306 return (*
this < other);
309 bool IPAddress::operator>(
const IPAddress &other)
const throw () {
310 if (this->family != other.family) {
311 return (this->family > other.family);
314 if (this->family == AF_INET) {
315 return (ntohl(this->addr.v4.s_addr) > ntohl(other.addr.v4.s_addr));
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;
320 return (ntohll(a[0]) > ntohll(b[0]) || ntohll(a[1]) > ntohll(b[1]));
324 bool IPAddress::operator<(
const IPAddress &other)
const throw () {
325 if (this->family != other.family) {
326 return (this->family < other.family);
329 if (this->family == AF_INET) {
330 return (ntohl(this->addr.v4.s_addr) < ntohl(other.addr.v4.s_addr));
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;
335 return (ntohll(a[0]) < ntohll(b[0]) || ntohll(a[1]) < ntohll(b[1]));
339 IPAddress IPAddress::operator&(
const IPAddress &other)
const throw (AddressException) {
340 if (this->family != other.family) {
341 THROW(AddressException,
"mismatched family not supported");
349 if (this->family == AF_INET) {
350 res.addr.v4.s_addr &= this->addr.v4.s_addr;
352 uint64_t *a = (uint64_t*) this->addr.v6.s6_addr;
353 uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
362 IPAddress IPAddress::operator|(
const IPAddress &other)
const throw (AddressException) {
363 if (this->family != other.family) {
364 THROW(AddressException,
"mismatched family not supported");
372 if (this->family == AF_INET) {
373 res.addr.v4.s_addr |= this->addr.v4.s_addr;
375 uint64_t *a = (uint64_t*) this->addr.v6.s6_addr;
376 uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
385 IPAddress IPAddress::operator^(
const IPAddress &other)
const throw (AddressException) {
386 if (this->family != other.family) {
387 THROW(AddressException,
"mismatched family not supported");
395 if (this->family == AF_INET) {
396 res.addr.v4.s_addr ^= this->addr.v4.s_addr;
398 uint64_t *a = (uint64_t*) this->addr.v6.s6_addr;
399 uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
408 IPAddress IPAddress::operator~()
const throw () {
414 if (this->family == AF_INET) {
415 res.addr.v4.s_addr = ~(res.addr.v4.s_addr);
417 uint64_t *r = (uint64_t*) res.addr.v6.s6_addr;
426 IPAddress& IPAddress::operator+=(uint32_t increment)
throw () {
428 this->scache.clear();
430 if (this->family == AF_INET) {
431 addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) + increment);
433 uint64_t t[2] { 0, 0 };
434 uint64_t *a = (uint64_t*) addr.v6.s6_addr;
436 t[1] = ntohll(a[1]) + increment;
438 if (t[1] < ntohll(a[1]) || t[1] < (uint64_t) increment) {
439 t[0] = ntohll(a[0]) + t[1] + 1;
442 if (t[0] < ntohll(a[0])) {
457 IPAddress IPAddress::operator+(uint32_t increment)
const throw () {
460 return (res += increment);
463 IPAddress IPAddress::operator++(
int) throw () {
470 IPAddress& IPAddress::operator++() throw () {
474 IPAddress& IPAddress::operator-=(uint32_t increment)
throw () {
476 this->scache.clear();
478 if (this->family == AF_INET) {
479 addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) - increment);
481 uint64_t t[2] { 0, 0 };
482 uint64_t *a = (uint64_t*) addr.v6.s6_addr;
484 t[1] = ntohll(a[1]) - increment;
486 if (t[1] > ntohll(a[1]) && t[1] > (uint64_t) increment) {
487 t[0] = ntohll(a[0]) - (std::numeric_limits<uint64_t>::max() - t[1] + 1);
488 t[1] = std::numeric_limits<uint64_t>::max();
490 if (t[0] > ntohll(a[0])) {
492 t[0] = std::numeric_limits<uint64_t>::max();
505 IPAddress IPAddress::operator-(uint32_t increment)
const throw () {
508 return (res -= increment);
511 IPAddress IPAddress::operator--(
int) throw () {
518 IPAddress& IPAddress::operator--() throw () {
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);
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);
536 bool IPAddress::parse(
int &family,
struct in_addr &v4,
const std::string &addr)
throw () {
539 struct ifreq interface[256];
540 struct sockaddr_in *sockaddr;
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;
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));
566 bool IPAddress::parse(
int &famiy,
struct in6_addr &v6,
const std::string &addr)
throw () {
569 struct ifreq interface[256];
570 struct sockaddr_in6 *sockaddr;
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;
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));
596 void IPAddress::applyCIDR(uint8_t cidr)
throw (AddressException) {
597 assert(this->family != 0);
599 if (this->family == AF_INET) {
605 addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) >> (32 - cidr) << (32 - cidr));
614 for (
int i = 15; i > cidr / 8 - 1; i--) {
616 addr.v6.s6_addr[i] = addr.v6.s6_addr[i] >> (8 - cidr % 8) << (8 - cidr % 8);
618 addr.v6.s6_addr[i] = 0;
627 int IPAddress::getFamily(
void)
const throw () {
628 assert(this->family != 0);
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");
637 return this->addr.v4;
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");
644 return this->addr.v6;
647 size_t IPAddress::getAddressStructureSize(
void)
const throw () {
648 assert(this->family != 0);
650 return (this->family == IPv4Family) ?
sizeof(this->addr.v4) :
sizeof(this->addr.v6);
653 const std::string& IPAddress::str(
void)
const throw (AddressException) {
654 char buffer[INET6_ADDRSTRLEN];
656 assert(this->family != 0);
658 if (scache.empty()) {
659 if (inet_ntop(this->family, &(this->addr), buffer,
sizeof(buffer)) == NULL) {
660 THROW(AddressException,
"inet_ntop failure");
669 const char* IPAddress::c_str(
void)
const throw (AddressException) {
670 return str().c_str();
673 uint32_t IPAddress::getU32(
void)
const throw () {
674 assert(this->family != 0);
676 if (this->family == IPv4Family) {
677 return ntohl(this->addr.v4.s_addr);
680 const uint32_t *a = (
const uint32_t*) this->addr.v6.s6_addr;
682 return ntohl(a[0] ^ ~a[1] ^ a[2] ^ ~a[3]);
685 uint32_t IPAddress::getHash(
void)
const throw () {
690 #if defined HASH_ALGO_INT1
691 uint32_t k = getU32();
693 hcache = ((k & 0xF0F0F0F0) >> 4) | ((k & 0x0F0F0F0F) << 4);
694 #elif defined HASH_ALGO_INT2
695 uint32_t k = getU32();
697 hcache = (k<<16)^(k>>16)^k;
698 #elif defined HASH_ALGO_INT3
701 #error No hash algo selected.
707 bool IPAddress::empty(
void)
const throw () {
708 if (family == IPv4Family) {
709 return this->addr.v4.s_addr == 0;
712 const uint64_t *a = (
const uint64_t*) this->addr.v6.s6_addr;
714 return (a[0] == 0 && a[1] == 0);
717 void IPAddress::clear(
void) throw () {
721 memset(&addr, 0,
sizeof(addr));
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);
728 const IPAddress::shared IPAddress::shared_ptr(
int family, uint8_t cidr)
throw (AddressException) {
729 return std::make_shared<IPAddress>(family, cidr);
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);
736 const IPAddress::shared IPAddress::shared_ptr(
const struct sockaddr *sa, uint8_t cidr)
throw (AddressException) {
737 return std::make_shared<IPAddress>(sa, cidr);
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);
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);
748 const IPAddress::shared IPAddress::shared_ptr(uint32_t address, uint8_t cidr)
throw (AddressException) {
749 return std::make_shared<IPAddress>(address, cidr);
752 const IPAddress::shared IPAddress::shared_ptr(
unsigned char address[16], uint8_t cidr)
throw (AddressException) {
753 return std::make_shared<IPAddress>(address, cidr);