Skip to content

Commit

Permalink
Ability to parse addresses in ARPA (Reverse DNS Lookup) format.
Browse files Browse the repository at this point in the history
  • Loading branch information
mlocati committed Jan 13, 2022
1 parent 28763c8 commit e244d80
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 2 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,19 @@ echo $ipv4->getReverseDNSLookupName();
echo $ipv6->getReverseDNSLookupName();
```

To parse addresses in reverse DNS lookup format you can use the `IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS` flag when parsing a string:

```php
$ipv4 = \IPLib\Factory::parseAddressString('255.3.2.1.in-addr.arpa', \IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS);
$ipv6 = \IPLib\Factory::parseAddressString('e.b.a.b.e.f.a.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.c.b.a.4.3.2.1.ip6.arpa', \IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS);

// This will print 1.2.3.255
echo $ipv4->toString();

// This will print 1234:abcd::cafe:babe
echo (string) $ipv6->toString();
```

You can also use `getReverseDNSLookupName()` for IP ranges.
In this case, the result is an array of strings:

Expand Down
8 changes: 7 additions & 1 deletion src/Address/IPv4.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ public static function parseString($address, $flags = 0)
return null;
}
$flags = (int) $flags;
$matches = null;
if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
if (preg_match('/^([12]?[0-9]{1,2}\.[12]?[0-9]{1,2}\.[12]?[0-9]{1,2}\.[12]?[0-9]{1,2})\.in-addr\.arpa\.?$/i', $address, $matches)) {
$address = implode('.', array_reverse(explode('.', $matches[1])));
$flags = $flags & ~(ParseStringFlag::IPV4_MAYBE_NON_DECIMAL | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED);
}
}
if ($flags & ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED) {
if (strpos($address, '.') === 0) {
return null;
Expand Down Expand Up @@ -151,7 +158,6 @@ public static function parseString($address, $flags = 0)
if ($flags & ParseStringFlag::MAY_INCLUDE_PORT) {
$rx .= '(?::\d+)?';
}
$matches = null;
if (!preg_match('/^' . $rx . '$/', $address, $matches)) {
return null;
}
Expand Down
15 changes: 14 additions & 1 deletion src/Address/IPv6.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,23 @@ public static function fromString($address, $mayIncludePort = true, $mayIncludeZ
*/
public static function parseString($address, $flags = 0)
{
if (!is_string($address)) {
return null;
}
$matches = null;
$flags = (int) $flags;
if ($flags & ParseStringFlag::ADDRESS_MAYBE_RDNS) {
if (preg_match('/^([0-9a-f](?:\.[0-9a-f]){31})\.ip6\.arpa\.?/i', $address, $matches)) {
$nibbles = array_reverse(explode('.', $matches[1]));
$quibbles = array();
foreach (array_chunk($nibbles, 4) as $n) {
$quibbles[] = implode('', $n);
}
$address = implode(':', $quibbles);
}
}
$result = null;
if (is_string($address) && strpos($address, ':') !== false && strpos($address, ':::') === false) {
$matches = null;
if ($flags & ParseStringFlag::MAY_INCLUDE_PORT && $address[0] === '[' && preg_match('/^\[(.+)]:\d+$/', $address, $matches)) {
$address = $matches[1];
}
Expand Down
12 changes: 12 additions & 0 deletions src/ParseStringFlag.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,16 @@ class ParseStringFlag
* @see http://git.musl-libc.org/cgit/musl/tree/src/network/inet_aton.c?h=v1.2.2
*/
const IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED = 16;

/**
* Use this flag if you want to accept parsing IPv4/IPv6 addresses in Reverse DNS Lookup Address format.
*
* @var int
*
* @since 1.18.0
*
* @example 140.13.12.10.in-addr.arpa => 10.12.13.140
* @example b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa => 4321:0:1:2:3:4:567:89ab
*/
const ADDRESS_MAYBE_RDNS = 32;
}
4 changes: 4 additions & 0 deletions test/tests/Addresses/ReverseDNSLookupNameTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace IPLib\Test\Addresses;

use IPLib\Factory;
use IPLib\ParseStringFlag;
use IPLib\Test\TestCase;

class ReverseDNSLookupNameTest extends TestCase
Expand Down Expand Up @@ -33,5 +34,8 @@ public function testReverseDNSLookupName($addressString, $expectedReverseDNSAddr
$address = Factory::addressFromString($addressString);
$actualReverseDNSAddress = $address->getReverseDNSLookupName();
$this->assertSame($expectedReverseDNSAddress, $actualReverseDNSAddress);
$address2 = Factory::parseAddressString($actualReverseDNSAddress, ParseStringFlag::ADDRESS_MAYBE_RDNS);
$this->assertNotNull($address2);
$this->assertSame((string) $address, (string) $address2);
}
}

0 comments on commit e244d80

Please sign in to comment.