Prevent ipv6 discovery messages for Sonos (#139648)

This commit is contained in:
Pete Sage 2025-03-12 15:19:09 -04:00 committed by GitHub
parent bad109dec5
commit 1f6658fca0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 58 additions and 1 deletions

View File

@ -7,6 +7,7 @@ from collections import OrderedDict
from dataclasses import dataclass, field
import datetime
from functools import partial
from ipaddress import AddressValueError, IPv4Address
import logging
import socket
from typing import Any, cast
@ -208,6 +209,14 @@ class SonosDiscoveryManager:
async def async_subscribe_to_zone_updates(self, ip_address: str) -> None:
"""Test subscriptions and create SonosSpeakers based on results."""
try:
_ = IPv4Address(ip_address)
except AddressValueError:
_LOGGER.debug(
"Sonos integration only supports IPv4 addresses, invalid ip_address received: %s",
ip_address,
)
return
soco = SoCo(ip_address)
# Cache now to avoid household ID lookup during first ZoneGroupState processing
await self.hass.async_add_executor_job(

View File

@ -31,6 +31,8 @@ class SonosDiscoveryFlowHandler(DiscoveryFlowHandler[Awaitable[bool]], domain=DO
hostname = discovery_info.hostname
if hostname is None or not hostname.lower().startswith("sonos"):
return self.async_abort(reason="not_sonos_device")
if discovery_info.ip_address.version != 4:
return self.async_abort(reason="not_ipv4_address")
if discovery_manager := self.hass.data.get(DATA_SONOS_DISCOVERY_MANAGER):
host = discovery_info.host
mdns_name = discovery_info.name

View File

@ -8,7 +8,8 @@
"abort": {
"not_sonos_device": "Discovered device is not a Sonos device",
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]",
"not_ipv4_address": "No IPv4 address in SSDP discovery information"
}
},
"issues": {

View File

@ -123,6 +123,22 @@ async def test_zeroconf_form(
assert len(mock_manager.mock_calls) == 2
async def test_zeroconf_form_not_ipv4(
hass: HomeAssistant, zeroconf_payload: ZeroconfServiceInfo
) -> None:
"""Test we pass Zeroconf discoveries to the manager."""
mock_manager = hass.data[DATA_SONOS_DISCOVERY_MANAGER] = MagicMock()
zeroconf_payload.ip_address = ip_address("2001:db8:3333:4444:5555:6666:7777:8888")
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=zeroconf_payload,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "not_ipv4_address"
assert mock_manager.call_count == 0
async def test_ssdp_discovery(hass: HomeAssistant, soco) -> None:
"""Test that SSDP discoveries create a config flow."""

View File

@ -455,3 +455,32 @@ async def test_async_poll_manual_hosts_8(
assert "media_player.garage" in entity_registry.entities
assert "media_player.studio" in entity_registry.entities
await hass.async_block_till_done(wait_background_tasks=True)
async def _setup_hass_ipv6_address_not_supported(hass: HomeAssistant):
await async_setup_component(
hass,
sonos.DOMAIN,
{
"sonos": {
"media_player": {
"interface_addr": "127.0.0.1",
"hosts": ["2001:db8:3333:4444:5555:6666:7777:8888"],
}
}
},
)
await hass.async_block_till_done()
async def test_ipv6_not_supported(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Tests that invalid ipv4 addresses do not generate stack dump."""
with caplog.at_level(logging.DEBUG):
caplog.clear()
await _setup_hass_ipv6_address_not_supported(hass)
await hass.async_block_till_done()
assert "invalid ip_address received" in caplog.text
assert "2001:db8:3333:4444:5555:6666:7777:8888" in caplog.text