Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -1255,13 +1255,20 @@ def _string_from_ip_int(cls, ip_int):
return '.'.join(map(str, ip_int.to_bytes(4, 'big')))

def _reverse_pointer(self):
"""Return the reverse DNS pointer name for the IPv4 address.
"""Return the reverse DNS pointer name for the IPv4 address or network.

This implements the method described in RFC1035 3.5.

"""
reverse_octets = str(self).split('.')[::-1]
return '.'.join(reverse_octets) + '.in-addr.arpa'
prefix = getattr(self, 'prefixlen', IPV4LENGTH)
octet_count, remainder = divmod(prefix, 8) # each octet is 8 bits long
if remainder:
raise NetmaskValueError(
'Reverse pointer cannot be generated for given prefix size')
address_exploded = getattr(self, 'network_address', self).exploded
reverse_octets = address_exploded.split('.')[:octet_count][::-1]
reverse_octets.append('in-addr.arpa')
return '.'.join(reverse_octets)

class IPv4Address(_BaseV4, _BaseAddress):

Expand Down Expand Up @@ -1870,13 +1877,20 @@ def _explode_shorthand_ip_string(self):
return ':'.join(parts)

def _reverse_pointer(self):
"""Return the reverse DNS pointer name for the IPv6 address.
"""Return the reverse DNS pointer name for the IPv6 address or network.

This implements the method described in RFC3596 2.5.

"""
reverse_chars = self.exploded[::-1].replace(':', '')
return '.'.join(reverse_chars) + '.ip6.arpa'
prefix = getattr(self, 'prefixlen', IPV6LENGTH)
char_count, remainder = divmod(prefix, 4) # each char is 4 bits long
if remainder:
raise NetmaskValueError(
'Reverse pointer cannot be generated for given prefix size')
address_exploded = getattr(self, 'network_address', self).exploded
reverse_chars = list(address_exploded.replace(':', '')[:char_count][::-1])
reverse_chars.append('ip6.arpa')
return '.'.join(reverse_chars)

@staticmethod
def _split_scope_id(ip_str):
Expand Down
36 changes: 36 additions & 0 deletions Lib/test/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,24 @@ def test_subnet_of_mixed_types(self):
ipaddress.IPv6Network('::1/128').subnet_of(
ipaddress.IPv4Network('10.0.0.0/30'))

def test_reverse_pointer(self):
self.assertEqual(self.factory('0.0.0.0/0').reverse_pointer,
'in-addr.arpa')
self.assertEqual(self.factory('127.0.0.0/8').reverse_pointer,
'127.in-addr.arpa')
self.assertEqual(self.factory('127.12.0.0/16').reverse_pointer,
'12.127.in-addr.arpa')
self.assertEqual(self.factory('127.12.34.0/24').reverse_pointer,
'34.12.127.in-addr.arpa')
self.assertEqual(self.factory('127.12.34.56/32').reverse_pointer,
'56.34.12.127.in-addr.arpa')

with self.assertRaises(ipaddress.NetmaskValueError):
self.factory('127.0.0.0/12').reverse_pointer

with self.assertRaises(ipaddress.NetmaskValueError):
self.factory('127.23.0.0/17').reverse_pointer


class NetmaskTestMixin_v6(CommonTestMixin_v6):
"""Input validation on interfaces and networks is very similar"""
Expand Down Expand Up @@ -865,6 +883,24 @@ def test_supernet_of(self):
self.factory('2000:aaa::/48').supernet_of(
self.factory('2000:aaa::/56')))

def test_reverse_pointer(self):
self.assertEqual(self.factory('::/0').reverse_pointer, 'ip6.arpa')
self.assertEqual(self.factory('2000::/4').reverse_pointer, '2.ip6.arpa')
self.assertEqual(self.factory('2000::/8').reverse_pointer,
'0.2.ip6.arpa')
self.assertEqual(self.factory('2001:db8::/32').reverse_pointer,
'8.b.d.0.1.0.0.2.ip6.arpa')
self.assertEqual(self.factory('2001:db8:1234:5678::/64').reverse_pointer,
'8.7.6.5.4.3.2.1.8.b.d.0.1.0.0.2.ip6.arpa')
self.assertEqual(self.factory('2001:db8::1/128').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')

with self.assertRaises(ipaddress.NetmaskValueError):
self.factory('2000::/7').reverse_pointer

with self.assertRaises(ipaddress.NetmaskValueError):
self.factory('2001:db8::10/127').reverse_pointer

class FactoryFunctionErrors(BaseTestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix reverse pointer generation for :class:`ipaddress.IPv4Network` and
:class:`ipaddress.IPv6Network` objects.
Loading