[IPv4Network('192.0.2.0/24')]
Args:
- addresses: An iterator of IPv4Network or IPv6Network objects.
+ addresses: An iterable of IPv4Network or IPv6Network objects.
Returns:
An iterator of the collapsed IPv(4|6)Network objects.
def _explode_shorthand_ip_string(self):
"""Expand a shortened IPv6 address.
- Args:
- ip_str: A string, the IPv6 address.
-
Returns:
A string, the expanded IPv6 address.
See RFC 2373 2.7 for details.
"""
+ ipv4_mapped = self.ipv4_mapped
+ if ipv4_mapped is not None:
+ return ipv4_mapped.is_multicast
return self in self._constants._multicast_network
@property
reserved IPv6 Network ranges.
"""
+ ipv4_mapped = self.ipv4_mapped
+ if ipv4_mapped is not None:
+ return ipv4_mapped.is_reserved
return any(self in x for x in self._constants._reserved_networks)
@property
A boolean, True if the address is reserved per RFC 4291.
"""
+ ipv4_mapped = self.ipv4_mapped
+ if ipv4_mapped is not None:
+ return ipv4_mapped.is_link_local
return self in self._constants._linklocal_network
@property
``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
IPv4 range where they are both ``False``.
"""
+ ipv4_mapped = self.ipv4_mapped
+ if ipv4_mapped is not None:
+ return ipv4_mapped.is_global
return not self.is_private
@property
RFC 2373 2.5.2.
"""
+ ipv4_mapped = self.ipv4_mapped
+ if ipv4_mapped is not None:
+ return ipv4_mapped.is_unspecified
return self._ip == 0
@property
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
@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):
IPv6Network('2001:db8::/32'),
# IANA says N/A, let's consider it not globally reachable to be safe
IPv6Network('2002::/16'),
+ # RFC 9637: https://www.rfc-editor.org/rfc/rfc9637.html#section-6-2.2
+ IPv6Network('3fff::/20'),
IPv6Network('fc00::/7'),
IPv6Network('fe80::/10'),
]
self.assertEqual(ipaddress.ip_address('::ffff:c0a8:101').ipv4_mapped,
ipaddress.ip_address('192.168.1.1'))
+ def testIpv4MappedProperties(self):
+ # Test that an IPv4 mapped IPv6 address has
+ # the same properties as an IPv4 address.
+ for addr4 in (
+ "178.62.3.251", # global
+ "169.254.169.254", # link local
+ "127.0.0.1", # loopback
+ "224.0.0.1", # multicast
+ "192.168.0.1", # private
+ "0.0.0.0", # unspecified
+ "100.64.0.1", # public and not global
+ ):
+ with self.subTest(addr4):
+ ipv4 = ipaddress.IPv4Address(addr4)
+ ipv6 = ipaddress.IPv6Address(f"::ffff:{addr4}")
+
+ self.assertEqual(ipv4.is_global, ipv6.is_global)
+ self.assertEqual(ipv4.is_private, ipv6.is_private)
+ self.assertEqual(ipv4.is_reserved, ipv6.is_reserved)
+ self.assertEqual(ipv4.is_multicast, ipv6.is_multicast)
+ self.assertEqual(ipv4.is_unspecified, ipv6.is_unspecified)
+ self.assertEqual(ipv4.is_link_local, ipv6.is_link_local)
+ self.assertEqual(ipv4.is_loopback, ipv6.is_loopback)
+
def testIpv4MappedPrivateCheck(self):
self.assertEqual(
True, ipaddress.ip_address('::ffff:192.168.1.1').is_private)