8000 util/network: cleanup, further alignment with stdlib · paravoid/home-assistant-core@3072189 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3072189

Browse files
committed
util/network: cleanup, further alignment with stdlib
* Remove the constants LINK_LOCAL_NETWORKS and LOOPBACK_NETWORKS, as they are currently unreferenced, due to the changes made by PR#102019. * Replace the PRIVATE_NETWORKS check with stdlib's is_private() method. Besides a reduction of code, this results in a more comprehensive check, as stdlib includes additional address spaces that were not covered before, and is ever evolving (see, for example, python/cpython#113179). * In contrast with CPython, loopbacks and link-locals are NOT included in our definition of "private", so adjust the code to keep the existing semantics * However, this *does* change the semantics for some address spaces to follow Python's interpretation of IANA, such as marking reserved documentation spaces as "local". Invert the test cases for 198.51.100.0/24 (TEST-NET-2) and 2001:db8::/32 (Documentation) accordingly. * We now need a new globally reachable IP space to use as EXTERNAL_ADDRESSES in test_auth. Use AS112's address space, as it is reserved by IANA, but marked as Globally Reachable. * Finally, inline the last remaining constant IPV6_IPV4_LOOPBACK, and leave a comment that work is underway in CPython by yours truly to reduce the need for it and have is_loopback() subsume it. Further work is required to align the semantics of e.g. what "private" means with stdlib, and replace these seldomly used util functions with stdlib properties across the tree (as is already the case in several integrations), but hopefully this provides a stepping stone towards this direction.
1 parent 370c902 commit 3072189

File tree

3 files changed

+18
-32
lines changed

3 files changed

+18
-32
lines changed

homeassistant/util/network.py

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,16 @@
77

88
import yarl
99

10-
# RFC6890 - IP addresses of loopback interfaces
11-
IPV6_IPV4_LOOPBACK = ip_network("::ffff:127.0.0.0/104")
12-
13-
LOOPBACK_NETWORKS = (
14-
ip_network("127.0.0.0/8"),
15-
ip_network("::1/128"),
16-
IPV6_IPV4_LOOPBACK,
17-
)
18-
19-
# RFC6890 - Address allocation for Private Internets
20-
PRIVATE_NETWORKS = (
21-
ip_network("10.0.0.0/8"),
22-
ip_network("172.16.0.0/12"),
23-
ip_network("192.168.0.0/16"),
24-
ip_network("fd00::/8"),
25-
ip_network("::ffff:10.0.0.0/104"),
26-
ip_network("::ffff:172.16.0.0/108"),
27-
ip_network("::ffff:192.168.0.0/112"),
28-
)
29-
30-
# RFC6890 - Link local ranges
31-
LINK_LOCAL_NETWORKS = (
32-
ip_network("169.254.0.0/16"),
33-
ip_network("fe80::/10"),
34-
ip_network("::ffff:169.254.0.0/112"),
35-
)
36-
3710

3811
def is_loopback(address: IPv4Address | IPv6Address) -> bool:
3912
"""Check if an address is a loopback address."""
40-
return address.is_loopback or address in IPV6_IPV4_LOOPBACK
13+
# the ::ffff: check is a workaround for python/cpython#117566
14+
return address.is_loopback or address in ip_network("::ffff:127.0.0.0/104")
4115

4216

4317
def is_private(address: IPv4Address | IPv6Address) -> bool:
4418
"""Check if an address is a unique local non-loopback address."""
45-
return any(address in network for network in PRIVATE_NETWORKS)
19+
return address.is_private and not is_loopback(address) and not address.is_link_local
4620

4721

4822
def is_link_local(address: IPv4Address | IPv6Address) -> bool:

tests/components/http/test_auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
ip_network("FD01:DB8::1"),
5454
]
5555
TRUSTED_ADDRESSES = ["100.64.0.1", "192.0.2.100", "FD01:DB8::1", "2001:DB8:ABCD::1"]
56-
EXTERNAL_ADDRESSES = ["198.51.100.1", "2001:DB8:FA1::1"]
56+
EXTERNAL_ADDRESSES = ["192.175.48.1", "2620:4f:8000::1"]
5757
UNTRUSTED_ADDRESSES = [*EXTERNAL_ADDRESSES, "127.0.0.1", "::1"]
5858

5959

tests/util/test_network.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,26 @@ def test_is_invalid() -> None:
4343

4444
def test_is_local() -> None:
4545
"""Test local addresses."""
46+
# RFC 1918 space
4647
assert network_util.is_local(ip_address("192.168.0.1"))
48+
# loopback
4749
assert network_util.is_local(ip_address("127.0.0.1"))
50+
assert network_util.is_local(ip_address("::ffff:127.0.0.1"))
51+
assert network_util.is_local(ip_address("::1"))
52+
# IPv6 ULA
4853
assert network_util.is_local(ip_address("fd12:3456:789a:1::1"))
54+
# IPv6 link-local
4955
assert network_util.is_local(ip_address("fe80::1234:5678:abcd"))
56+
# mapped ipv4-to-ipv6
5057
assert network_util.is_local(ip_address("::ffff:192.168.0.1"))
58+
# Documentation/TEST-NET2 IP space, marked as Globally Reachable: False by IANA
59+
assert network_util.is_local(ip_address("198.51.100.1"))
60+
assert network_util.is_local(ip_address("2001:DB8:FA1::1"))
61+
# AS112 space, marked as Globally Reachable: True by IANA
62+
assert not network_util.is_local(ip_address("192.175.48.1"))
63+
assert not network_util.is_local(ip_address("2620:4f:8000::1"))
64+
# random globally routable IP space
5165
assert not network_util.is_local(ip_address("208.5.4.2"))
52-
assert not network_util.is_local(ip_address("198.51.100.1"))
53-
assert not network_util.is_local(ip_address("2001:DB8:FA1::1"))
5466
assert not network_util.is_local(ip_address("::ffff:208.5.4.2"))
5567

5668

0 commit comments

Comments
 (0)
0