Expand network util to check for link local addresses (#33499)

This commit is contained in:
J. Nick Koston 2020-04-01 13:24:30 -05:00 committed by GitHub
parent 0cf9268ca8
commit 4a32a0f1da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 9 deletions

View file

@ -1,5 +1,7 @@
"""Config flow to configure Axis devices."""
from ipaddress import ip_address
import voluptuous as vol
from homeassistant import config_entries
@ -11,6 +13,7 @@ from homeassistant.const import (
CONF_PORT,
CONF_USERNAME,
)
from homeassistant.util.network import is_link_local
from .const import CONF_MODEL, DOMAIN
from .device import get_device
@ -129,7 +132,7 @@ class AxisFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if serial_number[:6] not in AXIS_OUI:
return self.async_abort(reason="not_axis_device")
if discovery_info[CONF_HOST].startswith("169.254"):
if is_link_local(ip_address(discovery_info[CONF_HOST])):
return self.async_abort(reason="link_local_address")
await self.async_set_unique_id(serial_number)

View file

@ -1,4 +1,5 @@
"""Config flow for DoorBird integration."""
from ipaddress import ip_address
import logging
import urllib
@ -8,6 +9,7 @@ import voluptuous as vol
from homeassistant import config_entries, core, exceptions
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import callback
from homeassistant.util.network import is_link_local
from .const import CONF_EVENTS, DOORBIRD_OUI
from .const import DOMAIN # pylint:disable=unused-import
@ -90,7 +92,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if macaddress[:6] != DOORBIRD_OUI:
return self.async_abort(reason="not_doorbird_device")
if discovery_info[CONF_HOST].startswith("169.254"):
if is_link_local(ip_address(discovery_info[CONF_HOST])):
return self.async_abort(reason="link_local_address")
await self.async_set_unique_id(macaddress)

View file

@ -1,18 +1,41 @@
"""Network utilities."""
from ipaddress import IPv4Address, IPv6Address, ip_address, ip_network
from ipaddress import IPv4Address, IPv6Address, ip_network
from typing import Union
# IP addresses of loopback interfaces
LOCAL_IPS = (ip_address("127.0.0.1"), ip_address("::1"))
# RFC6890 - IP addresses of loopback interfaces
LOOPBACK_NETWORKS = (
ip_network("127.0.0.0/8"),
ip_network("::1/128"),
ip_network("::ffff:127.0.0.0/104"),
)
# RFC1918 - Address allocation for Private Internets
LOCAL_NETWORKS = (
# RFC6890 - Address allocation for Private Internets
PRIVATE_NETWORKS = (
ip_network("fd00::/8"),
ip_network("10.0.0.0/8"),
ip_network("172.16.0.0/12"),
ip_network("192.168.0.0/16"),
)
# RFC6890 - Link local ranges
LINK_LOCAL_NETWORK = ip_network("169.254.0.0/16")
def is_loopback(address: Union[IPv4Address, IPv6Address]) -> bool:
"""Check if an address is a loopback address."""
return any(address in network for network in LOOPBACK_NETWORKS)
def is_private(address: Union[IPv4Address, IPv6Address]) -> bool:
"""Check if an address is a private address."""
return any(address in network for network in PRIVATE_NETWORKS)
def is_link_local(address: Union[IPv4Address, IPv6Address]) -> bool:
"""Check if an address is link local."""
return address in LINK_LOCAL_NETWORK
def is_local(address: Union[IPv4Address, IPv6Address]) -> bool:
"""Check if an address is local."""
return address in LOCAL_IPS or any(address in network for network in LOCAL_NETWORKS)
"""Check if an address is loopback or private."""
return is_loopback(address) or is_private(address)

View file

@ -0,0 +1,40 @@
"""Test Home Assistant volume utility functions."""
from ipaddress import ip_address
import homeassistant.util.network as network_util
def test_is_loopback():
"""Test loopback addresses."""
assert network_util.is_loopback(ip_address("127.0.0.2"))
assert network_util.is_loopback(ip_address("127.0.0.1"))
assert network_util.is_loopback(ip_address("::1"))
assert network_util.is_loopback(ip_address("::ffff:127.0.0.0"))
assert network_util.is_loopback(ip_address("0:0:0:0:0:0:0:1"))
assert network_util.is_loopback(ip_address("0:0:0:0:0:ffff:7f00:1"))
assert not network_util.is_loopback(ip_address("104.26.5.238"))
assert not network_util.is_loopback(ip_address("2600:1404:400:1a4::356e"))
def test_is_private():
"""Test private addresses."""
assert network_util.is_private(ip_address("192.168.0.1"))
assert network_util.is_private(ip_address("172.16.12.0"))
assert network_util.is_private(ip_address("10.5.43.3"))
assert network_util.is_private(ip_address("fd12:3456:789a:1::1"))
assert not network_util.is_private(ip_address("127.0.0.1"))
assert not network_util.is_private(ip_address("::1"))
def test_is_link_local():
"""Test link local addresses."""
assert network_util.is_link_local(ip_address("169.254.12.3"))
assert not network_util.is_link_local(ip_address("127.0.0.1"))
def test_is_local():
"""Test local addresses."""
assert network_util.is_local(ip_address("192.168.0.1"))
assert network_util.is_local(ip_address("127.0.0.1"))
assert not network_util.is_local(ip_address("208.5.4.2"))