`IPVAddressV(46)::fromInverseArpaName` static methods v2017.04.17.00
authorAngelo Failla <pallotron@fb.com>
Sun, 16 Apr 2017 10:10:17 +0000 (03:10 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sun, 16 Apr 2017 10:19:50 +0000 (03:19 -0700)
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

folly/IPAddressV4.cpp
folly/IPAddressV4.h
folly/IPAddressV6.cpp
folly/IPAddressV6.h
folly/test/IPAddressTest.cpp

index 62b05f7be795d9ff79e1f78d70dd2afb60640bde..dfe46695085bc82d6ecf340d2ec34053d32d079d 100644 (file)
@@ -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<StringPiece> 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{};
index 6603828a93b8e9bc44c5679946658e2fca7b42ff..094969461934088b3ebad26bcf326d0e9a41fc8e 100644 (file)
@@ -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
index 203d14a88489746e77195a6d7ebdedcab266aee1..c7a93efef96224f3564caedf787b85187b7b7665 100644 (file)
@@ -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<StringPiece> pieces;
+  split(".", piece, pieces);
+  if (pieces.size() != 32) {
+    throw IPAddressFormatException(sformat("Invalid input. Got '{}'", piece));
+  }
+  std::array<char, IPAddressV6::kToFullyQualifiedSize> 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()) {
index c6ddc453235689659b556696b2b08a2c71396780..21e892a42aac4f986c2c4a0d89585cb0e4b1431e 100644 (file)
@@ -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.
    */
index 2911a293454d5261fd82e3920fc8f8c53701ca1b..3dd64e9a35523789922c65f733df6c0c436a288a 100644 (file)
@@ -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();