16namespace swoc {
inline namespace SWOC_VERSION_NS {
18using std::string_view;
29 friend class IP4Range;
32 static constexpr size_t SIZE =
sizeof(in_addr_t);
33 static constexpr size_t WIDTH = std::numeric_limits<unsigned char>::digits *
SIZE;
35 static const self_type
MIN;
36 static const self_type
MAX;
37 static constexpr sa_family_t
AF_value = AF_INET;
47 explicit constexpr IP4Addr(in_addr_t addr);
50 explicit IP4Addr(sockaddr_in
const *s);
54 IP4Addr(string_view
const &text);
57 self_type &
operator=(self_type
const &that) =
default;
63 self_type &
operator=(sockaddr_in
const *sa);
93 sockaddr *
copy_to(sockaddr *sa)
const;
100 sockaddr_in *
copy_to(sockaddr_in *sin)
const;
116 bool load(string_view
const &text);
119 int cmp(self_type
const &that)
const;
124 constexpr sa_family_t
family()
const;
181 constexpr static in_addr_t
reorder(in_addr_t src);
185 using bytes = std::array<uint8_t, 4>;
187 friend bool operator==(self_type
const &, self_type
const &);
188 friend bool operator!=(self_type
const &, self_type
const &);
189 friend bool operator<(self_type
const &, self_type
const &);
190 friend bool operator<=(self_type
const &, self_type
const &);
203 friend class IP6Range;
207 static constexpr size_t WIDTH = 128;
208 static constexpr size_t SIZE =
WIDTH / std::numeric_limits<uint8_t>::digits;
221 static const self_type
MIN;
223 static const self_type
MAX;
226 IP6Addr(self_type
const &that) =
default;
229 explicit IP6Addr(in6_addr
const &addr);
232 explicit IP6Addr(sockaddr_in6
const *addr) { *
this = addr; }
237 IP6Addr(string_view
const &text);
287 self_type &
operator=(in6_addr
const &addr);
290 self_type &
operator=(sockaddr_in6
const *addr);
304 sockaddr_in6 *
copy_to(sockaddr_in6 *sin6)
const;
313 sockaddr *
copy_to(sockaddr *sa)
const;
342 bool load(string_view
const &str);
345 int cmp(self_type
const &that)
const;
348 constexpr sa_family_t
family()
const;
406 template <
typename T>
408 as_span() -> std::enable_if_t<swoc::meta::is_any_of_v<T, std::byte, uint8_t, uint16_t, uint32_t, uint64_t>,
swoc::MemSpan<T>> {
412 template <
typename T>
415 ->
std::enable_if_t<
swoc::meta::is_any_of_v<typename
std::remove_const_t<T>,
std::
byte, uint8_t, uint16_t, uint32_t, uint64_t>,
421 friend bool operator==(self_type
const &, self_type
const &);
423 friend bool operator!=(self_type
const &, self_type
const &);
425 friend bool operator<(self_type
const &, self_type
const &);
427 friend bool operator<=(self_type
const &, self_type
const &);
439 static constexpr size_t WORD_SIZE =
sizeof(
word_type);
442 static constexpr size_t WORD_WIDTH = std::numeric_limits<uint8_t>::digits * WORD_SIZE;
463 static_assert(
sizeof(in6_addr) ==
sizeof(
raw_type));
465 static constexpr unsigned LSW = 1;
466 static constexpr unsigned MSW = 0;
470 static constexpr std::array<unsigned, N_QUADS>
QUAD_IDX = {3, 2, 1, 0, 7, 6, 5, 4};
474 static constexpr std::array<unsigned, SIZE>
RAW_IDX = {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8};
480 static void reorder(
unsigned char dst[WORD_SIZE],
unsigned char const src[WORD_SIZE]);
487 IP6Addr(word_store_type::value_type msw, word_store_type::value_type lsw)
492 friend IP6Addr operator&(IP6Addr
const &addr, IPMask
const &mask);
494 friend IP6Addr operator|(IP6Addr
const &addr, IPMask
const &mask);
502 friend class IPRange;
511 explicit IPAddr(in_addr_t addr);
517 explicit IPAddr(in6_addr
const &addr);
523 explicit IPAddr(sockaddr
const *addr);
530 explicit IPAddr(string_view
const &text);
533 self_type &
assign(sockaddr
const *addr);
536 self_type &
assign(sockaddr_in
const *addr);
539 self_type &
assign(sockaddr_in6
const *addr);
542 self_type &
assign(in_addr_t addr);
545 self_type &
assign(in6_addr
const &addr);
554 self_type &
operator=(in6_addr
const &addr);
560 bool operator<(self_type
const &that)
const;
562 bool operator>(self_type
const &that)
const;
569 self_type &
operator=(sockaddr
const *addr);
571 self_type &operator&=(
IPMask const &mask);
573 self_type &operator|=(
IPMask const &mask);
580 sockaddr *
copy_to(sockaddr *sa)
const;
587 bool load(string_view
const &text);
590 int cmp(self_type
const &that)
const;
598 sa_family_t
family()
const;
610 explicit operator IP4Addr()
const;
616 explicit operator IP6Addr()
const;
637 static self_type
const INVALID;
644 union raw_addr_type {
648 constexpr raw_addr_type();
650 raw_addr_type(in_addr_t addr) :
_ip4(addr) {}
656 raw_addr_type(IP6Addr
const &addr) :
_ip6(addr) {}
669 friend class IP4Addr;
670 friend class IP6Addr;
693 bool load(string_view
const &text);
705 static self_type
mask_for(IP4Addr
const &addr);
711 static self_type
mask_for(IP6Addr
const &addr);
755 static constexpr auto INVALID = std::numeric_limits<raw_type>::max();
768 if (!this->
load(text)) {
773inline constexpr sa_family_t
832 this->
copy_to(
reinterpret_cast<sockaddr_in *
>(sa));
887 return _addr == INADDR_ANY;
892 return (*
this)[0] == IN_LOOPBACKNET;
897 return IN_MULTICAST(
_addr);
902 return ip::is_link_local_host_order(
_addr);
907 return ip::is_private_host_order(
_addr);
912 return reinterpret_cast<bytes const &
>(
_addr)[3 - idx];
922 return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 0xFF) << 8) | ((src >> 24) & 0xFF);
927inline constexpr sa_family_t
937 if (!this->
load(text)) {
943 _addr._store[
MSW] = 0;
952 return _addr._store[
MSW] == 0 && _addr._store[
LSW] == 1;
957 return _addr._raw[
RAW_IDX[0]] == 0xFF;
962 return _addr._store[
MSW] == 0 && _addr._store[
LSW] == 0;
967 return 0 == _addr._store[
MSW] && (_addr._quad[
QUAD_IDX[4]] == 0 && _addr._quad[
QUAD_IDX[5]] == 0xFFFF);
972 return _addr._raw[
RAW_IDX[0]] == 0xFE && (_addr._raw[
RAW_IDX[1]] & 0xC0) == 0x80;
977 return (_addr._raw[
RAW_IDX[0]] & 0xFE) == 0xFC;
983 {_addr._store[
LSW], _addr._store[
MSW]}
990 Addr *addr =
reinterpret_cast<Addr *
>(&dst);
1010 _addr._store[
MSW] = _addr._store[
LSW] = 0;
1023 *
this = addr->sin6_addr;
1032 if (++(_addr._store[
LSW]) == 0) {
1033 ++(_addr._store[
MSW]);
1040 if (--(_addr._store[
LSW]) == ~
static_cast<uint64_t
>(0)) {
1041 --(_addr._store[
MSW]);
1048 for (
size_t idx = 0; idx < WORD_SIZE; ++idx) {
1049 dst[idx] = src[WORD_SIZE - (idx + 1)];
1097 this->
copy_to(
reinterpret_cast<sockaddr_in6 *
>(sa));
1104 _addr._store[
LSW] = 0;
1105 if (0 == mask._cidr) {
1106 _addr._store[
MSW] = 0;
1110 }
else if (mask._cidr <
WIDTH) {
1119 if (mask._cidr <
WIDTH) {
1124 if (0 == mask._cidr) {
1153operator!=(IPMask
const &lhs, IPMask
const &rhs) {
1154 return lhs.width() != rhs.width();
1159 return lhs.width() < rhs.width();
1164 static constexpr auto MASK = ~in_addr_t{0};
1165 in_addr_t addr = MASK;
1167 addr = in_addr_t(0);
1171 return IP4Addr{addr};
1216 return _addr._raw[
RAW_IDX[idx]];
1221 return IPAddr{addr} &= mask;
1226 return IPAddr{addr} |= mask;
1230inline constexpr IPAddr::raw_addr_type::raw_addr_type() : _ip4(INADDR_ANY) {}
1260 return this->
assign(addr);
1285 return (AF_INET ==
_family && _addr._ip4.is_loopback()) || (AF_INET6 ==
_family && _addr._ip6.is_loopback());
1327 _addr._ip6 = addr->sin6_addr;
1359 return !(lhs == rhs);
1365 return !(rhs == lhs);
1368inline IP4Addr
const &
1372inline IPAddr::operator IP4Addr()
const {
1380inline IPAddr::operator IP6Addr()
const {
1385IPAddr::operator==(self_type
const &that)
const {
1389 ( this->
is_ip6() && _addr.
_ip6 == that._addr._ip6 ) ||
1395IPAddr::operator!=(self_type
const &that)
const {
1396 return !(*
this == that);
1400IPAddr::operator>(self_type
const &that)
const {
1401 return that < *
this;
1405IPAddr::operator<=(self_type
const &that)
const {
1406 return !(that < *
this);
1410IPAddr::operator>=(self_type
const &that)
const {
1411 return !(*
this < that);
1418 return lhs.is_ip4() && lhs.ip4() == rhs;
1423 return !lhs.is_ip4() || lhs.ip4() != rhs;
1428 return rhs.is_ip4() && lhs == rhs.ip4();
1433 return !rhs.is_ip4() || lhs != rhs.ip4();
1438 return lhs.is_ip6() && lhs.ip6() == rhs;
1443 return !lhs.is_ip6() || lhs.ip6() != rhs;
1448 return rhs.is_ip6() && lhs == rhs.ip6();
1453 return !rhs.is_ip6() || lhs != rhs.ip6();
1460template <>
struct hash<
swoc::IP4Addr> {
1468template <>
struct hash<
swoc::IP6Addr> {
1472 auto words = addr.as_span<uint64_t>();
1473 return words[0] ^ words[1];
1478template <>
struct hash<
swoc::IPAddr> {
1481 return addr.
is_ip4() ? hash<swoc::IP4Addr>()(addr.
ip4()) : addr.
is_ip6() ? hash<swoc::IP6Addr>()(addr.
ip6()) : 0;
bool is_multicast() const
static constexpr in_addr_t reorder(in_addr_t src)
self_type & operator>>=(unsigned n)
int cmp(self_type const &that) const
Standard ternary compare.
uint8_t operator[](unsigned idx) const
std::array< uint8_t, 4 > bytes
Access by bytes.
friend bool operator==(self_type const &, self_type const &)
Equality.
self_type & operator++()
Increment address.
self_type & operator&=(IPMask const &mask)
Apply mask to address, leaving the network portion.
friend bool operator<(self_type const &, self_type const &)
friend bool operator!=(self_type const &, self_type const &)
in_addr_t network_order() const
in_addr_t host_order() const
self_type & operator|=(IPMask const &mask)
Apply mask to address, creating the broadcast address.
static const self_type MIN
Minimum value.
static constexpr size_t SIZE
Size of IPv4 address in bytes.
constexpr sa_family_t family() const
static constexpr size_t WIDTH
sockaddr * copy_to(sockaddr *sa) const
IP4Addr(self_type const &that)=default
Copy constructor.
friend bool operator<=(self_type const &, self_type const &)
in_addr_t _addr
Address in host order.
self_type & operator--()
Decrement address.
static const self_type MAX
Maximum value.
self_type & operator=(self_type const &that)=default
Self assignment.
bool load(string_view const &text)
self_type & operator<<=(unsigned n)
constexpr IP4Addr()=default
Default constructor - ANY address.
bool is_link_local() const
static constexpr sa_family_t AF_value
Address family type.
self_type & operator=(self_type const &that)=default
Self assignment.
static void reorder(in6_addr &dst, raw_type const &src)
int cmp(self_type const &that) const
Generic three value compare.
self_type & operator++()
Increment address.
static constexpr word_type WORD_MASK
Mask the size of a word.
uint16_t quad_type
Size of one segment of an IPv6 address.
self_type & operator<<=(unsigned n)
static constexpr unsigned MSW
Most significant word index.
static const self_type MIN
Minimum value of an address.
static constexpr size_t QUAD_WIDTH
Number of bits per quad.
static constexpr quad_type QUAD_MASK
A bit mask of all 1 bits the size of a quad.
in6_addr host_order() const
Return the address in host order.
self_type & operator>>=(unsigned n)
uint64_t word_type
Type used as a "word", the natural working unit of the address.
bool load(string_view const &str)
std::array< word_type, N_STORE > word_store_type
Type used to store the address.
static const self_type MAX
Maximum value of an address.
static constexpr std::array< unsigned, N_QUADS > QUAD_IDX
static constexpr unsigned LSW
Least significant word index.
self_type & operator--()
Decrement address.
static constexpr size_t N_QUADS
in6_addr network_order() const
Return the address in network order.
self_type & operator|=(self_type const &that)
constexpr uint8_t operator[](int idx) const
std::array< quad_type, N_QUADS > quad_store_type
constexpr sa_family_t family() const
static constexpr std::array< unsigned, SIZE > RAW_IDX
sockaddr_in6 * copy_to(sockaddr_in6 *sin6) const
static constexpr size_t WIDTH
Number of bits in the address.
IP6Addr(sockaddr_in6 const *addr)
Construct from sockaddr_in.
std::array< uint8_t, SIZE > raw_type
self_type & operator&=(self_type const &that)
IP6Addr()=default
Default constructor - ANY address.
static constexpr size_t SIZE
Size of address in bytes.
bool is_link_local() const
IP6Addr(word_store_type::value_type msw, word_store_type::value_type lsw)
static constexpr size_t WORD_WIDTH
Number of bits per word.
bool is_multicast() const
static constexpr sa_family_t AF_value
Address family type.
bool is_mapped_ip4() const
static constexpr size_t N_STORE
Number of words used for basic address storage.
IPAddr(IP6Addr const &addr)
construct using an IPv6 addr
self_type & invalidate()
Make invalid.
self_type & operator=(self_type const &that)=default
Copy assignment.
bool is_valid() const
Test for validity.
bool is_loopback() const
Test for loopback.
IPAddr(self_type const &that)=default
Copy constructor.
bool is_ip6() const
Test for IPv6.
bool is_multicast() const
Test for multicast.
bool is_ip4() const
Test for IPv4.
bool is_private() const
Pre-constructed invalid instance.
IPAddr()=default
Default constructor - invalid result.
int cmp(self_type const &that) const
Generic compare.
bool is_same_family(self_type const &that)
IP6Addr const & ip6() const
sockaddr * copy_to(sockaddr *sa) const
IPAddr(IP4Addr const &addr)
Construct using an IPv4 addr.
bool is_link_local() const
bool load(string_view const &text)
IP4Addr const & ip4() const
sa_family_t _family
Protocol family.
self_type & assign(sockaddr const *addr)
Set to the address in addr.
sa_family_t family() const
bool load(string_view const &text)
uint8_t raw_type
Storage for mask width.
raw_type _cidr
Mask width in bits.
IPMask()=default
Default construct to invalid mask.
self_type & operator>>=(raw_type n)
self_type & clear()
Change to default constructed state (invalid).
raw_type width() const
The width of the mask.
static self_type mask_for(IPAddr const &addr)
static raw_type mask_for_quad(IP6Addr::quad_type q)
Compute a partial IPv6 mask, sized for the basic storage type.
self_type & operator<<=(raw_type n)
static constexpr auto INVALID
Marker value for an invalid mask.
Internal IP address utilities.
For template deduction guides.
MemSpan(std::array< T, N > &) -> MemSpan< T >
Deduction guides.
bool operator>(IP4Addr const &lhs, IP4Addr const &rhs)
bool operator<=(IP4Addr const &lhs, IP4Addr const &rhs)
bool operator>=(IP4Addr const &lhs, IP4Addr const &rhs)
bool operator==(IPAddr const &lhs, sockaddr const *sa)
Equality.
bool operator!=(IP4Addr const &lhs, IP4Addr const &rhs)
bool operator<(IP4Addr const &lhs, IP4Addr const &rhs)
in6_addr _in6
By networking type (but in host order!)
quad_store_type _quad
By quad.
word_store_type _store
0 is MSW, 1 is LSW.
IP4Addr _ip4
IPv4 address (host)
IP6Addr _ip6
IPv6 address (host)