@@ -1323,18 +1323,41 @@ def is_reserved(self):
1323
1323
@property
1324
1324
@functools .lru_cache ()
1325
1325
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:
1327
1329
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
1331
1336
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``.
1332
1339
"""
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
+ )
1334
1344
1335
1345
@property
1336
1346
@functools .lru_cache ()
1337
1347
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
+ """
1338
1361
return self not in self ._constants ._public_network and not self .is_private
1339
1362
1340
1363
@property
@@ -1538,13 +1561,15 @@ class _IPv4Constants:
1538
1561
1539
1562
_public_network = IPv4Network ('100.64.0.0/10' )
1540
1563
1564
+ # Not globally reachable address blocks listed on
1565
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
1541
1566
_private_networks = [
1542
1567
IPv4Network ('0.0.0.0/8' ),
1543
1568
IPv4Network ('10.0.0.0/8' ),
1544
1569
IPv4Network ('127.0.0.0/8' ),
1545
1570
IPv4Network ('169.254.0.0/16' ),
1546
1571
IPv4Network ('172.16.0.0/12' ),
1547
- IPv4Network ('192.0.0.0/29 ' ),
1572
+ IPv4Network ('192.0.0.0/24 ' ),
1548
1573
IPv4Network ('192.0.0.170/31' ),
1549
1574
IPv4Network ('192.0.2.0/24' ),
1550
1575
IPv4Network ('192.168.0.0/16' ),
@@ -1555,6 +1580,11 @@ class _IPv4Constants:
1555
1580
IPv4Network ('255.255.255.255/32' ),
1556
1581
]
1557
1582
1583
+ _private_networks_exceptions = [
1584
+ IPv4Network ('192.0.0.9/32' ),
1585
+ IPv4Network ('192.0.0.10/32' ),
1586
+ ]
1587
+
1558
1588
_reserved_network = IPv4Network ('240.0.0.0/4' )
1559
1589
1560
1590
_unspecified_address = IPv4Address ('0.0.0.0' )
@@ -1996,27 +2026,42 @@ def is_site_local(self):
1996
2026
@property
1997
2027
@functools .lru_cache ()
1998
2028
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:
2000
2032
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
2005
2039
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``.
2006
2042
"""
2007
2043
ipv4_mapped = self .ipv4_mapped
2008
2044
if ipv4_mapped is not None :
2009
2045
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
+ )
2011
2050
2012
2051
@property
2013
2052
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:
2015
2056
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
2019
2062
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``.
2020
2065
"""
2021
2066
return not self .is_private
2022
2067
@@ -2257,19 +2302,31 @@ class _IPv6Constants:
2257
2302
2258
2303
_multicast_network = IPv6Network ('ff00::/8' )
2259
2304
2305
+ # Not globally reachable address blocks listed on
2306
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
2260
2307
_private_networks = [
2261
2308
IPv6Network ('::1/128' ),
2262
2309
IPv6Network ('::/128' ),
2263
2310
IPv6Network ('::ffff:0:0/96' ),
2311
+ IPv6Network ('64:ff9b:1::/48' ),
2264
2312
IPv6Network ('100::/64' ),
2265
2313
IPv6Network ('2001::/23' ),
2266
- IPv6Network ('2001:2::/48' ),
2267
2314
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' ),
2269
2317
IPv6Network ('fc00::/7' ),
2270
2318
IPv6Network ('fe80::/10' ),
2271
2319
]
2272
2320
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
+
2273
2330
_reserved_networks = [
2274
2331
IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
2275
2332
IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments