Commit 5da6f8de authored by Angelo Failla's avatar Angelo Failla Committed by Facebook Github Bot

`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
parent ab7561be
......@@ -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{};
......
......@@ -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
......
......@@ -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()) {
......
......@@ -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.
*/
......
......@@ -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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment