@@ -1275,18 +1275,41 @@ def is_reserved(self):
12751275 @property
12761276 @functools .lru_cache ()
12771277 def is_private (self ):
1278- """Test if this address is allocated for private networks.
1278+ """``True`` if the address is defined as not globally reachable by
1279+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1280+ (for IPv6) with the following exceptions:
12791281
1280- Returns:
1281- A boolean, True if the address is reserved per
1282- iana-ipv4-special-registry.
1282+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1283+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1284+ semantics of the underlying IPv4 addresses and the following condition holds
1285+ (see :attr:`IPv6Address.ipv4_mapped`)::
1286+
1287+ address.is_private == address.ipv4_mapped.is_private
12831288
1289+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1290+ IPv4 range where they are both ``False``.
12841291 """
1285- return any (self in net for net in self ._constants ._private_networks )
1292+ return (
1293+ any (self in net for net in self ._constants ._private_networks )
1294+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1295+ )
12861296
12871297 @property
12881298 @functools .lru_cache ()
12891299 def is_global (self ):
1300+ """``True`` if the address is defined as globally reachable by
1301+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1302+ (for IPv6) with the following exception:
1303+
1304+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1305+ semantics of the underlying IPv4 addresses and the following condition holds
1306+ (see :attr:`IPv6Address.ipv4_mapped`)::
1307+
1308+ address.is_global == address.ipv4_mapped.is_global
1309+
1310+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1311+ IPv4 range where they are both ``False``.
1312+ """
12901313 return self not in self ._constants ._public_network and not self .is_private
12911314
12921315 @property
@@ -1490,13 +1513,15 @@ class _IPv4Constants:
14901513
14911514 _public_network = IPv4Network ('100.64.0.0/10' )
14921515
1516+ # Not globally reachable address blocks listed on
1517+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
14931518 _private_networks = [
14941519 IPv4Network ('0.0.0.0/8' ),
14951520 IPv4Network ('10.0.0.0/8' ),
14961521 IPv4Network ('127.0.0.0/8' ),
14971522 IPv4Network ('169.254.0.0/16' ),
14981523 IPv4Network ('172.16.0.0/12' ),
1499- IPv4Network ('192.0.0.0/29 ' ),
1524+ IPv4Network ('192.0.0.0/24 ' ),
15001525 IPv4Network ('192.0.0.170/31' ),
15011526 IPv4Network ('192.0.2.0/24' ),
15021527 IPv4Network ('192.168.0.0/16' ),
@@ -1507,6 +1532,11 @@ class _IPv4Constants:
15071532 IPv4Network ('255.255.255.255/32' ),
15081533 ]
15091534
1535+ _private_networks_exceptions = [
1536+ IPv4Network ('192.0.0.9/32' ),
1537+ IPv4Network ('192.0.0.10/32' ),
1538+ ]
1539+
15101540 _reserved_network = IPv4Network ('240.0.0.0/4' )
15111541
15121542 _unspecified_address = IPv4Address ('0.0.0.0' )
@@ -1897,23 +1927,42 @@ def is_site_local(self):
18971927 @property
18981928 @functools .lru_cache ()
18991929 def is_private (self ):
1900- """Test if this address is allocated for private networks.
1930+ """``True`` if the address is defined as not globally reachable by
1931+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1932+ (for IPv6) with the following exceptions:
19011933
1902- Returns:
1903- A boolean, True if the address is reserved per
1904- iana-ipv6-special-registry.
1934+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1935+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1936+ semantics of the underlying IPv4 addresses and the following condition holds
1937+ (see :attr:`IPv6Address.ipv4_mapped`)::
1938+
1939+ address.is_private == address.ipv4_mapped.is_private
19051940
1941+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1942+ IPv4 range where they are both ``False``.
19061943 """
1907- return any (self in net for net in self ._constants ._private_networks )
1944+ ipv4_mapped = self .ipv4_mapped
1945+ if ipv4_mapped is not None :
1946+ return ipv4_mapped .is_private
1947+ return (
1948+ any (self in net for net in self ._constants ._private_networks )
1949+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1950+ )
19081951
19091952 @property
19101953 def is_global (self ):
1911- """Test if this address is allocated for public networks.
1954+ """``True`` if the address is defined as globally reachable by
1955+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1956+ (for IPv6) with the following exception:
19121957
1913- Returns:
1914- A boolean, true if the address is not reserved per
1915- iana-ipv6-special-registry.
1958+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1959+ semantics of the underlying IPv4 addresses and the following condition holds
1960+ (see :attr:`IPv6Address.ipv4_mapped`)::
1961+
1962+ address.is_global == address.ipv4_mapped.is_global
19161963
1964+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1965+ IPv4 range where they are both ``False``.
19171966 """
19181967 return not self .is_private
19191968
@@ -2154,19 +2203,31 @@ class _IPv6Constants:
21542203
21552204 _multicast_network = IPv6Network ('ff00::/8' )
21562205
2206+ # Not globally reachable address blocks listed on
2207+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
21572208 _private_networks = [
21582209 IPv6Network ('::1/128' ),
21592210 IPv6Network ('::/128' ),
21602211 IPv6Network ('::ffff:0:0/96' ),
2212+ IPv6Network ('64:ff9b:1::/48' ),
21612213 IPv6Network ('100::/64' ),
21622214 IPv6Network ('2001::/23' ),
2163- IPv6Network ('2001:2::/48' ),
21642215 IPv6Network ('2001:db8::/32' ),
2165- IPv6Network ('2001:10::/28' ),
2216+ # IANA says N/A, let's consider it not globally reachable to be safe
2217+ IPv6Network ('2002::/16' ),
21662218 IPv6Network ('fc00::/7' ),
21672219 IPv6Network ('fe80::/10' ),
21682220 ]
21692221
2222+ _private_networks_exceptions = [
2223+ IPv6Network ('2001:1::1/128' ),
2224+ IPv6Network ('2001:1::2/128' ),
2225+ IPv6Network ('2001:3::/32' ),
2226+ IPv6Network ('2001:4:112::/48' ),
2227+ IPv6Network ('2001:20::/28' ),
2228+ IPv6Network ('2001:30::/28' ),
2229+ ]
2230+
21702231 _reserved_networks = [
21712232 IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
21722233 IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments