X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FIPAddressV4.cpp;h=55f2a7b861c7cb500fe21e6e0a0118cbd9dce2b2;hb=8f22c4e3ae765fa8b631c07ffa90dc4ba1aff279;hp=144e4cce6d006b204ce95d52fddfd14f0682c9e5;hpb=e892dc54738ff07c2827775a208767b2018a6b13;p=folly.git diff --git a/folly/IPAddressV4.cpp b/folly/IPAddressV4.cpp index 144e4cce..55f2a7b8 100644 --- a/folly/IPAddressV4.cpp +++ b/folly/IPAddressV4.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. @@ -22,12 +22,14 @@ #include #include #include +#include using std::ostream; using std::string; namespace folly { + // free functions size_t hash_value(const IPAddressV4& addr) { return addr.hash(); @@ -43,6 +45,15 @@ void toAppend(IPAddressV4 addr, fbstring* result) { result->append(addr.str()); } +bool IPAddressV4::validate(StringPiece ip) { + constexpr size_t kStrMaxLen = INET_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 in_addr addr; + return 1 == inet_pton(AF_INET, ip_cstr.data(), &addr); +} // public static IPAddressV4 IPAddressV4::fromLong(uint32_t src) { @@ -62,8 +73,8 @@ uint32_t IPAddressV4::toLong(StringPiece ip) { auto str = ip.str(); in_addr addr; if (inet_pton(AF_INET, str.c_str(), &addr) != 1) { - throw IPAddressFormatException("Can't convert invalid IP '", ip, "' ", - "to long"); + throw IPAddressFormatException( + to("Can't convert invalid IP '", ip, "' ", "to long")); } return addr.s_addr; } @@ -89,7 +100,8 @@ IPAddressV4::IPAddressV4(StringPiece addr) { auto ip = addr.str(); if (inet_pton(AF_INET, ip.c_str(), &addr_.inAddr_) != 1) { - throw IPAddressFormatException("Invalid IPv4 address '", addr, "'"); + throw IPAddressFormatException( + to("Invalid IPv4 address '", addr, "'")); } } @@ -102,21 +114,32 @@ IPAddressV4::IPAddressV4(const in_addr src) // public void IPAddressV4::setFromBinary(ByteRange bytes) { if (bytes.size() != 4) { - throw IPAddressFormatException("Invalid IPv4 binary data: length must " - "be 4 bytes, got ", bytes.size()); + throw IPAddressFormatException(to( + "Invalid IPv4 binary data: length must ", + "be 4 bytes, got ", + bytes.size())); } memcpy(&addr_.inAddr_.s_addr, bytes.data(), sizeof(in_addr)); } // public IPAddressV6 IPAddressV4::createIPv6() const { - ByteArray16 ba{{0}}; + ByteArray16 ba{}; ba[10] = 0xff; ba[11] = 0xff; std::memcpy(&ba[12], bytes(), 4); return IPAddressV6(ba); } +// public +IPAddressV6 IPAddressV4::getIPv6For6To4() const { + ByteArray16 ba{}; + ba[0] = (uint8_t)((IPAddressV6::PREFIX_6TO4 & 0xFF00) >> 8); + ba[1] = (uint8_t)(IPAddressV6::PREFIX_6TO4 & 0x00FF); + std::memcpy(&ba[2], bytes(), 4); + return IPAddressV6(ba); +} + // public string IPAddressV4::toJson() const { return format( @@ -128,8 +151,8 @@ bool IPAddressV4::inSubnet(StringPiece cidrNetwork) const { auto subnetInfo = IPAddress::createNetwork(cidrNetwork); auto addr = subnetInfo.first; if (!addr.isV4()) { - throw IPAddressFormatException("Address '", addr.toJson(), "' ", - "is not a V4 address"); + throw IPAddressFormatException(to( + "Address '", addr.toJson(), "' ", "is not a V4 address")); } return inSubnetWithMask(addr.asV4(), fetchMask(subnetInfo.second)); } @@ -143,6 +166,18 @@ bool IPAddressV4::inSubnetWithMask(const IPAddressV4& subnet, return (mask == subMask); } +// public +bool IPAddressV4::isLoopback() const { + static IPAddressV4 loopback_addr("127.0.0.0"); + return inSubnetWithMask(loopback_addr, fetchMask(8)); +} + +// public +bool IPAddressV4::isLinkLocal() const { + static IPAddressV4 linklocal_addr("169.254.0.0"); + return inSubnetWithMask(linklocal_addr, fetchMask(16)); +} + // public bool IPAddressV4::isNonroutable() const { auto ip = toLongHBO(); @@ -176,8 +211,8 @@ bool IPAddressV4::isMulticast() const { IPAddressV4 IPAddressV4::mask(size_t numBits) const { static const auto bits = bitCount(); if (numBits > bits) { - throw IPAddressFormatException("numBits(", numBits, - ") > bitsCount(", bits, ")"); + throw IPAddressFormatException( + to("numBits(", numBits, ") > bitsCount(", bits, ")")); } ByteArray4 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_); @@ -201,13 +236,22 @@ uint8_t IPAddressV4::getNthMSByte(size_t byteIndex) const { } // protected const ByteArray4 IPAddressV4::fetchMask(size_t numBits) { - static const uint8_t bits = bitCount(); + static const size_t bits = bitCount(); if (numBits > bits) { - throw IPAddressFormatException("IPv4 addresses are 32 bits"); + throw IPAddressFormatException( + to("IPv4 addresses are 32 bits")); } // masks_ is backed by an array so is zero indexed return masks_[numBits]; } +// public static +CIDRNetworkV4 IPAddressV4::longestCommonPrefix( + const CIDRNetworkV4& one, + const CIDRNetworkV4& two) { + auto prefix = detail::Bytes::longestCommonPrefix( + one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second); + return {IPAddressV4(prefix.first), prefix.second}; +} // static private const std::array IPAddressV4::masks_ = {{