@@ -1086,7 +1086,11 @@ def is_private(self):
1086
1086
"""
1087
1087
return any (self .network_address in priv_network and
1088
1088
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
+ )
1090
1094
1091
1095
@property
1092
1096
def is_global (self ):
@@ -1333,18 +1337,41 @@ def is_reserved(self):
1333
1337
@property
1334
1338
@functools .lru_cache ()
1335
1339
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:
1337
1343
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`)::
1341
1348
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``.
1342
1353
"""
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
+ )
1344
1358
1345
1359
@property
1346
1360
@functools .lru_cache ()
1347
1361
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
+ """
1348
1375
return self not in self ._constants ._public_network and not self .is_private
1349
1376
1350
1377
@property
@@ -1548,13 +1575,15 @@ class _IPv4Constants:
1548
1575
1549
1576
_public_network = IPv4Network ('100.64.0.0/10' )
1550
1577
1578
+ # Not globally reachable address blocks listed on
1579
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
1551
1580
_private_networks = [
1552
1581
IPv4Network ('0.0.0.0/8' ),
1553
1582
IPv4Network ('10.0.0.0/8' ),
1554
1583
IPv4Network ('127.0.0.0/8' ),
1555
1584
IPv4Network ('169.254.0.0/16' ),
1556
1585
IPv4Network ('172.16.0.0/12' ),
1557
- IPv4Network ('192.0.0.0/29 ' ),
1586
+ IPv4Network ('192.0.0.0/24 ' ),
1558
1587
IPv4Network ('192.0.0.170/31' ),
1559
1588
IPv4Network ('192.0.2.0/24' ),
1560
1589
IPv4Network ('192.168.0.0/16' ),
@@ -1565,6 +1594,11 @@ class _IPv4Constants:
1565
1594
IPv4Network ('255.255.255.255/32' ),
1566
1595
]
1567
1596
1597
+ _private_networks_exceptions = [
1598
+ IPv4Network ('192.0.0.9/32' ),
1599
+ IPv4Network ('192.0.0.10/32' ),
1600
+ ]
1601
+
1568
1602
_reserved_network = IPv4Network ('240.0.0.0/4' )
1569
1603
1570
1604
_unspecified_address = IPv4Address ('0.0.0.0' )
@@ -2007,27 +2041,42 @@ def is_site_local(self):
2007
2041
@property
2008
2042
@functools .lru_cache ()
2009
2043
def is_private (self ):
2010
- """Test if this address is allocated for private networks.
2044
+ """``True`` if the address is defined as not globally reachable by
2045
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2046
+ (for IPv6) with the following exceptions:
2011
2047
2012
- Returns:
2013
- A boolean, True if the address is reserved per
2014
- iana-ipv6-special-registry, or is ipv4_mapped and is
2015
- reserved in the iana-ipv4-special-registry.
2048
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
2049
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2050
+ semantics of the underlying IPv4 addresses and the following condition holds
2051
+ (see :attr:`IPv6Address.ipv4_mapped`)::
2016
2052
2053
+ address.is_private == address.ipv4_mapped.is_private
2054
+
2055
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
2056
+ IPv4 range where they are both ``False``.
2017
2057
"""
2018
2058
ipv4_mapped = self .ipv4_mapped
2019
2059
if ipv4_mapped is not None :
2020
2060
return ipv4_mapped .is_private
2021
- return any (self in net for net in self ._constants ._private_networks )
2061
+ return (
2062
+ any (self in net for net in self ._constants ._private_networks )
2063
+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
2064
+ )
2022
2065
2023
2066
@property
2024
2067
def is_global (self ):
2025
- """Test if this address is allocated for public networks.
2068
+ """``True`` if the address is defined as globally reachable by
2069
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2070
+ (for IPv6) with the following exception:
2026
2071
2027
- Returns:
2028
- A boolean, true if the address is not reserved per
2029
- iana-ipv6-special-registry.
2072
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2073
+ semantics of the underlying IPv4 addresses and the following condition holds
2074
+ (see :attr:`IPv6Address.ipv4_mapped`)::
2075
+
2076
+ address.is_global == address.ipv4_mapped.is_global
2030
2077
2078
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
2079
+ IPv4 range where they are both ``False``.
2031
2080
"""
2032
2081
return not self .is_private
2033
2082
@@ -2268,19 +2317,31 @@ class _IPv6Constants:
2268
2317
2269
2318
_multicast_network = IPv6Network ('ff00::/8' )
2270
2319
2320
+ # Not globally reachable address blocks listed on
2321
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
2271
2322
_private_networks = [
2272
2323
IPv6Network ('::1/128' ),
2273
2324
IPv6Network ('::/128' ),
2274
2325
IPv6Network ('::ffff:0:0/96' ),
2326
+ IPv6Network ('64:ff9b:1::/48' ),
2275
2327
IPv6Network ('100::/64' ),
2276
2328
IPv6Network ('2001::/23' ),
2277
- IPv6Network ('2001:2::/48' ),
2278
2329
IPv6Network ('2001:db8::/32' ),
2279
- IPv6Network ('2001:10::/28' ),
2330
+ # IANA says N/A, let's consider it not globally reachable to be safe
2331
+ IPv6Network ('2002::/16' ),
2280
2332
IPv6Network ('fc00::/7' ),
2281
2333
IPv6Network ('fe80::/10' ),
2282
2334
]
2283
2335
2336
+ _private_networks_exceptions = [
2337
+ IPv6Network ('2001:1::1/128' ),
2338
+ IPv6Network ('2001:1::2/128' ),
2339
+ IPv6Network ('2001:3::/32' ),
2340
+ IPv6Network ('2001:4:112::/48' ),
2341
+ IPv6Network ('2001:20::/28' ),
2342
+ IPv6Network ('2001:30::/28' ),
2343
+ ]
2344
+
2284
2345
_reserved_networks = [
2285
2346
IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
2286
2347
IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments