@@ -1275,18 +1275,41 @@ def is_reserved(self):
1275
1275
@property
1276
1276
@functools .lru_cache ()
1277
1277
def is_private (self ):
1278
- """Test if this address is allocated for private networks.
1278
+ """``True`` if the address is defined as not globally reachable by
1279
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1280
+ (for IPv6) with the following exceptions:
1279
1281
1280
- Returns:
1281
- A boolean, True if the address is reserved per
1282
- iana-ipv4-special-registry.
1282
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1283
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1284
+ semantics of the underlying IPv4 addresses and the following condition holds
1285
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1286
+
1287
+ address.is_private == address.ipv4_mapped.is_private
1283
1288
1289
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1290
+ IPv4 range where they are both ``False``.
1284
1291
"""
1285
- return any (self in net for net in self ._constants ._private_networks )
1292
+ return (
1293
+ any (self in net for net in self ._constants ._private_networks )
1294
+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1295
+ )
1286
1296
1287
1297
@property
1288
1298
@functools .lru_cache ()
1289
1299
def is_global (self ):
1300
+ """``True`` if the address is defined as globally reachable by
1301
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1302
+ (for IPv6) with the following exception:
1303
+
1304
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1305
+ semantics of the underlying IPv4 addresses and the following condition holds
1306
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1307
+
1308
+ address.is_global == address.ipv4_mapped.is_global
1309
+
1310
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1311
+ IPv4 range where they are both ``False``.
1312
+ """
1290
1313
return self not in self ._constants ._public_network and not self .is_private
1291
1314
1292
1315
@property
@@ -1490,13 +1513,15 @@ class _IPv4Constants:
1490
1513
1491
1514
_public_network = IPv4Network ('100.64.0.0/10' )
1492
1515
1516
+ # Not globally reachable address blocks listed on
1517
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
1493
1518
_private_networks = [
1494
1519
IPv4Network ('0.0.0.0/8' ),
1495
1520
IPv4Network ('10.0.0.0/8' ),
1496
1521
IPv4Network ('127.0.0.0/8' ),
1497
1522
IPv4Network ('169.254.0.0/16' ),
1498
1523
IPv4Network ('172.16.0.0/12' ),
1499
- IPv4Network ('192.0.0.0/29 ' ),
1524
+ IPv4Network ('192.0.0.0/24 ' ),
1500
1525
IPv4Network ('192.0.0.170/31' ),
1501
1526
IPv4Network ('192.0.2.0/24' ),
1502
1527
IPv4Network ('192.168.0.0/16' ),
@@ -1507,6 +1532,11 @@ class _IPv4Constants:
1507
1532
IPv4Network ('255.255.255.255/32' ),
1508
1533
]
1509
1534
1535
+ _private_networks_exceptions = [
1536
+ IPv4Network ('192.0.0.9/32' ),
1537
+ IPv4Network ('192.0.0.10/32' ),
1538
+ ]
1539
+
1510
1540
_reserved_network = IPv4Network ('240.0.0.0/4' )
1511
1541
1512
1542
_unspecified_address = IPv4Address ('0.0.0.0' )
@@ -1897,23 +1927,42 @@ def is_site_local(self):
1897
1927
@property
1898
1928
@functools .lru_cache ()
1899
1929
def is_private (self ):
1900
- """Test if this address is allocated for private networks.
1930
+ """``True`` if the address is defined as not globally reachable by
1931
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1932
+ (for IPv6) with the following exceptions:
1901
1933
1902
- Returns:
1903
- A boolean, True if the address is reserved per
1904
- iana-ipv6-special-registry.
1934
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1935
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1936
+ semantics of the underlying IPv4 addresses and the following condition holds
1937
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1938
+
1939
+ address.is_private == address.ipv4_mapped.is_private
1905
1940
1941
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1942
+ IPv4 range where they are both ``False``.
1906
1943
"""
1907
- return any (self in net for net in self ._constants ._private_networks )
1944
+ ipv4_mapped = self .ipv4_mapped
1945
+ if ipv4_mapped is not None :
1946
+ return ipv4_mapped .is_private
1947
+ return (
1948
+ any (self in net for net in self ._constants ._private_networks )
1949
+ and all (self not in net for net in self ._constants ._private_networks_exceptions )
1950
+ )
1908
1951
1909
1952
@property
1910
1953
def is_global (self ):
1911
- """Test if this address is allocated for public networks.
1954
+ """``True`` if the address is defined as globally reachable by
1955
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1956
+ (for IPv6) with the following exception:
1912
1957
1913
- Returns:
1914
- A boolean, true if the address is not reserved per
1915
- iana-ipv6-special-registry.
1958
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1959
+ semantics of the underlying IPv4 addresses and the following condition holds
1960
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1961
+
1962
+ address.is_global == address.ipv4_mapped.is_global
1916
1963
1964
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1965
+ IPv4 range where they are both ``False``.
1917
1966
"""
1918
1967
return not self .is_private
1919
1968
@@ -2154,19 +2203,31 @@ class _IPv6Constants:
2154
2203
2155
2204
_multicast_network = IPv6Network ('ff00::/8' )
2156
2205
2206
+ # Not globally reachable address blocks listed on
2207
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
2157
2208
_private_networks = [
2158
2209
IPv6Network ('::1/128' ),
2159
2210
IPv6Network ('::/128' ),
2160
2211
IPv6Network ('::ffff:0:0/96' ),
2212
+ IPv6Network ('64:ff9b:1::/48' ),
2161
2213
IPv6Network ('100::/64' ),
2162
2214
IPv6Network ('2001::/23' ),
2163
- IPv6Network ('2001:2::/48' ),
2164
2215
IPv6Network ('2001:db8::/32' ),
2165
- IPv6Network ('2001:10::/28' ),
2216
+ # IANA says N/A, let's consider it not globally reachable to be safe
2217
+ IPv6Network ('2002::/16' ),
2166
2218
IPv6Network ('fc00::/7' ),
2167
2219
IPv6Network ('fe80::/10' ),
2168
2220
]
2169
2221
2222
+ _private_networks_exceptions = [
2223
+ IPv6Network ('2001:1::1/128' ),
2224
+ IPv6Network ('2001:1::2/128' ),
2225
+ IPv6Network ('2001:3::/32' ),
2226
+ IPv6Network ('2001:4:112::/48' ),
2227
+ IPv6Network ('2001:20::/28' ),
2228
+ IPv6Network ('2001:30::/28' ),
2229
+ ]
2230
+
2170
2231
_reserved_networks = [
2171
2232
IPv6Network ('::/8' ), IPv6Network ('100::/8' ),
2172
2233
IPv6Network ('200::/7' ), IPv6Network ('400::/6' ),
0 commit comments