@@ -1323,18 +1323,41 @@ def is_reserved(self):
13231323 @property
13241324 @functools .lru_cache ()
13251325 def is_private (self ):
1326- """Test if this address is allocated for private networks.
1326+ """``True`` if the address is defined as not globally reachable by
1327+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1328+ (for IPv6) with the following exceptions:
13271329
1328- Returns:
1329- A boolean, True if the address is reserved per
1330- iana-ipv4-special-registry.
1330+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1331+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1332+ semantics of the underlying IPv4 addresses and the following condition holds
1333+ (see :attr:`IPv6Address.ipv4_mapped`)::
1334+
1335+ address.is_private == address.ipv4_mapped.is_private
13311336
1337+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1338+ IPv4 range where they are both ``False``.
13321339 """
1333- return any (self in net for net in self ._constants ._private_networks )
1340+ return (
1341+ any (self in net for net in self ._constants ._private_networks )
1342+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1343+ )
13341344
13351345 @property
13361346 @functools .lru_cache ()
13371347 def is_global (self ):
1348+ """``True`` if the address is defined as globally reachable by
1349+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1350+ (for IPv6) with the following exception:
1351+
1352+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1353+ semantics of the underlying IPv4 addresses and the following condition holds
1354+ (see :attr:`IPv6Address.ipv4_mapped`)::
1355+
1356+ address.is_global == address.ipv4_mapped.is_global
1357+
1358+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1359+ IPv4 range where they are both ``False``.
1360+ """
13381361 return self not in self ._constants ._public_network and not self .is_private
13391362
13401363 @property
@@ -1538,13 +1561,15 @@ class _IPv4Constants:
15381561
15391562 _public_network = IPv4Network ('100.64.0.0/10' )
15401563
1564+ # Not globally reachable address blocks listed on
1565+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
15411566 _private_networks = [
15421567 IPv4Network ('0.0.0.0/8' ),
15431568 IPv4Network ('10.0.0.0/8' ),
15441569 IPv4Network ('127.0.0.0/8' ),
15451570 IPv4Network ('169.254.0.0/16' ),
15461571 IPv4Network ('172.16.0.0/12' ),
1547- IPv4Network ('192.0.0.0/29 ' ),
1572+ IPv4Network ('192.0.0.0/24 ' ),
15481573 IPv4Network ('192.0.0.170/31' ),
15491574 IPv4Network ('192.0.2.0/24' ),
15501575 IPv4Network ('192.168.0.0/16' ),
@@ -1555,6 +1580,11 @@ class _IPv4Constants:
15551580 IPv4Network ('255.255.255.255/32' ),
15561581 ]
15571582
1583+ _private_networks_exceptions = [
1584+ IPv4Network ('192.0.0.9/32' ),
1585+ IPv4Network ('192.0.0.10/32' ),
1586+ ]
1587+
15581588 _reserved_network = IPv4Network ('240.0.0.0/4' )
15591589
15601590 _unspecified_address = IPv4Address ('0.0.0.0' )
@@ -1996,27 +2026,42 @@ def is_site_local(self):
19962026 @property
19972027 @functools .lru_cache ()
19982028 def is_private (self ):
1999- """Test if this address is allocated for private networks.
2029+ """``True`` if the address is defined as not globally reachable by
2030+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2031+ (for IPv6) with the following exceptions:
20002032
2001- Returns:
2002- A boolean, True if the address is reserved per
2003- iana-ipv6-special-registry, or is ipv4_mapped and is
2004- reserved in the iana-ipv4-special-registry.
2033+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
2034+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2035+ semantics of the underlying IPv4 addresses and the following condition holds
2036+ (see :attr:`IPv6Address.ipv4_mapped`)::
2037+
2038+ address.is_private == address.ipv4_mapped.is_private
20052039
2040+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
2041+ IPv4 range where they are both ``False``.
20062042 """
20072043 ipv4_mapped = self .ipv4_mapped
20082044 if ipv4_mapped is not None :
20092045 return ipv4_mapped .is_private
2010- return any (self in net for net in self ._constants ._private_networks )
2046+ return (
2047+ any (self in net for net in self ._constants ._private_networks )
2048+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
2049+ )
20112050
20122051 @property
20132052 def is_global (self ):
2014- """Test if this address is allocated for public networks.
2053+ """``True`` if the address is defined as globally reachable by
2054+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2055+ (for IPv6) with the following exception:
20152056
2016- Returns:
2017- A boolean, true if the address is not reserved per
2018- iana-ipv6-special-registry.
2057+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2058+ semantics of the underlying IPv4 addresses and the following condition holds
2059+ (see :attr:`IPv6Address.ipv4_mapped`)::
2060+
2061+ address.is_global == address.ipv4_mapped.is_global
20192062
2063+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
2064+ IPv4 range where they are both ``False``.
20202065 """
20212066 return not self .is_private
20222067
@@ -2257,19 +2302,31 @@ class _IPv6Constants:
22572302
22582303 _multicast_network = IPv6Network ('ff00::/8' )
22592304
2305+ # Not globally reachable address blocks listed on
2306+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
22602307 _private_networks = [
22612308 IPv6Network ('::1/128' ),
22622309 IPv6Network ('::/128' ),
22632310 IPv6Network ('::ffff:0:0/96' ),
2311+ IPv6Network ('64:ff9b:1::/48' ),
22642312 IPv6Network ('100::/64' ),
22652313 IPv6Network ('2001::/23' ),
2266- IPv6Network ('2001:2::/48' ),
22672314 IPv6Network ('2001:db8::/32' ),
2268- IPv6Network ('2001:10::/28' ),
2315+ # IANA says N/A, let's consider it not globally reachable to be safe
2316+ IPv6Network ('2002::/16' ),
22692317 IPv6Network ('fc00::/7' ),
22702318 IPv6Network ('fe80::/10' ),
22712319 ]
22722320
2321+ _private_networks_exceptions = [
2322+ IPv6Network ('2001:1::1/128' ),
2323+ IPv6Network ('2001:1::2/128' ),
2324+ IPv6Network ('2001:3::/32' ),
2325+ IPv6Network ('2001:4:112::/48' ),
2326+ IPv6Network ('2001:20::/28' ),
2327+ IPv6Network ('2001:30::/28' ),
2328+ ]
2329+
22732330 _reserved_networks = [
22742331 IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
22752332 IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments