@@ -1086,7 +1086,11 @@ def is_private(self):
10861086 """
10871087 return any (self .network_address in priv_network and
10881088 self .broadcast_address in priv_network
1089- for priv_network in self ._constants ._private_networks )
1089+ for priv_network in self ._constants ._private_networks ) and all (
1090+ self .network_address not in network and
1091+ self .broadcast_address not in network
1092+ for network in self ._constants ._private_networks_exceptions
1093+ )
10901094
10911095 @property
10921096 def is_global (self ):
@@ -1333,18 +1337,41 @@ def is_reserved(self):
13331337 @property
13341338 @functools .lru_cache ()
13351339 def is_private (self ):
1336- """Test if this address is allocated for private networks.
1340+ """``True`` if the address is defined as not globally reachable by
1341+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1342+ (for IPv6) with the following exceptions:
13371343
1338- Returns:
1339- A boolean, True if the address is reserved per
1340- iana-ipv4-special-registry.
1344+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1345+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1346+ semantics of the underlying IPv4 addresses and the following condition holds
1347+ (see :attr:`IPv6Address.ipv4_mapped`)::
13411348
1349+ address.is_private == address.ipv4_mapped.is_private
1350+
1351+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1352+ IPv4 range where they are both ``False``.
13421353 """
1343- return any (self in net for net in self ._constants ._private_networks )
1354+ return (
1355+ any (self in net for net in self ._constants ._private_networks )
1356+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1357+ )
13441358
13451359 @property
13461360 @functools .lru_cache ()
13471361 def is_global (self ):
1362+ """``True`` if the address is defined as globally reachable by
1363+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1364+ (for IPv6) with the following exception:
1365+
1366+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1367+ semantics of the underlying IPv4 addresses and the following condition holds
1368+ (see :attr:`IPv6Address.ipv4_mapped`)::
1369+
1370+ address.is_global == address.ipv4_mapped.is_global
1371+
1372+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1373+ IPv4 range where they are both ``False``.
1374+ """
13481375 return self not in self ._constants ._public_network and not self .is_private
13491376
13501377 @property
@@ -1548,13 +1575,15 @@ class _IPv4Constants:
15481575
15491576 _public_network = IPv4Network ('100.64.0.0/10' )
15501577
1578+ # Not globally reachable address blocks listed on
1579+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
15511580 _private_networks = [
15521581 IPv4Network ('0.0.0.0/8' ),
15531582 IPv4Network ('10.0.0.0/8' ),
15541583 IPv4Network ('127.0.0.0/8' ),
15551584 IPv4Network ('169.254.0.0/16' ),
15561585 IPv4Network ('172.16.0.0/12' ),
1557- IPv4Network ('192.0.0.0/29 ' ),
1586+ IPv4Network ('192.0.0.0/24 ' ),
15581587 IPv4Network ('192.0.0.170/31' ),
15591588 IPv4Network ('192.0.2.0/24' ),
15601589 IPv4Network ('192.168.0.0/16' ),
@@ -1565,6 +1594,11 @@ class _IPv4Constants:
15651594 IPv4Network ('255.255.255.255/32' ),
15661595 ]
15671596
1597+ _private_networks_exceptions = [
1598+ IPv4Network ('192.0.0.9/32' ),
1599+ IPv4Network ('192.0.0.10/32' ),
1600+ ]
1601+
15681602 _reserved_network = IPv4Network ('240.0.0.0/4' )
15691603
15701604 _unspecified_address = IPv4Address ('0.0.0.0' )
@@ -2010,27 +2044,42 @@ def is_site_local(self):
20102044 @property
20112045 @functools .lru_cache ()
20122046 def is_private (self ):
2013- """Test if this address is allocated for private networks.
2047+ """``True`` if the address is defined as not globally reachable by
2048+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2049+ (for IPv6) with the following exceptions:
20142050
2015- Returns:
2016- A boolean, True if the address is reserved per
2017- iana-ipv6-special-registry, or is ipv4_mapped and is
2018- reserved in the iana-ipv4-special-registry.
2051+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
2052+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2053+ semantics of the underlying IPv4 addresses and the following condition holds
2054+ (see :attr:`IPv6Address.ipv4_mapped`)::
20192055
2056+ address.is_private == address.ipv4_mapped.is_private
2057+
2058+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
2059+ IPv4 range where they are both ``False``.
20202060 """
20212061 ipv4_mapped = self .ipv4_mapped
20222062 if ipv4_mapped is not None :
20232063 return ipv4_mapped .is_private
2024- return any (self in net for net in self ._constants ._private_networks )
2064+ return (
2065+ any (self in net for net in self ._constants ._private_networks )
2066+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
2067+ )
20252068
20262069 @property
20272070 def is_global (self ):
2028- """Test if this address is allocated for public networks.
2071+ """``True`` if the address is defined as globally reachable by
2072+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2073+ (for IPv6) with the following exception:
20292074
2030- Returns:
2031- A boolean, true if the address is not reserved per
2032- iana-ipv6-special-registry.
2075+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2076+ semantics of the underlying IPv4 addresses and the following condition holds
2077+ (see :attr:`IPv6Address.ipv4_mapped`)::
2078+
2079+ address.is_global == address.ipv4_mapped.is_global
20332080
2081+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
2082+ IPv4 range where they are both ``False``.
20342083 """
20352084 return not self .is_private
20362085
@@ -2271,19 +2320,31 @@ class _IPv6Constants:
22712320
22722321 _multicast_network = IPv6Network ('ff00::/8' )
22732322
2323+ # Not globally reachable address blocks listed on
2324+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
22742325 _private_networks = [
22752326 IPv6Network ('::1/128' ),
22762327 IPv6Network ('::/128' ),
22772328 IPv6Network ('::ffff:0:0/96' ),
2329+ IPv6Network ('64:ff9b:1::/48' ),
22782330 IPv6Network ('100::/64' ),
22792331 IPv6Network ('2001::/23' ),
2280- IPv6Network ('2001:2::/48' ),
22812332 IPv6Network ('2001:db8::/32' ),
2282- IPv6Network ('2001:10::/28' ),
2333+ # IANA says N/A, let's consider it not globally reachable to be safe
2334+ IPv6Network ('2002::/16' ),
22832335 IPv6Network ('fc00::/7' ),
22842336 IPv6Network ('fe80::/10' ),
22852337 ]
22862338
2339+ _private_networks_exceptions = [
2340+ IPv6Network ('2001:1::1/128' ),
2341+ IPv6Network ('2001:1::2/128' ),
2342+ IPv6Network ('2001:3::/32' ),
2343+ IPv6Network ('2001:4:112::/48' ),
2344+ IPv6Network ('2001:20::/28' ),
2345+ IPv6Network ('2001:30::/28' ),
2346+ ]
2347+
22872348 _reserved_networks = [
22882349 IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
22892350 IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments