Skip to content

gh-71456: Treat ::FFFF: addresses as IPv4 for ordering and contains. #1741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
39 changes: 26 additions & 13 deletions Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,10 @@ def get_mixed_type_key(obj):

"""
if isinstance(obj, _BaseNetwork):
obj = obj.ipv4_mapped or obj
return obj._get_networks_key()
elif isinstance(obj, _BaseAddress):
obj = obj.ipv4_mapped or obj
return obj._get_address_key()
return NotImplemented

Expand Down Expand Up @@ -423,6 +425,15 @@ def _check_int_address(self, address):
raise AddressValueError(msg % (address, self._max_prefixlen,
self._version))

@property
def ipv4_mapped(self):
"""Returns an IPv4 address, maybe mapped by RFC 5156 from ::ffff:

Returns:
An IPv4Address instance or None
"""
return None

def _check_packed_address(self, address, expected_len):
address_len = len(address)
if address_len != expected_len:
Expand Down Expand Up @@ -668,6 +679,8 @@ def __hash__(self):
return hash(int(self.network_address) ^ int(self.netmask))

def __contains__(self, other):
if other._version == 6 and self._version == 4:
other = other.ipv4_mapped or other
# always false if one is v4 and the other is v6.
if self._version != other._version:
return False
Expand Down Expand Up @@ -1916,6 +1929,19 @@ def __init__(self, address):
raise AddressValueError("Unexpected '/' in %r" % address)
self._ip = self._ip_int_from_string(addr_str)

@property
def ipv4_mapped(self):
"""Return the IPv4 mapped address.

Returns:
If the IPv6 address is a v4 mapped address, return the
IPv4 mapped address. Return None otherwise.

"""
if (self._ip >> 32) != 0xFFFF:
return None
return IPv4Address(self._ip & 0xFFFFFFFF)

@property
def packed(self):
"""The binary representation of this address."""
Expand Down Expand Up @@ -2012,19 +2038,6 @@ def is_loopback(self):
"""
return self._ip == 1

@property
def ipv4_mapped(self):
"""Return the IPv4 mapped address.

Returns:
If the IPv6 address is a v4 mapped address, return the
IPv4 mapped address. Return None otherwise.

"""
if (self._ip >> 32) != 0xFFFF:
return None
return IPv4Address(self._ip & 0xFFFFFFFF)

@property
def teredo(self):
"""Tuple of embedded teredo IPs.
Expand Down
7 changes: 5 additions & 2 deletions Lib/test/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,10 @@ class ComparisonTests(unittest.TestCase):
v6net = ipaddress.IPv6Network(1)
v6intf = ipaddress.IPv6Interface(1)

v4_addresses = [v4addr, v4intf]
v4mapaddr = ipaddress.IPv6Address('::ffff:0:1')
v4mapnet = ipaddress.IPv6Address('::ffff:0:1')

v4_addresses = [v4addr, v4intf, v4mapaddr]
v4_objects = v4_addresses + [v4net]
v6_addresses = [v6addr, v6intf]
v6_objects = v6_addresses + [v6net]
Expand Down Expand Up @@ -684,7 +687,7 @@ def test_foreign_type_ordering(self):

def test_mixed_type_key(self):
# with get_mixed_type_key, you can sort addresses and network.
v4_ordered = [self.v4addr, self.v4net, self.v4intf]
v4_ordered = [self.v4addr, self.v4mapaddr, self.v4net, self.v4intf]
v6_ordered = [self.v6addr, self.v6net, self.v6intf]
self.assertEqual(v4_ordered,
sorted(self.v4_objects,
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy