From bc2cc42955921c6033086f36ec23710c2529ce63 Mon Sep 17 00:00:00 2001 From: Joshua Roys Date: Sun, 13 Feb 2022 16:24:23 -0500 Subject: [PATCH] Don't abort zeroconf discovery for IPv6-only devices (#66455) --- homeassistant/components/zeroconf/__init__.py | 17 ++++++++++++----- tests/components/zeroconf/test_init.py | 9 +++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index 78ad9b25cd7..ffe4140a434 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -541,9 +541,9 @@ def info_from_service(service: AsyncServiceInfo) -> ZeroconfServiceInfo | None: if isinstance(value, bytes): properties[key] = value.decode("utf-8") - if not (addresses := service.addresses): + if not (addresses := service.addresses or service.parsed_addresses()): return None - if (host := _first_non_link_local_or_v6_address(addresses)) is None: + if (host := _first_non_link_local_address(addresses)) is None: return None return ZeroconfServiceInfo( @@ -557,11 +557,18 @@ def info_from_service(service: AsyncServiceInfo) -> ZeroconfServiceInfo | None: ) -def _first_non_link_local_or_v6_address(addresses: list[bytes]) -> str | None: - """Return the first ipv6 or non-link local ipv4 address.""" +def _first_non_link_local_address( + addresses: list[bytes] | list[str], +) -> str | None: + """Return the first ipv6 or non-link local ipv4 address, preferring IPv4.""" for address in addresses: ip_addr = ip_address(address) - if not ip_addr.is_link_local or ip_addr.version == 6: + if not ip_addr.is_link_local and ip_addr.version == 4: + return str(ip_addr) + # If we didn't find a good IPv4 address, check for IPv6 addresses. + for address in addresses: + ip_addr = ip_address(address) + if not ip_addr.is_link_local and ip_addr.version == 6: return str(ip_addr) return None diff --git a/tests/components/zeroconf/test_init.py b/tests/components/zeroconf/test_init.py index dc007d5c2c5..b7e99991fdd 100644 --- a/tests/components/zeroconf/test_init.py +++ b/tests/components/zeroconf/test_init.py @@ -780,6 +780,15 @@ async def test_info_from_service_prefers_ipv4(hass): assert info.host == "192.168.66.12" +async def test_info_from_service_can_return_ipv6(hass): + """Test that IPv6-only devices can be discovered.""" + service_type = "_test._tcp.local." + service_info = get_service_info_mock(service_type, f"test.{service_type}") + service_info.addresses = ["fd11:1111:1111:0:1234:1234:1234:1234"] + info = zeroconf.info_from_service(service_info) + assert info.host == "fd11:1111:1111:0:1234:1234:1234:1234" + + async def test_get_instance(hass, mock_async_zeroconf): """Test we get an instance.""" assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})