diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 7c62750..eec5afe 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -153,6 +153,16 @@ write code that handles both IP versions correctly. the appropriate length (most significant octet first). This is 4 bytes for IPv4 and 16 bytes for IPv6. + .. attribute:: reverse_pointer + + The name of the reverse DNS pointer for the IP address, e.g.:: + + >>> ipaddress.ip_address("127.0.0.1").reverse_pointer + '1.0.0.127.in-addr.arpa.' + >>> ipaddress.ip_address("2001:db8::1").reverse_pointer + '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.' + + .. attribute:: is_multicast ``True`` if the address is reserved for multicast use. See @@ -226,6 +236,7 @@ write code that handles both IP versions correctly. groups consisting entirely of zeroes included. .. attribute:: packed + .. attribute:: reverse_pointer .. attribute:: version .. attribute:: max_prefixlen .. attribute:: is_multicast diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 97ff13d..1b87eea 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -436,6 +436,17 @@ class _IPAddressBase(_TotalOrderingMixin): return str(self) @property + def reverse_pointer(self): + """The name of the reverse DNS pointer for the IP address, e.g.: + >>> ipaddress.ip_address("127.0.0.1").reverse_pointer + '1.0.0.127.in-addr.arpa.' + >>> ipaddress.ip_address("2001:db8::1").reverse_pointer + '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.' + + """ + return self._reverse_pointer() + + @property def version(self): msg = '%200s has no version specified' % (type(self),) raise NotImplementedError(msg) @@ -1166,6 +1177,15 @@ class _BaseV4: return True return False + def _reverse_pointer(self): + """Return the reverse DNS pointer name for the IPv4 address. + + This implements the method described in RFC1035 3.5. + + """ + rev_octets = str(self).split('.')[::-1] + return '.'.join(rev_octets) + '.in-addr.arpa.' + @property def max_prefixlen(self): return self._max_prefixlen @@ -1746,6 +1766,15 @@ class _BaseV6: return '%s/%d' % (':'.join(parts), self._prefixlen) return ':'.join(parts) + def _reverse_pointer(self): + """Return the reverse DNS pointer name for the IPv6 address. + + This implements the method described in RFC3596 2.5. + + """ + reverse_chars = self.exploded[::-1].replace(':', '') + return '.'.join(reverse_chars) + '.ip6.arpa.' + @property def max_prefixlen(self): return self._max_prefixlen diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index f3b1565..1ff57ec 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -1560,6 +1560,14 @@ class IpaddrUnitTest(unittest.TestCase): addr3.exploded) self.assertEqual('192.168.178.1', addr4.exploded) + def testReversePointer(self): + addr1 = ipaddress.IPv4Address('127.0.0.1') + addr2 = ipaddress.IPv6Address('2001:db8::1') + self.assertEqual('1.0.0.127.in-addr.arpa.', addr1.reverse_pointer) + self.assertEqual('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.' + + 'b.d.0.1.0.0.2.ip6.arpa.', + addr2.reverse_pointer) + def testIntRepresentation(self): self.assertEqual(16909060, int(self.ipv4_address)) self.assertEqual(42540616829182469433547762482097946625,