From: Angelo Failla Date: Sun, 16 Apr 2017 10:10:17 +0000 (-0700) Subject: `IPVAddressV(46)::fromInverseArpaName` static methods X-Git-Tag: v2017.04.17.00^0 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=5da6f8de1779620e07722fea4d6e0bbc31e2e226 `IPVAddressV(46)::fromInverseArpaName` static methods Summary: In a previous diff I added toInverseArpaName methods but I forgot to add the inverse. This change adds `IPVAddressV(46)::fromInverseArpaName` static methods. I have also implemented some suggestions that were in D4867502 but I couldn't incorporate because the diff was landed already. Reviewed By: yfeldblum Differential Revision: D4885198 fbshipit-source-id: b95752aa695d6675cb293f8df2daa1787383390f --- diff --git a/folly/IPAddressV4.cpp b/folly/IPAddressV4.cpp index 62b05f7b..dfe46695 100644 --- a/folly/IPAddressV4.cpp +++ b/folly/IPAddressV4.cpp @@ -122,6 +122,23 @@ void IPAddressV4::setFromBinary(ByteRange bytes) { memcpy(&addr_.inAddr_.s_addr, bytes.data(), sizeof(in_addr)); } +// static +IPAddressV4 IPAddressV4::fromInverseArpaName(const std::string& arpaname) { + auto piece = StringPiece(arpaname); + // input must be something like 1.0.168.192.in-addr.arpa + if (!piece.removeSuffix(".in-addr.arpa")) { + throw IPAddressFormatException( + sformat("input does not end with '.in-addr.arpa': '{}'", arpaname)); + } + std::vector pieces; + split(".", piece, pieces); + if (pieces.size() != 4) { + throw IPAddressFormatException(sformat("Invalid input. Got {}", piece)); + } + // reverse 1.0.168.192 -> 192.168.0.1 + return IPAddressV4(join(".", pieces.rbegin(), pieces.rend())); +} + // public IPAddressV6 IPAddressV4::createIPv6() const { ByteArray16 ba{}; diff --git a/folly/IPAddressV4.h b/folly/IPAddressV4.h index 6603828a..09496946 100644 --- a/folly/IPAddressV4.h +++ b/folly/IPAddressV4.h @@ -79,6 +79,13 @@ class IPAddressV4 { return ByteRange((const unsigned char *) &addr_.inAddr_.s_addr, 4); } + /** + * Create a new IPAddress instance from the in-addr.arpa representation. + * @throws IPAddressFormatException if the input is not a valid in-addr.arpa + * representation + */ + static IPAddressV4 fromInverseArpaName(const std::string& arpaname); + /** * Convert a IPv4 address string to a long in network byte order. * @param [in] ip the address to convert diff --git a/folly/IPAddressV6.cpp b/folly/IPAddressV6.cpp index 203d14a8..c7a93efe 100644 --- a/folly/IPAddressV6.cpp +++ b/folly/IPAddressV6.cpp @@ -173,6 +173,34 @@ void IPAddressV6::setFromBinary(ByteRange bytes) { scope_ = 0; } +// 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; + int pos = 0; + int count = 0; + for (int p = pieces.size() - 1; p >= 0; p--) { + ip[pos] = pieces[p][0]; + pos++; + count++; + // add ':' every 4 chars + if (count == 4) { + ip[pos++] = ':'; + count = 0; + } + } + return IPAddressV6(folly::range(ip)); +} + // public IPAddressV4 IPAddressV6::createIPv4() const { if (!isIPv4Mapped()) { diff --git a/folly/IPAddressV6.h b/folly/IPAddressV6.h index c6ddc453..21e892a4 100644 --- a/folly/IPAddressV6.h +++ b/folly/IPAddressV6.h @@ -101,6 +101,13 @@ class IPAddressV6 { return addr; } + /** + * Create a new IPAddress instance from the ip6.arpa representation. + * @throws IPAddressFormatException if the input is not a valid ip6.arpa + * representation + */ + static IPAddressV6 fromInverseArpaName(const std::string& arpaname); + /** * Returns the address as a Range. */ diff --git a/folly/test/IPAddressTest.cpp b/folly/test/IPAddressTest.cpp index 2911a293..3dd64e9a 100644 --- a/folly/test/IPAddressTest.cpp +++ b/folly/test/IPAddressTest.cpp @@ -416,6 +416,17 @@ TEST(IPaddress, toInverseArpaName) { addr_ipv6.toInverseArpaName()); } +TEST(IPaddress, fromInverseArpaName) { + EXPECT_EQ( + IPAddressV4("10.0.0.1"), + IPAddressV4::fromInverseArpaName("1.0.0.10.in-addr.arpa")); + EXPECT_EQ( + IPAddressV6("2620:0000:1cfe:face:b00c:0000:0000:0003"), + IPAddressV6::fromInverseArpaName(sformat( + "{}.ip6.arpa", + "3.0.0.0.0.0.0.0.0.0.0.0.c.0.0.b.e.c.a.f.e.f.c.1.0.0.0.0.0.2.6.2"))); +} + // Test that invalid string values are killed TEST_P(IPAddressCtorTest, InvalidCreation) { string addr = GetParam();