in net/socket.h [45:153]
struct __attribute__ ((packed)) IPAddr {
public:
union {
in6_addr addr = {};
// all data is in network byte order
struct { uint16_t _1, _2, _3, _4, _5, _6; uint8_t a, b, c, d; };
} __attribute__((packed));
// For compatibility, the default constructor is still 0.0.0.0 (IPv4)
IPAddr() {
map_v4(htonl(INADDR_ANY));
}
// V6 constructor (Internet Address)
explicit IPAddr(in6_addr internet_addr) {
addr = internet_addr;
}
// V6 constructor (Network byte order)
IPAddr(uint32_t nl1, uint32_t nl2, uint32_t nl3, uint32_t nl4) {
addr._in_addr_field[0] = nl1;
addr._in_addr_field[1] = nl2;
addr._in_addr_field[2] = nl3;
addr._in_addr_field[3] = nl4;
}
// V4 constructor (Internet Address)
explicit IPAddr(in_addr internet_addr) {
map_v4(internet_addr);
}
// V4 constructor (Network byte order)
explicit IPAddr(uint32_t nl) {
map_v4(nl);
}
// String constructor
explicit IPAddr(const char* s) {
if (inet_pton(AF_INET6, s, &addr) > 0) {
return;
}
in_addr v4_addr;
if (inet_pton(AF_INET, s, &v4_addr) > 0) {
map_v4(v4_addr);
return;
}
// Invalid string, make it a default value
*this = IPAddr();
}
// Check if it's actually an IPv4 address mapped in IPV6
bool is_ipv4() const {
return addr._in_addr_field[0] == 0 &&
addr._in_addr_field[1] == 0 &&
addr._in_addr_field[2] == htonl(0x0000ffff);
}
bool is_ipv6() const {
return !is_ipv4();
}
// We regard the default IPv4 0.0.0.0 as undefined
bool undefined() const {
return mem_equal(V4Any());
}
void reset() { *this = IPAddr(); }
void clear() { reset(); }
// Should ONLY be used for IPv4 address
uint32_t to_nl() const {
assert(is_ipv4());
return addr._in_addr_field[3];
}
bool is_loopback() const {
return is_ipv4() ? mem_equal(V4Loopback()) : mem_equal(V6Loopback());
}
bool is_localhost() const {
return is_loopback();
}
bool is_broadcast() const {
// IPv6 does not support broadcast
return is_ipv4() && mem_equal(V4Broadcast());
}
bool is_link_local() const {
if (is_ipv4()) {
return (to_nl() & htonl(0xffff0000)) == htonl(0xa9fe0000);
} else {
return (addr._in_addr_field[0] & htonl(0xffc00000)) == htonl(0xfe800000);
}
}
bool operator==(const IPAddr& rhs) const {
return mem_equal(rhs);
}
bool operator!=(const IPAddr& rhs) const {
return !(*this == rhs);
}
static IPAddr V6None() {
return IPAddr(htonl(0xffffffff), htonl(0xffffffff), htonl(0xffffffff), htonl(0xffffffff));
}
static IPAddr V6Any() { return IPAddr(in6addr_any); }
static IPAddr V6Loopback() { return IPAddr(in6addr_loopback); }
static IPAddr V4Broadcast() { return IPAddr(htonl(INADDR_BROADCAST)); }
static IPAddr V4Any() { return IPAddr(htonl(INADDR_ANY)); }
static IPAddr V4Loopback() { return IPAddr(htonl(INADDR_LOOPBACK)); }
static IPAddr Localhost() { return V4Loopback(); }
private:
bool mem_equal(const IPAddr& rhs) const {
return memcmp(this, &rhs, sizeof(rhs)) == 0;
}
void map_v4(in_addr addr_) {
map_v4(addr_.s_addr);
}
void map_v4(uint32_t nl) {
addr._in_addr_field[0] = 0x00000000;
addr._in_addr_field[1] = 0x00000000;
addr._in_addr_field[2] = htonl(0xffff);
addr._in_addr_field[3] = nl;
}
};