X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FIPAddressV6.cpp;h=cdd82acc46a6fd0826c41917ad8e8fa87c11ee77;hp=6f1eb5958996c5f12bb16204a6c2a3398ddf26de;hb=fe9d8cadb9bba9ddc7ea151f779458b8dc1904cd;hpb=3e0ea1021a934b16df1f4848815b45ec671f3541 diff --git a/folly/IPAddressV6.cpp b/folly/IPAddressV6.cpp index 6f1eb595..cdd82acc 100644 --- a/folly/IPAddressV6.cpp +++ b/folly/IPAddressV6.cpp @@ -25,6 +25,19 @@ #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; @@ -49,32 +62,30 @@ void toAppend(IPAddressV6 addr, fbstring* result) { result->append(addr.str()); } -bool IPAddressV6::validate(StringPiece ip) { - if (ip.size() > 0 && ip.front() == '[' && ip.back() == ']') { - ip = ip.subpiece(1, ip.size() - 2); - } - - constexpr size_t kStrMaxLen = INET6_ADDRSTRLEN; - std::array ip_cstr; - const size_t len = std::min(ip.size(), kStrMaxLen); - std::memcpy(ip_cstr.data(), ip.data(), len); - ip_cstr[len] = 0; - struct in6_addr addr; - return 1 == inet_pton(AF_INET6, ip_cstr.data(), &addr); +bool IPAddressV6::validate(StringPiece ip) noexcept { + return tryFromString(ip).hasValue(); } // public default constructor -IPAddressV6::IPAddressV6() { -} +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( - to("Invalid IPv6 address '", ip, "': address too short")); + return makeUnexpected(IPAddressFormatError::INVALID_IP); } if (ip.front() == '[' && ip.back() == ']') { ip = ip.substr(1, ip.size() - 2); @@ -86,40 +97,29 @@ 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_ = uint16_t(ipAddr->sin6_scope_id); - freeaddrinfo(result); - } else { - throw IPAddressFormatException( - to("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_(uint16_t(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, @@ -138,20 +138,23 @@ IPAddressV6::AddressStorage::AddressStorage(MacAddress mac) { Optional IPAddressV6::getMacAddressFromLinkLocal() const { // Returned MacAddress must be constructed from a link-local IPv6 address. - if (!(addr_.bytes_[0] == 0xfe && addr_.bytes_[1] == 0x80 && - addr_.bytes_[2] == 0x00 && addr_.bytes_[3] == 0x00 && - addr_.bytes_[4] == 0x00 && addr_.bytes_[5] == 0x00 && - addr_.bytes_[6] == 0x00 && addr_.bytes_[7] == 0x00 && - addr_.bytes_[11] == 0xff && addr_.bytes_[12] == 0xfe)) { + if (!isLinkLocal()) { return folly::none; } - // The link-local address uses modified EUI-64 format, + 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 fe:80:00:00:00:00:00:00, and can be stripped + // 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 thhese bytes are they are + // 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] @@ -162,15 +165,34 @@ Optional IPAddressV6::getMacAddressFromLinkLocal() const { return Optional(MacAddress::fromBinary(range(bytes))); } -void IPAddressV6::setFromBinary(ByteRange bytes) { - if (bytes.size() != 16) { +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 ", + "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) { + return makeUnexpected(IPAddressFormatError::INVALID_IP); + } memcpy(&addr_.in6Addr_.s6_addr, bytes.data(), sizeof(in6_addr)); scope_ = 0; + return unit; } // static @@ -217,9 +239,8 @@ static inline uint16_t unpack(uint8_t lobyte, uint8_t hibyte) { // 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; @@ -230,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 { @@ -270,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) { @@ -286,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 @@ -310,18 +330,18 @@ bool IPAddressV6::inSubnet(StringPiece cidrNetwork) const { auto subnetInfo = IPAddress::createNetwork(cidrNetwork); auto addr = subnetInfo.first; if (!addr.isV6()) { - throw IPAddressFormatException(to( - "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); } @@ -337,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 { @@ -382,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)); } @@ -395,7 +428,7 @@ IPAddressV6 IPAddressV6::mask(size_t numBits) const { static const auto bits = bitCount(); if (numBits > bits) { throw IPAddressFormatException( - to("numBits(", numBits, ") > bitCount(", bits, ")")); + sformat("numBits({}) > bitCount({})", numBits, bits)); } ByteArray16 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_); return IPAddressV6(ba); @@ -403,21 +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 ip; - } else { - throw IPAddressFormatException(to( - "Invalid address with hex ", - "'", + 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 @@ -425,6 +467,11 @@ 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"; @@ -442,8 +489,9 @@ string IPAddressV6::toInverseArpaName() const { 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]; @@ -455,8 +503,18 @@ const ByteArray16 IPAddressV6::fetchMask(size_t numBits) { 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 @@ -469,530 +527,10 @@ CIDRNetworkV6 IPAddressV6::longestCommonPrefix( } // protected -bool IPAddressV6::inBinarySubnet(const std::array addr, - size_t numBits) const { +bool IPAddressV6::inBinarySubnet( + const std::array addr, + size_t numBits) const { auto masked = mask(numBits); return (std::memcmp(addr.data(), masked.bytes(), 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 +} // namespace folly