diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index e5bdfbb144b65a..cebf8255bc92d7 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -383,6 +383,13 @@ write code that handles both IP versions correctly. Address objects are the embedded ``(server, client)`` IP address pair. For any other address, this property will be ``None``. + .. attribute:: ipv4_translation + + For addresses that appear to be IPv6/IPv4 translation addresses + (starting with ``64:ff9b::/96``) as defined by :RFC:`6052` and :RFC:`8215`, + This property will report the embedded IPv4 address. For any other + address, this property will be ``None``. + .. method:: IPv6Address.__format__(fmt) Refer to the corresponding method documentation in diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 703fa289dda1fb..a6b048c1fc0b8c 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -2189,6 +2189,19 @@ def sixtofour(self): return None return IPv4Address((self._ip >> 80) & 0xFFFFFFFF) + @property + def ipv4_translation(self): + """Return the IPv4/IPv6 Translation embedded address. + + Returns: + The IPv4/IPv6 Translation embedded address if present or None + if the address doesn't appear to contain a translation address. + + """ + if (self._ip >> 96) != 0x64FF9B: + return None + return IPv4Address(self._ip & 0xFFFFFFFF) + class IPv6Interface(IPv6Address): diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index d04012d1afd540..2e1f2cbae57c51 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -2750,6 +2750,16 @@ def testsixtofour(self): sixtofouraddr.sixtofour) self.assertFalse(bad_addr.sixtofour) + def testipv4_translation(self): + embedded_rfc6052 = ipaddress.ip_address('64:ff9b::172.29.45.100') + embedded_rfc8215 = ipaddress.ip_address('64:ff9b:1::172.29.45.100') + bad_addr = ipaddress.ip_address('2001:db8::172.29.45.100') + self.assertEqual(ipaddress.IPv4Address('172.29.45.100'), + embedded_rfc6052.ipv4_translation) + self.assertEqual(ipaddress.IPv4Address('172.29.45.100'), + embedded_rfc8215.ipv4_translation) + self.assertFalse(bad_addr.ipv4_translation) + # issue41004 Hash collisions in IPv4Interface and IPv6Interface def testV4HashIsNotConstant(self): ipv4_address1 = ipaddress.IPv4Interface("1.2.3.4") diff --git a/Misc/NEWS.d/next/Library/2023-04-11-18-02-38.gh-issue-103268.7FN7nG.rst b/Misc/NEWS.d/next/Library/2023-04-11-18-02-38.gh-issue-103268.7FN7nG.rst new file mode 100644 index 00000000000000..fade459e3ad591 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-11-18-02-38.gh-issue-103268.7FN7nG.rst @@ -0,0 +1 @@ +Add property to ipaddress.IPv6Address to report RFC6052/RFC8215 embedded IPv4Address