@@ -1345,18 +1345,41 @@ def is_reserved(self):
13451345 @property
13461346 @functools .lru_cache ()
13471347 def is_private (self ):
1348- """Test if this address is allocated for private networks.
1348+ """``True`` if the address is defined as not globally reachable by
1349+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1350+ (for IPv6) with the following exceptions:
13491351
1350- Returns:
1351- A boolean, True if the address is reserved per
1352- iana-ipv4-special-registry.
1352+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1353+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1354+ semantics of the underlying IPv4 addresses and the following condition holds
1355+ (see :attr:`IPv6Address.ipv4_mapped`)::
1356+
1357+ address.is_private == address.ipv4_mapped.is_private
13531358
1359+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1360+ IPv4 range where they are both ``False``.
13541361 """
1355- return any (self in net for net in self ._constants ._private_networks )
1362+ return (
1363+ any (self in net for net in self ._constants ._private_networks )
1364+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1365+ )
13561366
13571367 @property
13581368 @functools .lru_cache ()
13591369 def is_global (self ):
1370+ """``True`` if the address is defined as globally reachable by
1371+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1372+ (for IPv6) with the following exception:
1373+
1374+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1375+ semantics of the underlying IPv4 addresses and the following condition holds
1376+ (see :attr:`IPv6Address.ipv4_mapped`)::
1377+
1378+ address.is_global == address.ipv4_mapped.is_global
1379+
1380+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1381+ IPv4 range where they are both ``False``.
1382+ """
13601383 return self not in self ._constants ._public_network and not self .is_private
13611384
13621385 @property
@@ -1557,13 +1580,15 @@ class _IPv4Constants:
15571580
15581581 _public_network = IPv4Network ('100.64.0.0/10' )
15591582
1583+ # Not globally reachable address blocks listed on
1584+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
15601585 _private_networks = [
15611586 IPv4Network ('0.0.0.0/8' ),
15621587 IPv4Network ('10.0.0.0/8' ),
15631588 IPv4Network ('127.0.0.0/8' ),
15641589 IPv4Network ('169.254.0.0/16' ),
15651590 IPv4Network ('172.16.0.0/12' ),
1566- IPv4Network ('192.0.0.0/29 ' ),
1591+ IPv4Network ('192.0.0.0/24 ' ),
15671592 IPv4Network ('192.0.0.170/31' ),
15681593 IPv4Network ('192.0.2.0/24' ),
15691594 IPv4Network ('192.168.0.0/16' ),
@@ -1574,6 +1599,11 @@ class _IPv4Constants:
15741599 IPv4Network ('255.255.255.255/32' ),
15751600 ]
15761601
1602+ _private_networks_exceptions = [
1603+ IPv4Network ('192.0.0.9/32' ),
1604+ IPv4Network ('192.0.0.10/32' ),
1605+ ]
1606+
15771607 _reserved_network = IPv4Network ('240.0.0.0/4' )
15781608
15791609 _unspecified_address = IPv4Address ('0.0.0.0' )
@@ -1964,23 +1994,42 @@ def is_site_local(self):
19641994 @property
19651995 @functools .lru_cache ()
19661996 def is_private (self ):
1967- """Test if this address is allocated for private networks.
1997+ """``True`` if the address is defined as not globally reachable by
1998+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1999+ (for IPv6) with the following exceptions:
19682000
1969- Returns:
1970- A boolean, True if the address is reserved per
1971- iana-ipv6-special-registry.
2001+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
2002+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2003+ semantics of the underlying IPv4 addresses and the following condition holds
2004+ (see :attr:`IPv6Address.ipv4_mapped`)::
2005+
2006+ address.is_private == address.ipv4_mapped.is_private
19722007
2008+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
2009+ IPv4 range where they are both ``False``.
19732010 """
1974- return any (self in net for net in self ._constants ._private_networks )
2011+ ipv4_mapped = self .ipv4_mapped
2012+ if ipv4_mapped is not None :
2013+ return ipv4_mapped .is_private
2014+ return (
2015+ any (self in net for net in self ._constants ._private_networks )
2016+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
2017+ )
19752018
19762019 @property
19772020 def is_global (self ):
1978- """Test if this address is allocated for public networks.
2021+ """``True`` if the address is defined as globally reachable by
2022+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2023+ (for IPv6) with the following exception:
19792024
1980- Returns:
1981- A boolean, true if the address is not reserved per
1982- iana-ipv6-special-registry.
2025+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2026+ semantics of the underlying IPv4 addresses and the following condition holds
2027+ (see :attr:`IPv6Address.ipv4_mapped`)::
2028+
2029+ address.is_global == address.ipv4_mapped.is_global
19832030
2031+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
2032+ IPv4 range where they are both ``False``.
19842033 """
19852034 return not self .is_private
19862035
@@ -2217,19 +2266,31 @@ class _IPv6Constants:
22172266
22182267 _multicast_network = IPv6Network ('ff00::/8' )
22192268
2269+ # Not globally reachable address blocks listed on
2270+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
22202271 _private_networks = [
22212272 IPv6Network ('::1/128' ),
22222273 IPv6Network ('::/128' ),
22232274 IPv6Network ('::ffff:0:0/96' ),
2275+ IPv6Network ('64:ff9b:1::/48' ),
22242276 IPv6Network ('100::/64' ),
22252277 IPv6Network ('2001::/23' ),
2226- IPv6Network ('2001:2::/48' ),
22272278 IPv6Network ('2001:db8::/32' ),
2228- IPv6Network ('2001:10::/28' ),
2279+ # IANA says N/A, let's consider it not globally reachable to be safe
2280+ IPv6Network ('2002::/16' ),
22292281 IPv6Network ('fc00::/7' ),
22302282 IPv6Network ('fe80::/10' ),
22312283 ]
22322284
2285+ _private_networks_exceptions = [
2286+ IPv6Network ('2001:1::1/128' ),
2287+ IPv6Network ('2001:1::2/128' ),
2288+ IPv6Network ('2001:3::/32' ),
2289+ IPv6Network ('2001:4:112::/48' ),
2290+ IPv6Network ('2001:20::/28' ),
2291+ IPv6Network ('2001:30::/28' ),
2292+ ]
2293+
22332294 _reserved_networks = [
22342295 IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
22352296 IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments