LibSWOC++ 1.5.14
Solid Wall of C++
Loading...
Searching...
No Matches
IPAddr.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright Network Geographics 2014
6
7#pragma once
8
9#include <cstddef>
10
11#include "swoc/swoc_version.h"
12#include "swoc/swoc_meta.h"
13#include "swoc/MemSpan.h"
14#include "swoc/swoc_ip_util.h"
15
16namespace swoc { inline namespace SWOC_VERSION_NS {
17
18using std::string_view;
19
20union IPEndpoint;
21class IPAddr;
22class IPMask;
23
27class IP4Addr {
28 using self_type = IP4Addr;
29 friend class IP4Range;
30
31public:
32 static constexpr size_t SIZE = sizeof(in_addr_t);
33 static constexpr size_t WIDTH = std::numeric_limits<unsigned char>::digits * SIZE;
34
35 static const self_type MIN;
36 static const self_type MAX;
37 static constexpr sa_family_t AF_value = AF_INET;
38
39 constexpr IP4Addr() = default;
40
42 IP4Addr(self_type const &that) = default;
43
47 explicit constexpr IP4Addr(in_addr_t addr);
48
50 explicit IP4Addr(sockaddr_in const *s);
51
54 IP4Addr(string_view const &text);
55
57 self_type &operator=(self_type const &that) = default;
58
60 self_type &operator=(in_addr_t ip);
61
63 self_type &operator=(sockaddr_in const *sa);
64
66 self_type &operator++();
67
69 self_type &operator--();
70
78 uint8_t operator[](unsigned idx) const;
79
81 self_type &operator&=(IPMask const &mask);
82
84 self_type &operator|=(IPMask const &mask);
85
93 sockaddr *copy_to(sockaddr *sa) const;
94
100 sockaddr_in *copy_to(sockaddr_in *sin) const;
101
103 in_addr_t network_order() const;
104
106 in_addr_t host_order() const;
107
116 bool load(string_view const &text);
117
119 int cmp(self_type const &that) const;
120
124 constexpr sa_family_t family() const;
125
127 bool is_any() const;
128
130 bool is_multicast() const;
131
133 bool is_loopback() const;
134
136 bool is_link_local() const;
137
139 bool is_private() const;
140
146 self_type &operator<<=(unsigned n);
147
153 self_type &operator>>=(unsigned n);
154
162 self_type &operator&=(self_type const &that);
163
171 self_type &operator|=(self_type const &that);
172
181 constexpr static in_addr_t reorder(in_addr_t src);
182
183protected:
185 using bytes = std::array<uint8_t, 4>;
186
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 &);
191
192 in_addr_t _addr = INADDR_ANY;
193};
194
200class IP6Addr {
201 using self_type = IP6Addr;
202
203 friend class IP6Range;
204 friend class IPMask;
205
206public:
207 static constexpr size_t WIDTH = 128;
208 static constexpr size_t SIZE = WIDTH / std::numeric_limits<uint8_t>::digits;
209 static constexpr sa_family_t AF_value = AF_INET6;
210
211 using quad_type = uint16_t;
212 static constexpr size_t N_QUADS = SIZE / sizeof(quad_type);
214 static constexpr size_t QUAD_WIDTH = std::numeric_limits<uint8_t>::digits * sizeof(quad_type);
215
218 using raw_type = std::array<uint8_t, SIZE>;
219
221 static const self_type MIN;
223 static const self_type MAX;
224
225 IP6Addr() = default;
226 IP6Addr(self_type const &that) = default;
227
229 explicit IP6Addr(in6_addr const &addr);
230
232 explicit IP6Addr(sockaddr_in6 const *addr) { *this = addr; }
233
237 IP6Addr(string_view const &text);
238
243 explicit IP6Addr(IP4Addr addr);
244
246 self_type &operator=(self_type const &that) = default;
247
253 self_type &operator<<=(unsigned n);
254
260 self_type &operator>>=(unsigned n);
261
269 self_type &operator&=(self_type const &that);
270
278 self_type &operator|=(self_type const &that);
279
281 self_type &operator++();
282
284 self_type &operator--();
285
287 self_type &operator=(in6_addr const &addr);
288
290 self_type &operator=(sockaddr_in6 const *addr);
291
297 constexpr uint8_t operator[](int idx) const;
298
304 sockaddr_in6 *copy_to(sockaddr_in6 *sin6) const;
305
313 sockaddr *copy_to(sockaddr *sa) const;
314
316 in6_addr host_order() const;
317
323 in6_addr &host_order(in6_addr &dst) const;
324
326 in6_addr network_order() const;
327
333 in6_addr &network_order(in6_addr &dst) const;
334
342 bool load(string_view const &str);
343
345 int cmp(self_type const &that) const;
346
348 constexpr sa_family_t family() const;
349
351 bool is_any() const;
352
354 bool is_loopback() const;
355
357 bool is_multicast() const;
358
360 bool is_link_local() const;
361
363 bool is_private() const;
364
366 bool is_mapped_ip4() const;
367
372 self_type &clear();
373
381 self_type &operator&=(IPMask const &that);
382
390 self_type &operator|=(IPMask const &that);
391
397 static void reorder(in6_addr &dst, raw_type const &src);
398
404 static void reorder(raw_type &dst, in6_addr const &src);
405
406 template <typename T>
407 auto
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>> {
409 return swoc::MemSpan(_addr._store).template rebind<T>();
410 }
411
412 template <typename T>
413 auto
414 as_span() const
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>,
416 swoc::MemSpan<T const>> {
417 return swoc::MemSpan<uint64_t const>(_addr._store).template rebind<T const>();
418 }
419
420protected:
421 friend bool operator==(self_type const &, self_type const &);
422
423 friend bool operator!=(self_type const &, self_type const &);
424
425 friend bool operator<(self_type const &, self_type const &);
426
427 friend bool operator<=(self_type const &, self_type const &);
428
431 using quad_store_type = std::array<quad_type, N_QUADS>;
432
434 static constexpr quad_type QUAD_MASK = ~quad_type{0};
435
437 using word_type = uint64_t;
438
439 static constexpr size_t WORD_SIZE = sizeof(word_type);
440
442 static constexpr size_t WORD_WIDTH = std::numeric_limits<uint8_t>::digits * WORD_SIZE;
443
445 static constexpr word_type WORD_MASK = ~word_type(0);
446
448 static constexpr size_t N_STORE = SIZE / WORD_SIZE;
449
451 using word_store_type = std::array<word_type, N_STORE>;
452
463 static_assert(sizeof(in6_addr) == sizeof(raw_type));
464
465 static constexpr unsigned LSW = 1;
466 static constexpr unsigned MSW = 0;
467
470 static constexpr std::array<unsigned, N_QUADS> QUAD_IDX = {3, 2, 1, 0, 7, 6, 5, 4};
471
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};
475
480 static void reorder(unsigned char dst[WORD_SIZE], unsigned char const src[WORD_SIZE]);
481
487 IP6Addr(word_store_type::value_type msw, word_store_type::value_type lsw)
488 : _addr{
489 {msw, lsw}
490 } {}
491
492 friend IP6Addr operator&(IP6Addr const &addr, IPMask const &mask);
493
494 friend IP6Addr operator|(IP6Addr const &addr, IPMask const &mask);
495};
496
501class IPAddr {
502 friend class IPRange;
503
504 using self_type = IPAddr;
505public:
506 IPAddr() = default;
507 IPAddr(self_type const &that) = default;
508 self_type &operator=(self_type const &that) = default;
509
511 explicit IPAddr(in_addr_t addr);
512
514 IPAddr(IP4Addr const &addr) : _addr{addr}, _family(IP4Addr::AF_value) {}
515
517 explicit IPAddr(in6_addr const &addr);
518
520 IPAddr(IP6Addr const &addr) : _addr{addr}, _family(IP6Addr::AF_value) {}
521
523 explicit IPAddr(sockaddr const *addr);
524
526 explicit IPAddr(IPEndpoint const &addr);
527
530 explicit IPAddr(string_view const &text);
531
533 self_type &assign(sockaddr const *addr);
534
536 self_type &assign(sockaddr_in const *addr);
537
539 self_type &assign(sockaddr_in6 const *addr);
540
542 self_type &assign(in_addr_t addr);
543
545 self_type &assign(in6_addr const &addr);
546
548 self_type &operator=(IPEndpoint const &ip);
549
551 self_type &operator=(in_addr_t ip);
552
554 self_type &operator=(in6_addr const &addr);
555
556 bool operator==(self_type const &that) const;
557
558 bool operator!=(self_type const &that) const;
559
560 bool operator<(self_type const &that) const;
561
562 bool operator>(self_type const &that) const;
563
564 bool operator<=(self_type const &that) const;
565
566 bool operator>=(self_type const &that) const;
567
569 self_type &operator=(sockaddr const *addr);
570
571 self_type &operator&=(IPMask const &mask);
572
573 self_type &operator|=(IPMask const &mask);
574
580 sockaddr *copy_to(sockaddr *sa) const;
581
587 bool load(string_view const &text);
588
590 int cmp(self_type const &that) const;
591
594 bool is_same_family(self_type const &that);
595
598 sa_family_t family() const;
599
601 bool is_ip4() const;
602
604 bool is_ip6() const;
605
607 IP4Addr const &ip4() const;
608
610 explicit operator IP4Addr() const;
611
613 IP6Addr const &ip6() const;
614
616 explicit operator IP6Addr() const;
617
619 bool is_valid() const;
620
622 self_type &invalidate();
623
625 bool is_loopback() const;
626
628 bool is_multicast() const;
629
631 bool is_link_local() const;
632
634 bool is_private() const;
635
637 static self_type const INVALID;
638
639protected:
640 friend IP4Addr;
641 friend IP6Addr;
642
644 union raw_addr_type {
645 IP4Addr _ip4;
646 IP6Addr _ip6;
647
648 constexpr raw_addr_type();
649
650 raw_addr_type(in_addr_t addr) : _ip4(addr) {}
651
652 raw_addr_type(in6_addr const &addr) : _ip6(addr) {}
653
654 raw_addr_type(IP4Addr const &addr) : _ip4(addr) {}
655
656 raw_addr_type(IP6Addr const &addr) : _ip6(addr) {}
657 } _addr;
658
659 sa_family_t _family{AF_UNSPEC};
660};
661
666class IPMask {
667 using self_type = IPMask;
668
669 friend class IP4Addr;
670 friend class IP6Addr;
671
672public:
673 using raw_type = uint8_t;
674
675 IPMask() = default;
676
683 explicit IPMask(raw_type width);
684
686 bool is_valid() const;
687
693 bool load(string_view const &text);
694
699 static self_type mask_for(IPAddr const &addr);
700
705 static self_type mask_for(IP4Addr const &addr);
706
711 static self_type mask_for(IP6Addr const &addr);
712
714 self_type &clear();
715
717 raw_type width() const;
718
726 self_type &operator<<=(raw_type n);
727
735 self_type &operator>>=(raw_type n);
736
743 IP4Addr as_ip4() const;
744
751 IP6Addr as_ip6() const;
752
753protected:
755 static constexpr auto INVALID = std::numeric_limits<raw_type>::max();
756
758
761};
762
763// --- Implementation
764
765inline constexpr IP4Addr::IP4Addr(in_addr_t addr) : _addr(addr) {}
766
767inline IP4Addr::IP4Addr(string_view const &text) {
768 if (!this->load(text)) {
769 _addr = INADDR_ANY;
770 }
771}
772
773inline constexpr sa_family_t
775 return AF_value;
776}
777
778inline auto
779IP4Addr::operator<<=(unsigned n) -> self_type & {
780 _addr <<= n;
781 return *this;
782}
783
784inline auto
785IP4Addr::operator>>=(unsigned n) -> self_type & {
786 _addr >>= n;
787 return *this;
788}
789
790inline auto
791IP4Addr::operator&=(self_type const &that) -> self_type & {
792 _addr &= that._addr;
793 return *this;
794}
795
796inline auto
797IP4Addr::operator|=(self_type const &that) -> self_type & {
798 _addr |= that._addr;
799 return *this;
800}
801
802inline auto
803IP4Addr::operator++() -> self_type & {
804 ++_addr;
805 return *this;
806}
807
808inline auto
809IP4Addr::operator--() -> self_type & {
810 --_addr;
811 return *this;
812}
813
814inline in_addr_t
816 return htonl(_addr);
817}
818
819inline in_addr_t
821 return _addr;
822}
823
824inline auto
825IP4Addr::operator=(in_addr_t ip) -> self_type & {
826 _addr = ntohl(ip);
827 return *this;
828}
829
830inline sockaddr *
831IP4Addr::copy_to(sockaddr *sa) const {
832 this->copy_to(reinterpret_cast<sockaddr_in *>(sa));
833 return sa;
834}
835
837
838inline bool
839operator==(IP4Addr const &lhs, IP4Addr const &rhs) {
840 return lhs._addr == rhs._addr;
841}
842
844inline bool
845operator!=(IP4Addr const &lhs, IP4Addr const &rhs) {
846 return lhs._addr != rhs._addr;
847}
848
850inline bool
851operator<(IP4Addr const &lhs, IP4Addr const &rhs) {
852 return lhs._addr < rhs._addr;
853}
854
856inline bool
857operator<=(IP4Addr const &lhs, IP4Addr const &rhs) {
858 return lhs._addr <= rhs._addr;
859}
860
862inline bool
863operator>(IP4Addr const &lhs, IP4Addr const &rhs) {
864 return rhs < lhs;
865}
866
868inline bool
869operator>=(IP4Addr const &lhs, IP4Addr const &rhs) {
870 return rhs <= lhs;
871}
872
873inline IP4Addr &
875 _addr &= mask.as_ip4()._addr;
876 return *this;
877}
878
879inline IP4Addr &
881 _addr |= ~(mask.as_ip4()._addr);
882 return *this;
883}
884
885inline bool
887 return _addr == INADDR_ANY;
888}
889
890inline bool
892 return (*this)[0] == IN_LOOPBACKNET;
893}
894
895inline bool
897 return IN_MULTICAST(_addr);
898}
899
900inline bool
902 return ip::is_link_local_host_order(_addr);
903}
904
905inline bool
907 return ip::is_private_host_order(_addr);
908}
909
910inline uint8_t
911IP4Addr::operator[](unsigned int idx) const {
912 return reinterpret_cast<bytes const &>(_addr)[3 - idx];
913}
914
915inline int
916IP4Addr::cmp(IP4Addr::self_type const &that) const {
917 return _addr < that._addr ? -1 : _addr > that._addr ? 1 : 0;
918}
919
920constexpr in_addr_t
921IP4Addr::reorder(in_addr_t src) {
922 return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 0xFF) << 8) | ((src >> 24) & 0xFF);
923}
924
925// +++ IP6Addr +++
926
927inline constexpr sa_family_t
929 return AF_value;
930}
931
932inline IP6Addr::IP6Addr(in6_addr const &addr) {
933 *this = addr;
934}
935
936inline IP6Addr::IP6Addr(string_view const &text) {
937 if (!this->load(text)) {
938 this->clear();
939 }
940}
941
943 _addr._store[MSW] = 0;
944 _addr._quad[QUAD_IDX[4]] = 0;
945 _addr._quad[QUAD_IDX[5]] = 0xffff;
946 _addr._quad[QUAD_IDX[6]] = addr.host_order() >> QUAD_WIDTH;
947 _addr._quad[QUAD_IDX[7]] = addr.host_order();
948}
949
950inline bool
952 return _addr._store[MSW] == 0 && _addr._store[LSW] == 1;
953}
954
955inline bool
957 return _addr._raw[RAW_IDX[0]] == 0xFF;
958}
959
960inline bool
962 return _addr._store[MSW] == 0 && _addr._store[LSW] == 0;
963}
964
965inline bool
967 return 0 == _addr._store[MSW] && (_addr._quad[QUAD_IDX[4]] == 0 && _addr._quad[QUAD_IDX[5]] == 0xFFFF);
968}
969
970inline bool
972 return _addr._raw[RAW_IDX[0]] == 0xFE && (_addr._raw[RAW_IDX[1]] & 0xC0) == 0x80; // fe80::/10
973}
974
975inline bool
977 return (_addr._raw[RAW_IDX[0]] & 0xFE) == 0xFC; // fc00::/7
978}
979
980inline in6_addr
982 Addr zret{
983 {_addr._store[LSW], _addr._store[MSW]}
984 };
985 return zret._in6;
986}
987
988inline in6_addr &
989IP6Addr::host_order(in6_addr &dst) const {
990 Addr *addr = reinterpret_cast<Addr *>(&dst);
991 addr->_store[0] = _addr._store[LSW];
992 addr->_store[1] = _addr._store[MSW];
993 return dst;
994}
995
996inline in6_addr
998 in6_addr zret;
999 return this->network_order(zret);
1000}
1001
1002inline in6_addr &
1003IP6Addr::network_order(in6_addr &dst) const {
1004 self_type::reorder(dst, _addr._raw);
1005 return dst;
1006}
1007
1008inline auto
1009IP6Addr::clear() -> self_type & {
1010 _addr._store[MSW] = _addr._store[LSW] = 0;
1011 return *this;
1012}
1013
1014inline auto
1015IP6Addr::operator=(in6_addr const &addr) -> self_type & {
1016 self_type::reorder(_addr._raw, addr);
1017 return *this;
1018}
1019
1020inline auto
1021IP6Addr::operator=(sockaddr_in6 const *addr) -> self_type & {
1022 if (addr) {
1023 *this = addr->sin6_addr;
1024 } else {
1025 this->clear();
1026 }
1027 return *this;
1028}
1029
1030inline auto
1031IP6Addr::operator++() -> self_type & {
1032 if (++(_addr._store[LSW]) == 0) {
1033 ++(_addr._store[MSW]);
1034 }
1035 return *this;
1036}
1037
1038inline auto
1039IP6Addr::operator--() -> self_type & {
1040 if (--(_addr._store[LSW]) == ~static_cast<uint64_t>(0)) {
1041 --(_addr._store[MSW]);
1042 }
1043 return *this;
1044}
1045
1046inline void
1047IP6Addr::reorder(unsigned char dst[WORD_SIZE], unsigned char const src[WORD_SIZE]) {
1048 for (size_t idx = 0; idx < WORD_SIZE; ++idx) {
1049 dst[idx] = src[WORD_SIZE - (idx + 1)];
1050 }
1051}
1052
1054inline bool
1055operator==(IP6Addr const &lhs, IP6Addr const &rhs) {
1056 return lhs._addr._store[IP6Addr::MSW] == rhs._addr._store[IP6Addr::MSW] &&
1057 lhs._addr._store[IP6Addr::LSW] == rhs._addr._store[IP6Addr::LSW];
1058}
1059
1061inline bool
1062operator!=(IP6Addr const &lhs, IP6Addr const &rhs) {
1063 return lhs._addr._store[IP6Addr::MSW] != rhs._addr._store[IP6Addr::MSW] ||
1064 lhs._addr._store[IP6Addr::LSW] != rhs._addr._store[IP6Addr::LSW];
1065}
1066
1068inline bool
1069operator<(IP6Addr const &lhs, IP6Addr const &rhs) {
1070 return lhs._addr._store[IP6Addr::MSW] < rhs._addr._store[IP6Addr::MSW] ||
1071 (lhs._addr._store[IP6Addr::MSW] == rhs._addr._store[IP6Addr::MSW] &&
1072 lhs._addr._store[IP6Addr::LSW] < rhs._addr._store[IP6Addr::LSW]);
1073}
1074
1076inline bool
1077operator>(IP6Addr const &lhs, IP6Addr const &rhs) {
1078 return rhs < lhs;
1079}
1080
1082inline bool
1083operator<=(IP6Addr const &lhs, IP6Addr const &rhs) {
1084 return lhs._addr._store[IP6Addr::MSW] < rhs._addr._store[IP6Addr::MSW] ||
1085 (lhs._addr._store[IP6Addr::MSW] == rhs._addr._store[IP6Addr::MSW] &&
1086 lhs._addr._store[IP6Addr::LSW] <= rhs._addr._store[IP6Addr::LSW]);
1087}
1088
1090inline bool
1091operator>=(IP6Addr const &lhs, IP6Addr const &rhs) {
1092 return rhs <= lhs;
1093}
1094
1095inline sockaddr *
1096IP6Addr::copy_to(sockaddr *sa) const {
1097 this->copy_to(reinterpret_cast<sockaddr_in6 *>(sa));
1098 return sa;
1099}
1100
1101inline auto
1102IP6Addr::operator&=(IPMask const &mask) -> self_type & {
1103 if (mask._cidr <= WORD_WIDTH) {
1104 _addr._store[LSW] = 0;
1105 if (0 == mask._cidr) {
1106 _addr._store[MSW] = 0;
1107 } else if (mask._cidr < WORD_WIDTH) {
1108 _addr._store[MSW] &= (WORD_MASK << (WORD_WIDTH - mask._cidr));
1109 }
1110 } else if (mask._cidr < WIDTH) {
1111 _addr._store[LSW] &= (WORD_MASK << (2 * WORD_WIDTH - mask._cidr));
1112 }
1113 return *this;
1114}
1115
1116inline auto
1117IP6Addr::operator|=(IPMask const &mask) -> self_type & {
1118 if (mask._cidr > WORD_WIDTH) {
1119 if (mask._cidr < WIDTH) {
1120 _addr._store[LSW] |= (WORD_MASK >> (mask._cidr - WORD_WIDTH));
1121 }
1122 } else {
1123 _addr._store[LSW] = WORD_MASK;
1124 if (0 == mask._cidr) {
1125 _addr._store[MSW] = WORD_MASK;
1126 } else if (mask._cidr < WORD_WIDTH) {
1127 _addr._store[MSW] |= (WORD_MASK >> mask._cidr);
1128 }
1129 }
1130 return *this;
1131}
1132
1133// +++ IPMask +++
1134
1136
1137inline bool
1139 return _cidr < INVALID;
1140}
1141
1142inline auto
1144 return _cidr;
1145}
1146
1147inline bool
1148operator==(IPMask const &lhs, IPMask const &rhs) {
1149 return lhs.width() == rhs.width();
1150}
1151
1152inline bool
1153operator!=(IPMask const &lhs, IPMask const &rhs) {
1154 return lhs.width() != rhs.width();
1155}
1156
1157inline bool
1158operator<(IPMask const &lhs, IPMask const &rhs) {
1159 return lhs.width() < rhs.width();
1160}
1161
1162inline IP4Addr
1164 static constexpr auto MASK = ~in_addr_t{0};
1165 in_addr_t addr = MASK;
1166 if (0 == _cidr) {
1167 addr = in_addr_t(0);
1168 } else if (_cidr < IP4Addr::WIDTH) {
1169 addr <<= IP4Addr::WIDTH - _cidr;
1170 }
1171 return IP4Addr{addr};
1172}
1173
1174inline auto
1175IPMask::clear() -> self_type & {
1176 _cidr = INVALID;
1177 return *this;
1178}
1179
1180inline auto
1181IPMask::operator<<=(raw_type n) -> self_type & {
1182 _cidr -= n;
1183 return *this;
1184}
1185
1186inline auto
1188 _cidr += n;
1189 return *this;
1190}
1191
1192// +++ mixed mask operators +++
1193
1194inline IP4Addr
1195operator&(IP4Addr const &addr, IPMask const &mask) {
1196 return IP4Addr{addr} &= mask;
1197}
1198
1199inline IP4Addr
1200operator|(IP4Addr const &addr, IPMask const &mask) {
1201 return IP4Addr{addr} |= mask;
1202}
1203
1204inline IP6Addr
1205operator&(IP6Addr const &addr, IPMask const &mask) {
1206 return IP6Addr{addr} &= mask;
1207}
1208
1209inline IP6Addr
1210operator|(IP6Addr const &addr, IPMask const &mask) {
1211 return IP6Addr{addr} |= mask;
1212}
1213
1214constexpr uint8_t
1215IP6Addr::operator[](int idx) const {
1216 return _addr._raw[RAW_IDX[idx]];
1217}
1218
1219inline IPAddr
1220operator&(IPAddr const &addr, IPMask const &mask) {
1221 return IPAddr{addr} &= mask;
1222}
1223
1224inline IPAddr
1225operator|(IPAddr const &addr, IPMask const &mask) {
1226 return IPAddr{addr} |= mask;
1227}
1228
1229// @c constexpr constructor is required to initialize _something_, it can't be completely uninitializing.
1230inline constexpr IPAddr::raw_addr_type::raw_addr_type() : _ip4(INADDR_ANY) {}
1231
1232inline IPAddr::IPAddr(in_addr_t addr) : _addr(addr), _family(IP4Addr::AF_value) {}
1233
1234inline IPAddr::IPAddr(in6_addr const &addr) : _addr(addr), _family(IP6Addr::AF_value) {}
1235
1236inline IPAddr::IPAddr(sockaddr const *addr) {
1237 this->assign(addr);
1238}
1239
1240inline IPAddr::IPAddr(string_view const &text) {
1241 this->load(text);
1242}
1243
1244inline IPAddr &
1245IPAddr::operator=(in_addr_t addr) {
1246 _family = AF_INET;
1247 _addr._ip4 = addr;
1248 return *this;
1249}
1250
1251inline IPAddr &
1252IPAddr::operator=(in6_addr const &addr) {
1253 _family = AF_INET6;
1254 _addr._ip6 = addr;
1255 return *this;
1256}
1257
1258inline IPAddr &
1259IPAddr::operator=(sockaddr const *addr) {
1260 return this->assign(addr);
1261}
1262
1263inline sa_family_t
1265 return _family;
1266}
1267
1268inline bool
1270 return AF_INET == _family;
1271}
1272
1273inline bool
1275 return AF_INET6 == _family;
1276}
1277
1278inline bool
1279IPAddr::is_same_family(self_type const &that) {
1280 return this->is_valid() && _family == that._family;
1281}
1282
1283inline bool
1285 return (AF_INET == _family && _addr._ip4.is_loopback()) || (AF_INET6 == _family && _addr._ip6.is_loopback());
1286}
1287
1288inline bool
1290 return this->is_ip4() ? this->ip4().is_link_local() : this->is_ip6() ? this->ip6().is_link_local() : false;
1291}
1292
1293inline bool
1295 return this->is_ip4() ? this->ip4().is_private() : this->is_ip6() ? this->ip6().is_private() : false;
1296}
1297
1298inline IPAddr &
1299IPAddr::assign(in_addr_t addr) {
1300 _family = AF_INET;
1301 _addr._ip4 = addr;
1302 return *this;
1303}
1304
1305inline IPAddr &
1306IPAddr::assign(in6_addr const &addr) {
1307 _family = AF_INET6;
1308 _addr._ip6 = addr;
1309 return *this;
1310}
1311
1312inline IPAddr &
1313IPAddr::assign(sockaddr_in const *addr) {
1314 if (addr) {
1315 _family = AF_INET;
1316 _addr._ip4 = addr;
1317 } else {
1318 _family = AF_UNSPEC;
1319 }
1320 return *this;
1321}
1322
1323inline IPAddr &
1324IPAddr::assign(sockaddr_in6 const *addr) {
1325 if (addr) {
1326 _family = AF_INET6;
1327 _addr._ip6 = addr->sin6_addr;
1328 } else {
1329 _family = AF_UNSPEC;
1330 }
1331 return *this;
1332}
1333
1334inline bool
1336 return _family == AF_INET || _family == AF_INET6;
1337}
1338
1339inline IPAddr &
1341 _family = AF_UNSPEC;
1342 return *this;
1343}
1344
1345// Associated operators.
1346
1348bool operator==(IPAddr const &lhs, sockaddr const *rhs);
1349
1351inline bool
1352operator==(sockaddr const *lhs, IPAddr const &rhs) {
1353 return rhs == lhs;
1354}
1355
1357inline bool
1358operator!=(IPAddr const &lhs, sockaddr const *rhs) {
1359 return !(lhs == rhs);
1360}
1361
1363inline bool
1364operator!=(sockaddr const *lhs, IPAddr const &rhs) {
1365 return !(rhs == lhs);
1366}
1367
1368inline IP4Addr const &
1370 return _addr._ip4;
1371}
1372inline IPAddr::operator IP4Addr() const {
1373 return _addr._ip4;
1374}
1375
1376inline IP6Addr const &
1378 return _addr._ip6;
1379}
1380inline IPAddr::operator IP6Addr() const {
1381 return _addr._ip6;
1382}
1383
1384inline bool
1385IPAddr::operator==(self_type const &that) const {
1386 return _family == that.family() &&
1387 (
1388 ( this->is_ip4() && _addr._ip4 == that._addr._ip4 ) ||
1389 ( this->is_ip6() && _addr._ip6 == that._addr._ip6 ) ||
1390 _family == AF_UNSPEC
1391 );
1392}
1393
1394inline bool
1395IPAddr::operator!=(self_type const &that) const {
1396 return !(*this == that);
1397}
1398
1399inline bool
1400IPAddr::operator>(self_type const &that) const {
1401 return that < *this;
1402}
1403
1404inline bool
1405IPAddr::operator<=(self_type const &that) const {
1406 return !(that < *this);
1407}
1408
1409inline bool
1410IPAddr::operator>=(self_type const &that) const {
1411 return !(*this < that);
1412}
1413
1414// Disambiguating between comparisons and implicit conversions.
1415
1416inline bool
1417operator==(IPAddr const &lhs, IP4Addr const &rhs) {
1418 return lhs.is_ip4() && lhs.ip4() == rhs;
1419}
1420
1421inline bool
1422operator!=(IPAddr const &lhs, IP4Addr const &rhs) {
1423 return !lhs.is_ip4() || lhs.ip4() != rhs;
1424}
1425
1426inline bool
1427operator==(IP4Addr const &lhs, IPAddr const &rhs) {
1428 return rhs.is_ip4() && lhs == rhs.ip4();
1429}
1430
1431inline bool
1432operator!=(IP4Addr const &lhs, IPAddr const &rhs) {
1433 return !rhs.is_ip4() || lhs != rhs.ip4();
1434}
1435
1436inline bool
1437operator==(IPAddr const &lhs, IP6Addr const &rhs) {
1438 return lhs.is_ip6() && lhs.ip6() == rhs;
1439}
1440
1441inline bool
1442operator!=(IPAddr const &lhs, IP6Addr const &rhs) {
1443 return !lhs.is_ip6() || lhs.ip6() != rhs;
1444}
1445
1446inline bool
1447operator==(IP6Addr const &lhs, IPAddr const &rhs) {
1448 return rhs.is_ip6() && lhs == rhs.ip6();
1449}
1450
1451inline bool
1452operator!=(IP6Addr const &lhs, IPAddr const &rhs) {
1453 return !rhs.is_ip6() || lhs != rhs.ip6();
1454}
1455}} // namespace swoc::SWOC_VERSION_NS
1456
1457namespace std {
1458
1460template <> struct hash<swoc::IP4Addr> {
1461 size_t
1462 operator()(swoc::IP4Addr const &addr) const {
1463 return addr.network_order();
1464 }
1465};
1466
1468template <> struct hash<swoc::IP6Addr> {
1469 size_t
1470 operator()(swoc::IP6Addr const &addr) const {
1471 // XOR the 64 chunks
1472 auto words = addr.as_span<uint64_t>();
1473 return words[0] ^ words[1];
1474 }
1475};
1476
1478template <> struct hash<swoc::IPAddr> {
1479 size_t
1480 operator()(swoc::IPAddr const &addr) const {
1481 return addr.is_ip4() ? hash<swoc::IP4Addr>()(addr.ip4()) : addr.is_ip6() ? hash<swoc::IP6Addr>()(addr.ip6()) : 0;
1482 }
1483};
1484
1485} // namespace std
bool is_multicast() const
Definition IPAddr.h:896
static constexpr in_addr_t reorder(in_addr_t src)
Definition IPAddr.h:921
self_type & operator>>=(unsigned n)
Definition IPAddr.h:785
int cmp(self_type const &that) const
Standard ternary compare.
Definition IPAddr.h:916
bool is_loopback() const
Definition IPAddr.h:891
uint8_t operator[](unsigned idx) const
Definition IPAddr.h:911
std::array< uint8_t, 4 > bytes
Access by bytes.
Definition IPAddr.h:185
friend bool operator==(self_type const &, self_type const &)
Equality.
Definition IPAddr.h:839
self_type & operator++()
Increment address.
Definition IPAddr.h:803
self_type & operator&=(IPMask const &mask)
Apply mask to address, leaving the network portion.
Definition IPAddr.h:874
friend bool operator<(self_type const &, self_type const &)
Definition IPAddr.h:851
friend bool operator!=(self_type const &, self_type const &)
Definition IPAddr.h:845
in_addr_t network_order() const
Definition IPAddr.h:815
in_addr_t host_order() const
Definition IPAddr.h:820
self_type & operator|=(IPMask const &mask)
Apply mask to address, creating the broadcast address.
Definition IPAddr.h:880
static const self_type MIN
Minimum value.
Definition IPAddr.h:35
static constexpr size_t SIZE
Size of IPv4 address in bytes.
Definition IPAddr.h:32
constexpr sa_family_t family() const
Definition IPAddr.h:774
static constexpr size_t WIDTH
Definition IPAddr.h:33
sockaddr * copy_to(sockaddr *sa) const
Definition IPAddr.h:831
IP4Addr(self_type const &that)=default
Copy constructor.
friend bool operator<=(self_type const &, self_type const &)
Definition IPAddr.h:857
in_addr_t _addr
Address in host order.
Definition IPAddr.h:192
self_type & operator--()
Decrement address.
Definition IPAddr.h:809
static const self_type MAX
Maximum value.
Definition IPAddr.h:36
bool is_any() const
Definition IPAddr.h:886
self_type & operator=(self_type const &that)=default
Self assignment.
bool is_private() const
Definition IPAddr.h:906
bool load(string_view const &text)
Definition swoc_ip.cc:299
self_type & operator<<=(unsigned n)
Definition IPAddr.h:779
constexpr IP4Addr()=default
Default constructor - ANY address.
bool is_link_local() const
Definition IPAddr.h:901
static constexpr sa_family_t AF_value
Address family type.
Definition IPAddr.h:37
self_type & operator=(self_type const &that)=default
Self assignment.
static void reorder(in6_addr &dst, raw_type const &src)
Definition swoc_ip.cc:502
int cmp(self_type const &that) const
Generic three value compare.
Definition swoc_ip.cc:369
self_type & operator++()
Increment address.
Definition IPAddr.h:1031
static constexpr word_type WORD_MASK
Mask the size of a word.
Definition IPAddr.h:445
uint16_t quad_type
Size of one segment of an IPv6 address.
Definition IPAddr.h:211
self_type & operator<<=(unsigned n)
Definition swoc_ip.cc:374
static constexpr unsigned MSW
Most significant word index.
Definition IPAddr.h:466
static const self_type MIN
Minimum value of an address.
Definition IPAddr.h:221
static constexpr size_t QUAD_WIDTH
Number of bits per quad.
Definition IPAddr.h:214
static constexpr quad_type QUAD_MASK
A bit mask of all 1 bits the size of a quad.
Definition IPAddr.h:434
in6_addr host_order() const
Return the address in host order.
Definition IPAddr.h:981
self_type & operator>>=(unsigned n)
Definition swoc_ip.cc:389
uint64_t word_type
Type used as a "word", the natural working unit of the address.
Definition IPAddr.h:437
bool load(string_view const &str)
Definition swoc_ip.cc:418
std::array< word_type, N_STORE > word_store_type
Type used to store the address.
Definition IPAddr.h:451
static const self_type MAX
Maximum value of an address.
Definition IPAddr.h:223
static constexpr std::array< unsigned, N_QUADS > QUAD_IDX
Definition IPAddr.h:470
bool is_private() const
Definition IPAddr.h:976
static constexpr unsigned LSW
Least significant word index.
Definition IPAddr.h:465
self_type & operator--()
Decrement address.
Definition IPAddr.h:1039
static constexpr size_t N_QUADS
Definition IPAddr.h:212
in6_addr network_order() const
Return the address in network order.
Definition IPAddr.h:997
self_type & operator|=(self_type const &that)
Definition swoc_ip.cc:411
bool is_loopback() const
Definition IPAddr.h:951
bool is_any() const
Definition IPAddr.h:961
constexpr uint8_t operator[](int idx) const
Definition IPAddr.h:1215
std::array< quad_type, N_QUADS > quad_store_type
Definition IPAddr.h:431
constexpr sa_family_t family() const
Definition IPAddr.h:928
static constexpr std::array< unsigned, SIZE > RAW_IDX
Definition IPAddr.h:474
sockaddr_in6 * copy_to(sockaddr_in6 *sin6) const
Definition swoc_ip.cc:361
static constexpr size_t WIDTH
Number of bits in the address.
Definition IPAddr.h:207
IP6Addr(sockaddr_in6 const *addr)
Construct from sockaddr_in.
Definition IPAddr.h:232
std::array< uint8_t, SIZE > raw_type
Definition IPAddr.h:218
self_type & operator&=(self_type const &that)
Definition swoc_ip.cc:404
self_type & clear()
Definition IPAddr.h:1009
IP6Addr()=default
Default constructor - ANY address.
static constexpr size_t SIZE
Size of address in bytes.
Definition IPAddr.h:208
bool is_link_local() const
Definition IPAddr.h:971
IP6Addr(word_store_type::value_type msw, word_store_type::value_type lsw)
Definition IPAddr.h:487
static constexpr size_t WORD_WIDTH
Number of bits per word.
Definition IPAddr.h:442
bool is_multicast() const
Definition IPAddr.h:956
static constexpr sa_family_t AF_value
Address family type.
Definition IPAddr.h:209
bool is_mapped_ip4() const
Definition IPAddr.h:966
static constexpr size_t N_STORE
Number of words used for basic address storage.
Definition IPAddr.h:448
IPAddr(IP6Addr const &addr)
construct using an IPv6 addr
Definition IPAddr.h:520
self_type & invalidate()
Make invalid.
Definition IPAddr.h:1340
self_type & operator=(self_type const &that)=default
Copy assignment.
bool is_valid() const
Test for validity.
Definition IPAddr.h:1335
bool is_loopback() const
Test for loopback.
Definition IPAddr.h:1284
IPAddr(self_type const &that)=default
Copy constructor.
bool is_ip6() const
Test for IPv6.
Definition IPAddr.h:1274
bool is_multicast() const
Test for multicast.
Definition swoc_ip.cc:646
bool is_ip4() const
Test for IPv4.
Definition IPAddr.h:1269
bool is_private() const
Pre-constructed invalid instance.
Definition IPAddr.h:1294
IPAddr()=default
Default constructor - invalid result.
int cmp(self_type const &that) const
Generic compare.
Definition swoc_ip.cc:602
bool is_same_family(self_type const &that)
Definition IPAddr.h:1279
IP6Addr const & ip6() const
Definition IPAddr.h:1377
sockaddr * copy_to(sockaddr *sa) const
Definition swoc_ip.cc:523
IPAddr(IP4Addr const &addr)
Construct using an IPv4 addr.
Definition IPAddr.h:514
bool is_link_local() const
Definition IPAddr.h:1289
bool load(string_view const &text)
Definition swoc_ip.cc:533
IP4Addr const & ip4() const
Definition IPAddr.h:1369
sa_family_t _family
Protocol family.
Definition IPAddr.h:659
self_type & assign(sockaddr const *addr)
Set to the address in addr.
Definition swoc_ip.cc:562
sa_family_t family() const
Definition IPAddr.h:1264
bool load(string_view const &text)
Definition swoc_ip.cc:663
uint8_t raw_type
Storage for mask width.
Definition IPAddr.h:673
raw_type _cidr
Mask width in bits.
Definition IPAddr.h:757
IPMask()=default
Default construct to invalid mask.
IP6Addr as_ip6() const
Definition swoc_ip.cc:724
self_type & operator>>=(raw_type n)
Definition IPAddr.h:1187
self_type & clear()
Change to default constructed state (invalid).
Definition IPAddr.h:1175
bool is_valid() const
Definition IPAddr.h:1138
raw_type width() const
The width of the mask.
Definition IPAddr.h:1143
IP4Addr as_ip4() const
Definition IPAddr.h:1163
static self_type mask_for(IPAddr const &addr)
Definition swoc_ip.cc:674
static raw_type mask_for_quad(IP6Addr::quad_type q)
Compute a partial IPv6 mask, sized for the basic storage type.
Definition swoc_ip.cc:684
self_type & operator<<=(raw_type n)
Definition IPAddr.h:1181
static constexpr auto INVALID
Marker value for an invalid mask.
Definition IPAddr.h:755
STL namespace.
Internal IP address utilities.
For template deduction guides.
Definition ArenaWriter.cc:9
MemSpan(std::array< T, N > &) -> MemSpan< T >
Deduction guides.
bool operator>(IP4Addr const &lhs, IP4Addr const &rhs)
Definition IPAddr.h:863
bool operator<=(IP4Addr const &lhs, IP4Addr const &rhs)
Definition IPAddr.h:857
bool operator>=(IP4Addr const &lhs, IP4Addr const &rhs)
Definition IPAddr.h:869
bool operator==(IPAddr const &lhs, sockaddr const *sa)
Equality.
Definition swoc_ip.cc:650
bool operator!=(IP4Addr const &lhs, IP4Addr const &rhs)
Definition IPAddr.h:845
bool operator<(IP4Addr const &lhs, IP4Addr const &rhs)
Definition IPAddr.h:851
in6_addr _in6
By networking type (but in host order!)
Definition IPAddr.h:461
raw_type _raw
By byte.
Definition IPAddr.h:460
quad_store_type _quad
By quad.
Definition IPAddr.h:459
word_store_type _store
0 is MSW, 1 is LSW.
Definition IPAddr.h:458
IP4Addr _ip4
IPv4 address (host)
Definition IPAddr.h:645
IP6Addr _ip6
IPv6 address (host)
Definition IPAddr.h:646