gh-117566: fix IPv6Address.is_loopback for IPv4-mapped loopbacks (GH-117567)
While properties like IPv6Address.is_private account for IPv4-mapped IPv6 addresses, such as for example: >>> ipaddress.ip_address("192.168.0.1").is_private True >>> ipaddress.ip_address("::ffff:192.168.0.1").is_private True ...the same doesn't currently apply to the is_loopback property: >>> ipaddress.ip_address("127.0.0.1").is_loopback True >>> ipaddress.ip_address("::ffff:127.0.0.1").is_loopback False At minimum, this inconsistency between different properties is counter-intuitive. Moreover, ::ffff:127.0.0.0/104 is for all intents and purposes a loopback address, and should be treated as such.
This commit is contained in:
parent
eb20a7d12c
commit
fb7f79b4da
@ -2142,6 +2142,9 @@ class IPv6Address(_BaseV6, _BaseAddress):
|
||||
RFC 2373 2.5.3.
|
||||
|
||||
"""
|
||||
ipv4_mapped = self.ipv4_mapped
|
||||
if ipv4_mapped is not None:
|
||||
return ipv4_mapped.is_loopback
|
||||
return self._ip == 1
|
||||
|
||||
@property
|
||||
@ -2258,7 +2261,7 @@ class IPv6Interface(IPv6Address):
|
||||
|
||||
@property
|
||||
def is_loopback(self):
|
||||
return self._ip == 1 and self.network.is_loopback
|
||||
return super().is_loopback and self.network.is_loopback
|
||||
|
||||
|
||||
class IPv6Network(_BaseV6, _BaseNetwork):
|
||||
|
@ -2446,6 +2446,22 @@ class IpaddrUnitTest(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
False, ipaddress.ip_address('::ffff:172.32.0.0').is_private)
|
||||
|
||||
def testIpv4MappedLoopbackCheck(self):
|
||||
# test networks
|
||||
self.assertEqual(True, ipaddress.ip_network(
|
||||
'::ffff:127.100.200.254/128').is_loopback)
|
||||
self.assertEqual(True, ipaddress.ip_network(
|
||||
'::ffff:127.42.0.0/112').is_loopback)
|
||||
self.assertEqual(False, ipaddress.ip_network(
|
||||
'::ffff:128.0.0.0').is_loopback)
|
||||
# test addresses
|
||||
self.assertEqual(True, ipaddress.ip_address(
|
||||
'::ffff:127.100.200.254').is_loopback)
|
||||
self.assertEqual(True, ipaddress.ip_address(
|
||||
'::ffff:127.42.0.0').is_loopback)
|
||||
self.assertEqual(False, ipaddress.ip_address(
|
||||
'::ffff:128.0.0.0').is_loopback)
|
||||
|
||||
def testAddrExclude(self):
|
||||
addr1 = ipaddress.ip_network('10.1.1.0/24')
|
||||
addr2 = ipaddress.ip_network('10.1.1.0/26')
|
||||
|
@ -0,0 +1,3 @@
|
||||
:meth:`ipaddress.IPv6Address.is_loopback` will now return ``True`` for
|
||||
IPv4-mapped loopback addresses, i.e. addresses in the
|
||||
``::ffff:127.0.0.0/104`` address space.
|
Loading…
x
Reference in New Issue
Block a user