X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FIPAddressV6.cpp;h=cdd82acc46a6fd0826c41917ad8e8fa87c11ee77;hp=45e9e3a1ceea957668db595fbc6fdd17450ef3a6;hb=f6ed4a26c0f3e6ba12788206e54add9db18e4dd6;hpb=7ffe7766f032914384aa6e0b9598bab7d9a90602 diff --git a/folly/IPAddressV6.cpp b/folly/IPAddressV6.cpp index 45e9e3a1..cdd82acc 100644 --- a/folly/IPAddressV6.cpp +++ b/folly/IPAddressV6.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,20 @@ #include #include #include +#include + +#if !_WIN32 +#include +#else +// Because of the massive pain that is libnl, this can't go into the socket +// portability header as you can't include and in +// the same translation unit without getting errors -_-... +#include // @manual +#include // @manual + +// Alias the max size of an interface name to what posix expects. +#define IFNAMSIZ IF_NAMESIZE +#endif using std::ostream; using std::string; @@ -48,18 +62,30 @@ void toAppend(IPAddressV6 addr, fbstring* result) { result->append(addr.str()); } -// public default constructor -IPAddressV6::IPAddressV6() { +bool IPAddressV6::validate(StringPiece ip) noexcept { + return tryFromString(ip).hasValue(); } +// public default constructor +IPAddressV6::IPAddressV6() {} + // public string constructor IPAddressV6::IPAddressV6(StringPiece addr) { - auto ip = addr.str(); + auto maybeIp = tryFromString(addr); + if (maybeIp.hasError()) { + throw IPAddressFormatException( + to("Invalid IPv6 address '", addr, "'")); + } + *this = std::move(maybeIp.value()); +} + +Expected IPAddressV6::tryFromString( + StringPiece str) noexcept { + auto ip = str.str(); // Allow addresses surrounded in brackets if (ip.size() < 2) { - throw IPAddressFormatException("Invalid IPv6 address '", ip, - "': address too short"); + return makeUnexpected(IPAddressFormatError::INVALID_IP); } if (ip.front() == '[' && ip.back() == ']') { ip = ip.substr(1, ip.size() - 2); @@ -71,46 +97,36 @@ IPAddressV6::IPAddressV6(StringPiece addr) { hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST; - if (!getaddrinfo(ip.c_str(), nullptr, &hints, &result)) { - struct sockaddr_in6* ipAddr = (struct sockaddr_in6*)result->ai_addr; - addr_.in6Addr_ = ipAddr->sin6_addr; - scope_ = ipAddr->sin6_scope_id; - freeaddrinfo(result); - } else { - throw IPAddressFormatException("Invalid IPv6 address '", ip, "'"); + if (::getaddrinfo(ip.c_str(), nullptr, &hints, &result) == 0) { + SCOPE_EXIT { + ::freeaddrinfo(result); + }; + const struct sockaddr_in6* sa = + reinterpret_cast(result->ai_addr); + return IPAddressV6(*sa); } + return makeUnexpected(IPAddressFormatError::INVALID_IP); } // in6_addr constructor -IPAddressV6::IPAddressV6(const in6_addr& src) - : addr_(src) -{ -} +IPAddressV6::IPAddressV6(const in6_addr& src) noexcept : addr_(src) {} // sockaddr_in6 constructor -IPAddressV6::IPAddressV6(const sockaddr_in6& src) - : addr_(src.sin6_addr) - , scope_(src.sin6_scope_id) -{ -} +IPAddressV6::IPAddressV6(const sockaddr_in6& src) noexcept + : addr_(src.sin6_addr), scope_(uint16_t(src.sin6_scope_id)) {} // ByteArray16 constructor -IPAddressV6::IPAddressV6(const ByteArray16& src) - : addr_(src) -{ -} +IPAddressV6::IPAddressV6(const ByteArray16& src) noexcept : addr_(src) {} // link-local constructor -IPAddressV6::IPAddressV6(LinkLocalTag, MacAddress mac) - : addr_(mac) { -} +IPAddressV6::IPAddressV6(LinkLocalTag, MacAddress mac) : addr_(mac) {} IPAddressV6::AddressStorage::AddressStorage(MacAddress mac) { // The link-local address uses modified EUI-64 format, // See RFC 4291 sections 2.5.1, 2.5.6, and Appendix A const auto* macBytes = mac.bytes(); memcpy(&bytes_.front(), "\xfe\x80\x00\x00\x00\x00\x00\x00", 8); - bytes_[8] = macBytes[0] ^ 0x02; + bytes_[8] = uint8_t(macBytes[0] ^ 0x02); bytes_[9] = macBytes[1]; bytes_[10] = macBytes[2]; bytes_[11] = 0xff; @@ -120,13 +136,91 @@ IPAddressV6::AddressStorage::AddressStorage(MacAddress mac) { bytes_[15] = macBytes[5]; } -void IPAddressV6::setFromBinary(ByteRange bytes) { +Optional IPAddressV6::getMacAddressFromLinkLocal() const { + // Returned MacAddress must be constructed from a link-local IPv6 address. + if (!isLinkLocal()) { + return folly::none; + } + return getMacAddressFromEUI64(); +} + +Optional IPAddressV6::getMacAddressFromEUI64() const { + if (!(addr_.bytes_[11] == 0xff && addr_.bytes_[12] == 0xfe)) { + return folly::none; + } + // The auto configured address uses modified EUI-64 format, + // See RFC 4291 sections 2.5.1, 2.5.6, and Appendix A + std::array bytes; + // Step 1: first 8 bytes are network prefix, and can be stripped + // Step 2: invert the universal/local (U/L) flag (bit 7) + bytes[0] = addr_.bytes_[8] ^ 0x02; + // Step 3: copy these bytes as they are + bytes[1] = addr_.bytes_[9]; + bytes[2] = addr_.bytes_[10]; + // Step 4: strip bytes (0xfffe), which are bytes_[11] and bytes_[12] + // Step 5: copy the rest. + bytes[3] = addr_.bytes_[13]; + bytes[4] = addr_.bytes_[14]; + bytes[5] = addr_.bytes_[15]; + return Optional(MacAddress::fromBinary(range(bytes))); +} + +IPAddressV6 IPAddressV6::fromBinary(ByteRange bytes) { + auto maybeIp = tryFromBinary(bytes); + if (maybeIp.hasError()) { + throw IPAddressFormatException(to( + "Invalid IPv6 binary data: length must be 16 bytes, got ", + bytes.size())); + } + return maybeIp.value(); +} + +Expected IPAddressV6::tryFromBinary( + ByteRange bytes) noexcept { + IPAddressV6 addr; + auto setResult = addr.trySetFromBinary(bytes); + if (setResult.hasError()) { + return makeUnexpected(std::move(setResult.error())); + } + return addr; +} + +Expected IPAddressV6::trySetFromBinary( + ByteRange bytes) noexcept { if (bytes.size() != 16) { - throw IPAddressFormatException("Invalid IPv6 binary data: length must " - "be 16 bytes, got ", bytes.size()); + return makeUnexpected(IPAddressFormatError::INVALID_IP); } memcpy(&addr_.in6Addr_.s6_addr, bytes.data(), sizeof(in6_addr)); scope_ = 0; + return unit; +} + +// static +IPAddressV6 IPAddressV6::fromInverseArpaName(const std::string& arpaname) { + auto piece = StringPiece(arpaname); + if (!piece.removeSuffix(".ip6.arpa")) { + throw IPAddressFormatException(sformat( + "Invalid input. Should end with 'ip6.arpa'. Got '{}'", arpaname)); + } + std::vector pieces; + split(".", piece, pieces); + if (pieces.size() != 32) { + throw IPAddressFormatException(sformat("Invalid input. Got '{}'", piece)); + } + std::array ip; + size_t pos = 0; + int count = 0; + for (size_t i = 1; i <= pieces.size(); i++) { + ip[pos] = pieces[pieces.size() - i][0]; + pos++; + count++; + // add ':' every 4 chars + if (count == 4 && pos < ip.size()) { + ip[pos++] = ':'; + count = 0; + } + } + return IPAddressV6(folly::range(ip)); } // public @@ -140,14 +234,13 @@ IPAddressV4 IPAddressV6::createIPv4() const { // convert two uint8_t bytes into a uint16_t as hibyte.lobyte static inline uint16_t unpack(uint8_t lobyte, uint8_t hibyte) { - return ((uint16_t)hibyte << 8) | (uint16_t)lobyte; + return uint16_t((uint16_t(hibyte) << 8) | lobyte); } // given a src string, unpack count*2 bytes into dest // dest must have as much storage as count -static inline void unpackInto(const unsigned char* src, - uint16_t* dest, - size_t count) { +static inline void +unpackInto(const unsigned char* src, uint16_t* dest, size_t count) { for (size_t i = 0, hi = 1, lo = 0; i < count; i++) { dest[i] = unpack(src[hi], src[lo]); hi += 2; @@ -158,11 +251,11 @@ static inline void unpackInto(const unsigned char* src, // public IPAddressV4 IPAddressV6::getIPv4For6To4() const { if (!is6To4()) { - throw IPAddressV6::TypeError(format( - "Invalid IP '{}': not a 6to4 address", str()).str()); + throw IPAddressV6::TypeError( + sformat("Invalid IP '{}': not a 6to4 address", str())); } // convert 16x8 bytes into first 4x16 bytes - uint16_t ints[4] = {0,0,0,0}; + uint16_t ints[4] = {0, 0, 0, 0}; unpackInto(bytes(), ints, 4); // repack into 4x8 union { @@ -198,7 +291,7 @@ bool IPAddressV6::isIPv4Mapped() const { // public IPAddressV6::Type IPAddressV6::type() const { // convert 16x8 bytes into first 2x16 bytes - uint16_t ints[2] = {0,0}; + uint16_t ints[2] = {0, 0}; unpackInto(bytes(), ints, 2); if ((((uint32_t)ints[0] << 16) | ints[1]) == IPAddressV6::PREFIX_TEREDO) { @@ -214,8 +307,7 @@ IPAddressV6::Type IPAddressV6::type() const { // public string IPAddressV6::toJson() const { - return format( - "{{family:'AF_INET6', addr:'{}', hash:{}}}", str(), hash()).str(); + return sformat("{{family:'AF_INET6', addr:'{}', hash:{}}}", str(), hash()); } // public @@ -238,18 +330,18 @@ bool IPAddressV6::inSubnet(StringPiece cidrNetwork) const { auto subnetInfo = IPAddress::createNetwork(cidrNetwork); auto addr = subnetInfo.first; if (!addr.isV6()) { - throw IPAddressFormatException("Address '", addr.toJson(), "' ", - "is not a V6 address"); + throw IPAddressFormatException( + sformat("Address '{}' is not a V6 address", addr.toJson())); } return inSubnetWithMask(addr.asV6(), fetchMask(subnetInfo.second)); } // public -bool IPAddressV6::inSubnetWithMask(const IPAddressV6& subnet, - const ByteArray16& cidrMask) const { - const ByteArray16 mask = detail::Bytes::mask(toByteArray(), cidrMask); - const ByteArray16 subMask = detail::Bytes::mask(subnet.toByteArray(), - cidrMask); +bool IPAddressV6::inSubnetWithMask( + const IPAddressV6& subnet, + const ByteArray16& cidrMask) const { + const auto mask = detail::Bytes::mask(toByteArray(), cidrMask); + const auto subMask = detail::Bytes::mask(subnet.toByteArray(), cidrMask); return (mask == subMask); } @@ -265,11 +357,11 @@ bool IPAddressV6::isLoopback() const { bool IPAddressV6::isRoutable() const { return - // 2000::/3 is the only assigned global unicast block - inBinarySubnet({{0x20, 0x00}}, 3) || - // ffxe::/16 are global scope multicast addresses, - // which are eligible to be routed over the internet - (isMulticast() && getMulticastScope() == 0xe); + // 2000::/3 is the only assigned global unicast block + inBinarySubnet({{0x20, 0x00}}, 3) || + // ffxe::/16 are global scope multicast addresses, + // which are eligible to be routed over the internet + (isMulticast() && getMulticastScope() == 0xe); } bool IPAddressV6::isLinkLocalBroadcast() const { @@ -286,6 +378,7 @@ bool IPAddressV6::isPrivate() const { return isLoopback() || inBinarySubnet({{0xfc, 0x00}}, 7); } +// public bool IPAddressV6::isLinkLocal() const { return inBinarySubnet({{0xfe, 0x80}}, 10); } @@ -296,12 +389,12 @@ bool IPAddressV6::isMulticast() const { uint8_t IPAddressV6::getMulticastFlags() const { DCHECK(isMulticast()); - return ((addr_.bytes_[1] >> 4) & 0xf); + return uint8_t((addr_.bytes_[1] >> 4) & 0xf); } uint8_t IPAddressV6::getMulticastScope() const { DCHECK(isMulticast()); - return (addr_.bytes_[1] & 0xf); + return uint8_t(addr_.bytes_[1] & 0xf); } IPAddressV6 IPAddressV6::getSolicitedNodeAddress() const { @@ -309,11 +402,24 @@ IPAddressV6 IPAddressV6::getSolicitedNodeAddress() const { // addresses DCHECK(!isMulticast()); - uint8_t bytes[16] = { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00 }; - bytes[13] = addr_.bytes_[13]; - bytes[14] = addr_.bytes_[14]; - bytes[15] = addr_.bytes_[15]; + uint8_t bytes[16] = { + 0xff, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0xff, + addr_.bytes_[13], + addr_.bytes_[14], + addr_.bytes_[15], + }; return IPAddressV6::fromBinary(ByteRange(bytes, 16)); } @@ -321,8 +427,8 @@ IPAddressV6 IPAddressV6::getSolicitedNodeAddress() const { IPAddressV6 IPAddressV6::mask(size_t numBits) const { static const auto bits = bitCount(); if (numBits > bits) { - throw IPAddressFormatException("numBits(", numBits, ") > bitCount(", - bits, ")"); + throw IPAddressFormatException( + sformat("numBits({}) > bitCount({})", numBits, bits)); } ByteArray16 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_); return IPAddressV6(ba); @@ -330,18 +436,30 @@ IPAddressV6 IPAddressV6::mask(size_t numBits) const { // public string IPAddressV6::str() const { - char buffer[INET6_ADDRSTRLEN] = {0}; - sockaddr_in6 sock = toSockAddr(); - if (!getnameinfo( - (sockaddr*)&sock, sizeof(sock), - buffer, INET6_ADDRSTRLEN, - nullptr, 0, NI_NUMERICHOST)) { - string ip(buffer); - return std::move(ip); - } else { - throw IPAddressFormatException("Invalid address with hex ", - "'", detail::Bytes::toHex(bytes(), 16), "'"); + char buffer[INET6_ADDRSTRLEN + IFNAMSIZ + 1]; + + if (!inet_ntop(AF_INET6, toAddr().s6_addr, buffer, INET6_ADDRSTRLEN)) { + throw IPAddressFormatException(sformat( + "Invalid address with hex '{}' with error {}", + detail::Bytes::toHex(bytes(), 16), + strerror(errno))); + } + + auto scopeId = getScopeId(); + if (scopeId != 0) { + auto len = strlen(buffer); + buffer[len] = '%'; + + auto errsv = errno; + if (!if_indextoname(scopeId, buffer + len + 1)) { + // if we can't map the if because eg. it no longer exists, + // append the if index instead + snprintf(buffer + len + 1, IFNAMSIZ, "%u", scopeId); + } + errno = errsv; } + + return string(buffer); } // public @@ -349,12 +467,31 @@ string IPAddressV6::toFullyQualified() const { return detail::fastIpv6ToString(addr_.in6Addr_); } +// public +void IPAddressV6::toFullyQualifiedAppend(std::string& out) const { + detail::fastIpv6AppendToString(addr_.in6Addr_, out); +} + +// public +string IPAddressV6::toInverseArpaName() const { + constexpr folly::StringPiece lut = "0123456789abcdef"; + std::array a; + int j = 0; + for (int i = 15; i >= 0; i--) { + a[j] = (lut[bytes()[i] & 0xf]); + a[j + 1] = (lut[bytes()[i] >> 4]); + j += 2; + } + return sformat("{}.ip6.arpa", join(".", a)); +} + // public uint8_t IPAddressV6::getNthMSByte(size_t byteIndex) const { const auto highestIndex = byteCount() - 1; if (byteIndex > highestIndex) { - throw std::invalid_argument(to("Byte index must be <= ", - to(highestIndex), " for addresses of type :", + throw std::invalid_argument(sformat( + "Byte index must be <= {} for addresses of type: {}", + highestIndex, detail::familyNameStr(AF_INET6))); } return bytes()[byteIndex]; @@ -362,539 +499,38 @@ uint8_t IPAddressV6::getNthMSByte(size_t byteIndex) const { // protected const ByteArray16 IPAddressV6::fetchMask(size_t numBits) { - static const uint8_t bits = bitCount(); + static const size_t bits = bitCount(); if (numBits > bits) { throw IPAddressFormatException("IPv6 addresses are 128 bits."); } - // masks_ is backed by an array so is zero indexed - return masks_[numBits]; + if (numBits == 0) { + return {{0}}; + } + constexpr auto _0s = uint64_t(0); + constexpr auto _1s = ~_0s; + auto const fragment = Endian::big(_1s << ((128 - numBits) % 64)); + auto const hi = numBits <= 64 ? fragment : _1s; + auto const lo = numBits <= 64 ? _0s : fragment; + uint64_t const parts[] = {hi, lo}; + ByteArray16 arr; + std::memcpy(arr.data(), parts, sizeof(parts)); + return arr; +} + +// public static +CIDRNetworkV6 IPAddressV6::longestCommonPrefix( + const CIDRNetworkV6& one, + const CIDRNetworkV6& two) { + auto prefix = detail::Bytes::longestCommonPrefix( + one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second); + return {IPAddressV6(prefix.first), prefix.second}; } // protected -bool IPAddressV6::inBinarySubnet(const std::array addr, - size_t numBits) const { - const unsigned char* subbytes = mask(numBits).bytes(); - return (std::memcmp(addr.data(), subbytes, 2) == 0); -} - -// static private -const std::array IPAddressV6::masks_ = {{ -/* /0 */ {{ 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /1 */ {{ 0x80,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /2 */ {{ 0xc0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /3 */ {{ 0xe0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /4 */ {{ 0xf0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /5 */ {{ 0xf8,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /6 */ {{ 0xfc,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /7 */ {{ 0xfe,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /8 */ {{ 0xff,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /9 */ {{ 0xff,0x80,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /10 */ {{ 0xff,0xc0,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /11 */ {{ 0xff,0xe0,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /12 */ {{ 0xff,0xf0,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /13 */ {{ 0xff,0xf8,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /14 */ {{ 0xff,0xfc,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /15 */ {{ 0xff,0xfe,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /16 */ {{ 0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /17 */ {{ 0xff,0xff,0x80,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /18 */ {{ 0xff,0xff,0xc0,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /19 */ {{ 0xff,0xff,0xe0,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /20 */ {{ 0xff,0xff,0xf0,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /21 */ {{ 0xff,0xff,0xf8,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /22 */ {{ 0xff,0xff,0xfc,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /23 */ {{ 0xff,0xff,0xfe,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /24 */ {{ 0xff,0xff,0xff,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /25 */ {{ 0xff,0xff,0xff,0x80, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /26 */ {{ 0xff,0xff,0xff,0xc0, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /27 */ {{ 0xff,0xff,0xff,0xe0, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /28 */ {{ 0xff,0xff,0xff,0xf0, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /29 */ {{ 0xff,0xff,0xff,0xf8, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /30 */ {{ 0xff,0xff,0xff,0xfc, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /31 */ {{ 0xff,0xff,0xff,0xfe, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /32 */ {{ 0xff,0xff,0xff,0xff, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /33 */ {{ 0xff,0xff,0xff,0xff, - 0x80,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /34 */ {{ 0xff,0xff,0xff,0xff, - 0xc0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /35 */ {{ 0xff,0xff,0xff,0xff, - 0xe0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /36 */ {{ 0xff,0xff,0xff,0xff, - 0xf0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /37 */ {{ 0xff,0xff,0xff,0xff, - 0xf8,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /38 */ {{ 0xff,0xff,0xff,0xff, - 0xfc,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /39 */ {{ 0xff,0xff,0xff,0xff, - 0xfe,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /40 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /41 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0x80,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /42 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xc0,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /43 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xe0,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /44 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xf0,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /45 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xf8,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /46 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xfc,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /47 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xfe,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /48 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /49 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0x80,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /50 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xc0,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /51 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xe0,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /52 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xf0,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /53 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xf8,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /54 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xfc,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /55 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xfe,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /56 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /57 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0x80, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /58 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xc0, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /59 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xe0, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /60 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xf0, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /61 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xf8, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /62 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xfc, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /63 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xfe, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /64 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /65 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0x80,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /66 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xc0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /67 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xe0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /68 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xf0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /69 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xf8,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /70 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xfc,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /71 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xfe,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /72 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /73 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0x80,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /74 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xc0,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /75 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xe0,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /76 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xf0,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /77 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xf8,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /78 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xfc,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /79 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xfe,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /80 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /81 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0x80,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /82 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xc0,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /83 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xe0,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /84 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xf0,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /85 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xf8,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /86 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xfc,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /87 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xfe,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /88 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0x00, - 0x00,0x00,0x00,0x00 }}, -/* /89 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0x80, - 0x00,0x00,0x00,0x00 }}, -/* /90 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xc0, - 0x00,0x00,0x00,0x00 }}, -/* /91 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xe0, - 0x00,0x00,0x00,0x00 }}, -/* /92 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xf0, - 0x00,0x00,0x00,0x00 }}, -/* /93 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xf8, - 0x00,0x00,0x00,0x00 }}, -/* /94 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xfc, - 0x00,0x00,0x00,0x00 }}, -/* /95 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xfe, - 0x00,0x00,0x00,0x00 }}, -/* /96 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0x00,0x00,0x00,0x00 }}, -/* /97 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0x80,0x00,0x00,0x00 }}, -/* /98 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xc0,0x00,0x00,0x00 }}, -/* /99 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xe0,0x00,0x00,0x00 }}, -/* /100 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xf0,0x00,0x00,0x00 }}, -/* /101 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xf8,0x00,0x00,0x00 }}, -/* /102 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xfc,0x00,0x00,0x00 }}, -/* /103 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xfe,0x00,0x00,0x00 }}, -/* /104 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0x00,0x00,0x00 }}, -/* /105 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0x80,0x00,0x00 }}, -/* /106 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xc0,0x00,0x00 }}, -/* /107 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xe0,0x00,0x00 }}, -/* /108 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xf0,0x00,0x00 }}, -/* /109 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xf8,0x00,0x00 }}, -/* /110 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xfc,0x00,0x00 }}, -/* /111 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xfe,0x00,0x00 }}, -/* /112 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0x00,0x00 }}, -/* /113 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0x80,0x00 }}, -/* /114 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xc0,0x00 }}, -/* /115 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xe0,0x00 }}, -/* /116 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xf0,0x00 }}, -/* /117 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xf8,0x00 }}, -/* /118 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xfc,0x00 }}, -/* /119 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xfe,0x00 }}, -/* /120 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0x00 }}, -/* /121 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0x80 }}, -/* /122 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xc0 }}, -/* /123 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xe0 }}, -/* /124 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xf0 }}, -/* /125 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xf8 }}, -/* /126 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xfc }}, -/* /127 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xfe }}, -/* /128 */ {{ 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff }}, -}}; - -} // folly +bool IPAddressV6::inBinarySubnet( + const std::array addr, + size_t numBits) const { + auto masked = mask(numBits); + return (std::memcmp(addr.data(), masked.bytes(), 2) == 0); +} +} // namespace folly