42 result->append(addr.str());
45 result->
append(addr.str());
57 return addr.asV6().createIPv4();
62 IPAddressV6 IPAddress::createIPv6(
const IPAddress& addr) {
66 return addr.asV4().createIPv6();
71 vector<string> splitIpSlashCidr(
StringPiece ipSlashCidr) {
73 split(
"/", ipSlashCidr, vec);
79 CIDRNetwork IPAddress::createNetwork(
84 IPAddress::tryCreateNetwork(ipSlashCidr, defaultCidr, applyMask);
91 throw std::range_error(
"defaultCidr must be <= UINT8_MAX");
96 "Invalid ipSlashCidr specified. Expected IP/CIDR format, got '{}'",
102 auto const vec = splitIpSlashCidr(ipSlashCidr);
104 switch (ret.error()) {
106 CHECK_GE(
vec.size(), 1);
110 CHECK_GE(
vec.size(), 2);
111 throw IPAddressFormatException(
112 sformat(
"Mask value '{}' not a valid mask",
vec.at(1)));
114 auto const subnet = IPAddress::tryFromString(
vec.at(0)).
value();
115 auto cidr =
static_cast<uint8_t>(
116 (defaultCidr > -1) ? defaultCidr : (subnet.isV4() ? 32 : 128));
118 throw IPAddressFormatException(
sformat(
119 "CIDR value '{}' is > network bit count '{}'",
120 vec.size() == 2 ?
vec.at(1) : to<string>(cidr),
130 return CIDRNetwork{};
142 auto const vec = splitIpSlashCidr(ipSlashCidr);
143 auto const elemCount =
vec.size();
145 if (elemCount == 0 ||
150 auto const subnet = IPAddress::tryFromString(
vec.at(0));
151 if (subnet.hasError()) {
155 auto cidr =
static_cast<uint8_t>(
156 (defaultCidr > -1) ? defaultCidr : (subnet.value().isV4() ? 32 : 128));
158 if (elemCount == 2) {
159 auto const maybeCidr = tryTo<uint8_t>(
vec.at(1));
160 if (maybeCidr.hasError()) {
163 cidr = maybeCidr.value();
166 if (cidr > subnet.value().bitCount()) {
170 return std::make_pair(
171 applyMask ? subnet.value().mask(cidr) : subnet.value(), cidr);
175 std::string IPAddress::networkToString(
const CIDRNetwork& network) {
176 return sformat(
"{}/{}", network.first.str(), network.second);
180 IPAddress IPAddress::fromBinary(
ByteRange bytes) {
181 if (bytes.
size() == 4) {
183 }
else if (bytes.
size() == 16) {
188 sformat(
"Invalid address with hex value '{}'", hexval));
195 if (bytes.
size() == 16) {
197 }
else if (bytes.
size() == 4) {
205 IPAddress IPAddress::fromLong(
uint32_t src) {
208 IPAddress IPAddress::fromLongHBO(
uint32_t src) {
213 IPAddress::IPAddress() : addr_(), family_(AF_UNSPEC) {}
216 IPAddress::IPAddress(
StringPiece str) : addr_(), family_(AF_UNSPEC) {
217 auto maybeIp = tryFromString(str);
218 if (maybeIp.hasError()) {
220 to<std::string>(
"Invalid IP address '", str,
"'"));
229 if (str.
find(
':') != string::npos) {
231 }
else if (str.
find(
'.') != string::npos) {
239 IPAddress::IPAddress(
const sockaddr* addr) : addr_(), family_(AF_UNSPEC) {
240 if (addr ==
nullptr) {
243 family_ = addr->sa_family;
244 switch (addr->sa_family) {
246 const sockaddr_in* v4addr =
reinterpret_cast<const sockaddr_in*
>(
addr);
251 const sockaddr_in6* v6addr =
reinterpret_cast<const sockaddr_in6*
>(
addr);
262 : addr_(ipV4Addr), family_(AF_INET) {}
265 IPAddress::IPAddress(
const in_addr ipV4Addr)
noexcept 266 : addr_(
IPAddressV4(ipV4Addr)), family_(AF_INET) {}
270 : addr_(ipV6Addr), family_(AF_INET6) {}
273 IPAddress::IPAddress(
const in6_addr& ipV6Addr)
noexcept 274 : addr_(
IPAddressV6(ipV6Addr)), family_(AF_INET6) {}
278 addr_ = IPAddressV46(ipv4_addr);
285 addr_ = IPAddressV46(ipv6_addr);
291 bool IPAddress::inSubnet(
StringPiece cidrNetwork)
const {
292 auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
293 return inSubnet(subnetInfo.first, subnetInfo.second);
297 bool IPAddress::inSubnet(
const IPAddress& subnet,
uint8_t cidr)
const {
298 if (bitCount() == subnet.bitCount()) {
300 return asV4().inSubnet(subnet.asV4(), cidr);
302 return asV6().inSubnet(subnet.asV6(), cidr);
313 }
else if (subnet.isV6()) {
324 bool IPAddress::inSubnetWithMask(
const IPAddress& subnet,
ByteRange mask)
328 std::memcpy(ba.data(), mask.
begin(), std::min<size_t>(mask.
size(), 4));
332 if (bitCount() == subnet.bitCount()) {
334 return asV4().inSubnetWithMask(subnet.asV4(), mkByteArray4());
337 std::memcpy(ba.data(), mask.
begin(), std::min<size_t>(mask.
size(), 16));
338 return asV6().inSubnetWithMask(subnet.asV6(), ba);
350 }
else if (subnet.isV6()) {
360 uint8_t IPAddress::getNthMSByte(
size_t byteIndex)
const {
361 const auto highestIndex = byteCount() - 1;
362 if (byteIndex > highestIndex) {
363 throw std::invalid_argument(
sformat(
364 "Byte index must be <= {} for addresses of type: {}",
369 return asV4().bytes()[byteIndex];
371 return asV6().bytes()[byteIndex];
375 bool operator==(
const IPAddress& addr1,
const IPAddress& addr2) {
376 if (addr1.family() == addr2.family()) {
378 return (addr1.asV6() == addr2.asV6());
379 }
else if (addr1.isV4()) {
380 return (addr1.asV4() == addr2.asV4());
382 CHECK_EQ(addr1.family(), AF_UNSPEC);
390 if (addr1.isIPv4Mapped() && addr2.isV4()) {
391 if (IPAddress::createIPv4(addr1) == addr2.asV4()) {
396 if (addr2.isIPv4Mapped() && addr1.isV4()) {
397 if (IPAddress::createIPv4(addr2) == addr1.asV4()) {
405 bool operator<(
const IPAddress& addr1,
const IPAddress& addr2) {
406 if (addr1.family() == addr2.family()) {
408 return (addr1.asV6() < addr2.asV6());
409 }
else if (addr1.isV4()) {
410 return (addr1.asV4() < addr2.asV4());
412 CHECK_EQ(addr1.family(), AF_UNSPEC);
421 return addr1.asV6() < addr2.asV4().createIPv6();
425 return addr1.asV4().createIPv6() < addr2.asV6();
430 CIDRNetwork IPAddress::longestCommonPrefix(
431 const CIDRNetwork& one,
432 const CIDRNetwork& two) {
433 if (one.first.family() != two.first.family()) {
434 throw std::invalid_argument(
sformat(
435 "Can't compute longest common prefix between addresses of different" 436 "families. Passed: {} and {}",
440 if (one.first.isV4()) {
442 {one.first.asV4(), one.second}, {two.first.asV4(), two.second});
444 }
else if (one.first.isV6()) {
446 {one.first.asV6(), one.second}, {two.first.asV6(), two.second});
449 throw std::invalid_argument(
"Unknown address family");
454 [[noreturn]]
void IPAddress::asV4Throw()
const {
457 sformat(
"Can't convert address with family {} to AF_INET address", fam));
460 [[noreturn]]
void IPAddress::asV6Throw()
const {
463 sformat(
"Can't convert address with family {} to AF_INET6 address", fam));
static CIDRNetworkV6 longestCommonPrefix(const CIDRNetworkV6 &one, const CIDRNetworkV6 &two)
static CIDRNetworkV4 longestCommonPrefix(const CIDRNetworkV4 &one, const CIDRNetworkV4 &two)
std::string sformat(StringPiece fmt, Args &&...args)
static IPAddressV6 fromBinary(ByteRange bytes)
constexpr detail::Map< Move > move
size_type find(const_range_type str) const
constexpr size_type size() const
IPAddressV4 getIPv4For6To4() const
static IPAddressV4 fromBinary(ByteRange bytes)
—— Concurrent Priority Queue Implementation ——
requires E e noexcept(noexcept(s.error(std::move(e))))
bool prefix(Cursor &c, uint32_t expected)
static Expected< IPAddressV4, IPAddressFormatError > tryFromString(StringPiece str) noexcept
void split(const Delim &delimiter, const String &input, std::vector< OutputType > &out, bool ignoreEmpty)
static Expected< IPAddressV4, IPAddressFormatError > tryFromBinary(ByteRange bytes) noexcept
bool inSubnetWithMask(const IPAddressV4 &subnet, const ByteArray4 mask) const
static Expected< IPAddressV6, IPAddressFormatError > tryFromBinary(ByteRange bytes) noexcept
static IPAddressV4 fromLong(uint32_t src)
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
constexpr Iter data() const
static bool validate(StringPiece ip) noexcept
static Expected< IPAddressV6, IPAddressFormatError > tryFromString(StringPiece str) noexcept
std::array< uint8_t, 16 > ByteArray16
size_t hash_value(const IPAddress &addr)
void toAppend(char value, Tgt *result)
constexpr Iter begin() const
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
static IPAddressV4 fromLongHBO(uint32_t src)
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
static bool validate(StringPiece ip) noexcept
bool inSubnet(StringPiece cidrNetwork) const
basic_fbstring & append(const basic_fbstring &str)
std::array< uint8_t, 4 > ByteArray4
static std::string toHex(const uint8_t *src, std::size_t len)
std::string familyNameStr(sa_family_t family)
ThreadPoolListHook * addr
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
std::ostream & operator<<(std::ostream &out, dynamic const &d)