Skip to content

Commit fd689d7

Browse files
committed
Make IPv4-mapped IPv6 address properties consistent with IPv4
1 parent 5bd7291 commit fd689d7

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

Lib/ipaddress.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,6 +2043,9 @@ def is_multicast(self):
20432043
See RFC 2373 2.7 for details.
20442044
20452045
"""
2046+
ipv4_mapped = self.ipv4_mapped
2047+
if ipv4_mapped is not None:
2048+
return ipv4_mapped.is_multicast
20462049
return self in self._constants._multicast_network
20472050

20482051
@property
@@ -2054,6 +2057,9 @@ def is_reserved(self):
20542057
reserved IPv6 Network ranges.
20552058
20562059
"""
2060+
ipv4_mapped = self.ipv4_mapped
2061+
if ipv4_mapped is not None:
2062+
return ipv4_mapped.is_reserved
20572063
return any(self in x for x in self._constants._reserved_networks)
20582064

20592065
@property
@@ -2064,6 +2070,9 @@ def is_link_local(self):
20642070
A boolean, True if the address is reserved per RFC 4291.
20652071
20662072
"""
2073+
ipv4_mapped = self.ipv4_mapped
2074+
if ipv4_mapped is not None:
2075+
return ipv4_mapped.is_link_local
20672076
return self in self._constants._linklocal_network
20682077

20692078
@property
@@ -2120,6 +2129,9 @@ def is_global(self):
21202129
``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
21212130
IPv4 range where they are both ``False``.
21222131
"""
2132+
ipv4_mapped = self.ipv4_mapped
2133+
if ipv4_mapped is not None:
2134+
return ipv4_mapped.is_global
21232135
return not self.is_private
21242136

21252137
@property
@@ -2131,6 +2143,9 @@ def is_unspecified(self):
21312143
RFC 2373 2.5.2.
21322144
21332145
"""
2146+
ipv4_mapped = self.ipv4_mapped
2147+
if ipv4_mapped is not None:
2148+
return ipv4_mapped.is_unspecified
21342149
return self._ip == 0
21352150

21362151
@property

Lib/test/test_ipaddress.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,30 @@ def testIpv4Mapped(self):
24402440
self.assertEqual(ipaddress.ip_address('::ffff:c0a8:101').ipv4_mapped,
24412441
ipaddress.ip_address('192.168.1.1'))
24422442

2443+
def testIpv4MappedProperties(self):
2444+
# Test that an IPv4 mapped IPv6 address has
2445+
# the same properties as an IPv4 address.
2446+
for addr4 in (
2447+
"178.62.3.251", # global
2448+
"169.254.169.254", # link local
2449+
"127.0.0.1", # loopback
2450+
"224.0.0.1", # multicast
2451+
"192.168.0.1", # private
2452+
"0.0.0.0", # unspecified
2453+
"100.64.0.1", # public and not global
2454+
):
2455+
with self.subTest(addr4):
2456+
ipv4 = ipaddress.IPv4Address(addr4)
2457+
ipv6 = ipaddress.IPv6Address(f"::ffff:{addr4}")
2458+
2459+
self.assertEqual(ipv4.is_global, ipv6.is_global)
2460+
self.assertEqual(ipv4.is_private, ipv6.is_private)
2461+
self.assertEqual(ipv4.is_reserved, ipv6.is_reserved)
2462+
self.assertEqual(ipv4.is_multicast, ipv6.is_multicast)
2463+
self.assertEqual(ipv4.is_unspecified, ipv6.is_unspecified)
2464+
self.assertEqual(ipv4.is_link_local, ipv6.is_link_local)
2465+
self.assertEqual(ipv4.is_loopback, ipv6.is_loopback)
2466+
24432467
def testIpv4MappedPrivateCheck(self):
24442468
self.assertEqual(
24452469
True, ipaddress.ip_address('::ffff:192.168.1.1').is_private)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Changed IPv4-mapped IPv6 addresses to consistently use the mapped IPv4
2+
address for deciding properties. Affected properties are ``is_multicast``,
3+
``is_reserved``, ``is_link_local``, ``is_global``, and ``is_unspecified``.

0 commit comments

Comments
 (0)