@@ -1302,18 +1302,41 @@ def is_reserved(self):
1302
1302
@property
1303
1303
@functools .lru_cache ()
1304
1304
def is_private (self ):
1305
- """Test if this address is allocated for private networks.
1305
+ """``True`` if the address is defined as not globally reachable by
1306
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1307
+ (for IPv6) with the following exceptions:
1306
1308
1307
- Returns:
1308
- A boolean, True if the address is reserved per
1309
- iana-ipv4-special-registry.
1309
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1310
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1311
+ semantics of the underlying IPv4 addresses and the following condition holds
1312
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1313
+
1314
+ address.is_private == address.ipv4_mapped.is_private
1310
1315
1316
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1317
+ IPv4 range where they are both ``False``.
1311
1318
"""
1312
- return any (self in net for net in self ._constants ._private_networks )
1319
+ return (
1320
+ any (self in net for net in self ._constants ._private_networks )
1321
+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1322
+ )
1313
1323
1314
1324
@property
1315
1325
@functools .lru_cache ()
1316
1326
def is_global (self ):
1327
+ """``True`` if the address is defined as globally reachable by
1328
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1329
+ (for IPv6) with the following exception:
1330
+
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_global == address.ipv4_mapped.is_global
1336
+
1337
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1338
+ IPv4 range where they are both ``False``.
1339
+ """
1317
1340
return self not in self ._constants ._public_network and not self .is_private
1318
1341
1319
1342
@property
@@ -1548,13 +1571,15 @@ class _IPv4Constants:
1548
1571
1549
1572
_public_network = IPv4Network ('100.64.0.0/10' )
1550
1573
1574
+ # Not globally reachable address blocks listed on
1575
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
1551
1576
_private_networks = [
1552
1577
IPv4Network ('0.0.0.0/8' ),
1553
1578
IPv4Network ('10.0.0.0/8' ),
1554
1579
IPv4Network ('127.0.0.0/8' ),
1555
1580
IPv4Network ('169.254.0.0/16' ),
1556
1581
IPv4Network ('172.16.0.0/12' ),
1557
- IPv4Network ('192.0.0.0/29 ' ),
1582
+ IPv4Network ('192.0.0.0/24 ' ),
1558
1583
IPv4Network ('192.0.0.170/31' ),
1559
1584
IPv4Network ('192.0.2.0/24' ),
1560
1585
IPv4Network ('192.168.0.0/16' ),
@@ -1565,6 +1590,11 @@ class _IPv4Constants:
1565
1590
IPv4Network ('255.255.255.255/32' ),
1566
1591
]
1567
1592
1593
+ _private_networks_exceptions = [
1594
+ IPv4Network ('192.0.0.9/32' ),
1595
+ IPv4Network ('192.0.0.10/32' ),
1596
+ ]
1597
+
1568
1598
_reserved_network = IPv4Network ('240.0.0.0/4' )
1569
1599
1570
1600
_unspecified_address = IPv4Address ('0.0.0.0' )
@@ -1953,23 +1983,42 @@ def is_site_local(self):
1953
1983
@property
1954
1984
@functools .lru_cache ()
1955
1985
def is_private (self ):
1956
- """Test if this address is allocated for private networks.
1986
+ """``True`` if the address is defined as not globally reachable by
1987
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1988
+ (for IPv6) with the following exceptions:
1957
1989
1958
- Returns:
1959
- A boolean, True if the address is reserved per
1960
- iana-ipv6-special-registry.
1990
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1991
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1992
+ semantics of the underlying IPv4 addresses and the following condition holds
1993
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1994
+
1995
+ address.is_private == address.ipv4_mapped.is_private
1961
1996
1997
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1998
+ IPv4 range where they are both ``False``.
1962
1999
"""
1963
- return any (self in net for net in self ._constants ._private_networks )
2000
+ ipv4_mapped = self .ipv4_mapped
2001
+ if ipv4_mapped is not None :
2002
+ return ipv4_mapped .is_private
2003
+ return (
2004
+ any (self in net for net in self ._constants ._private_networks )
2005
+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
2006
+ )
1964
2007
1965
2008
@property
1966
2009
def is_global (self ):
1967
- """Test if this address is allocated for public networks.
2010
+ """``True`` if the address is defined as globally reachable by
2011
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2012
+ (for IPv6) with the following exception:
1968
2013
1969
- Returns:
1970
- A boolean, true if the address is not reserved per
1971
- iana-ipv6-special-registry.
2014
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2015
+ semantics of the underlying IPv4 addresses and the following condition holds
2016
+ (see :attr:`IPv6Address.ipv4_mapped`)::
2017
+
2018
+ address.is_global == address.ipv4_mapped.is_global
1972
2019
2020
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
2021
+ IPv4 range where they are both ``False``.
1973
2022
"""
1974
2023
return not self .is_private
1975
2024
@@ -2236,19 +2285,31 @@ class _IPv6Constants:
2236
2285
2237
2286
_multicast_network = IPv6Network ('ff00::/8' )
2238
2287
2288
+ # Not globally reachable address blocks listed on
2289
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
2239
2290
_private_networks = [
2240
2291
IPv6Network ('::1/128' ),
2241
2292
IPv6Network ('::/128' ),
2242
2293
IPv6Network ('::ffff:0:0/96' ),
2294
+ IPv6Network ('64:ff9b:1::/48' ),
2243
2295
IPv6Network ('100::/64' ),
2244
2296
IPv6Network ('2001::/23' ),
2245
- IPv6Network ('2001:2::/48' ),
2246
2297
IPv6Network ('2001:db8::/32' ),
2247
- IPv6Network ('2001:10::/28' ),
2298
+ # IANA says N/A, let's consider it not globally reachable to be safe
2299
+ IPv6Network ('2002::/16' ),
2248
2300
IPv6Network ('fc00::/7' ),
2249
2301
IPv6Network ('fe80::/10' ),
2250
2302
]
2251
2303
2304
+ _private_networks_exceptions = [
2305
+ IPv6Network ('2001:1::1/128' ),
2306
+ IPv6Network ('2001:1::2/128' ),
2307
+ IPv6Network ('2001:3::/32' ),
2308
+ IPv6Network ('2001:4:112::/48' ),
2309
+ IPv6Network ('2001:20::/28' ),
2310
+ IPv6Network ('2001:30::/28' ),
2311
+ ]
2312
+
2252
2313
_reserved_networks = [
2253
2314
IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
2254
2315
IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments