Skip to content
Closed
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
22 changes: 22 additions & 0 deletions Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,19 @@ def is_global(self):
self.broadcast_address in IPv4Network('100.64.0.0/10')) and
not self.is_private)

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

This implements the method described in RFC1035 3.5.

For networks for which no exact domain is matched the covering domain is returned.

>>> IPv4Network('127.0.0.0/13').reverse_pointer
'127.in-addr.arpa
"""
octets = str(self.network_address).split('.')[:self.prefixlen // 8]
return '.'.join(reversed(['arpa', 'in-addr'] + octets))


class _IPv4Constants:
_linklocal_network = IPv4Network('169.254.0.0/16')
Expand Down Expand Up @@ -2262,6 +2275,15 @@ def is_site_local(self):
return (self.network_address.is_site_local and
self.broadcast_address.is_site_local)

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

This implements the method described in RFC3596 2.5.

"""
chars = self.exploded.replace(':', '')[:self.prefixlen // 4]
return '.'.join(reversed(['arpa', 'ip6'] + list(chars)))


class _IPv6Constants:

Expand Down
32 changes: 32 additions & 0 deletions Lib/test/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,26 @@ class InterfaceTestCase_v4(BaseTestCase, NetmaskTestMixin_v4):
class NetworkTestCase_v4(BaseTestCase, NetmaskTestMixin_v4):
factory = ipaddress.IPv4Network

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.128.0.0/9').reverse_pointer,
'127.in-addr.arpa')
self.assertEqual(self.factory('127.254.0.0/15').reverse_pointer,
'127.in-addr.arpa')
self.assertEqual(self.factory('127.255.0.0/16').reverse_pointer,
'255.127.in-addr.arpa')
self.assertEqual(self.factory('127.255.123.0/24').reverse_pointer,
'123.255.127.in-addr.arpa')
self.assertEqual(self.factory('127.255.123.128/25').reverse_pointer,
'123.255.127.in-addr.arpa')
self.assertEqual(self.factory('127.255.123.254/31').reverse_pointer,
'123.255.127.in-addr.arpa')
self.assertEqual(self.factory('127.111.222.255/32').reverse_pointer,
'255.222.111.127.in-addr.arpa')


class NetmaskTestMixin_v6(CommonTestMixin_v6):
"""Input validation on interfaces and networks is very similar"""
Expand Down Expand Up @@ -540,6 +560,18 @@ class InterfaceTestCase_v6(BaseTestCase, NetmaskTestMixin_v6):
class NetworkTestCase_v6(BaseTestCase, NetmaskTestMixin_v6):
factory = ipaddress.IPv6Network

def test_reverse_pointer(self):
self.assertEqual(self.factory('::/0').reverse_pointer,
'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::/48').reverse_pointer,
'4.3.2.1.8.b.d.0.1.0.0.2.ip6.arpa')
self.assertEqual(self.factory('2001:db8:1234::/49').reverse_pointer,
'4.3.2.1.8.b.d.0.1.0.0.2.ip6.arpa')
self.assertEqual(self.factory('2001:db8:1234:5678:90ab:cdef:cafe:b100').reverse_pointer,
'0.0.1.b.e.f.a.c.f.e.d.c.b.a.0.9.8.7.6.5.4.3.2.1.8.b.d.0.1.0.0.2.ip6.arpa')


class FactoryFunctionErrors(BaseTestCase):

Expand Down