From 5f790f6bd9178f600da17215048e60d2eccf1788 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 6 Aug 2021 11:15:35 -0500 Subject: [PATCH] Fetch interface index from network integration instead of socket.if_nametoindex in zeroconf (#54152) --- homeassistant/components/network/models.py | 1 + homeassistant/components/network/util.py | 1 + homeassistant/components/zeroconf/__init__.py | 5 ++- tests/components/network/test_init.py | 32 +++++++++++++++++++ tests/components/zeroconf/test_init.py | 4 +++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/network/models.py b/homeassistant/components/network/models.py index a007eb8636d..d3fbc824489 100644 --- a/homeassistant/components/network/models.py +++ b/homeassistant/components/network/models.py @@ -24,6 +24,7 @@ class Adapter(TypedDict): """Configured network adapters.""" name: str + index: int enabled: bool auto: bool default: bool diff --git a/homeassistant/components/network/util.py b/homeassistant/components/network/util.py index eece4b38548..f8b33b3df90 100644 --- a/homeassistant/components/network/util.py +++ b/homeassistant/components/network/util.py @@ -116,6 +116,7 @@ def _ifaddr_adapter_to_ha( return { "name": adapter.nice_name, + "index": adapter.index, "enabled": False, "auto": auto, "default": default, diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index 4c4c81aff32..cdb46318578 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -155,9 +155,8 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool: for ipv4 in ipv4s if not ipaddress.ip_address(ipv4["address"]).is_loopback ) - if adapter["ipv6"]: - ifi = socket.if_nametoindex(adapter["name"]) - interfaces.append(ifi) + if adapter["ipv6"] and adapter["index"] not in interfaces: + interfaces.append(adapter["index"]) ipv6 = True if not any(adapter["enabled"] and adapter["ipv6"] for adapter in adapters): diff --git a/tests/components/network/test_init.py b/tests/components/network/test_init.py index bc4c543842f..6a85f5ea9e8 100644 --- a/tests/components/network/test_init.py +++ b/tests/components/network/test_init.py @@ -21,15 +21,19 @@ def _generate_mock_adapters(): mock_lo0 = Mock(spec=ifaddr.Adapter) mock_lo0.nice_name = "lo0" mock_lo0.ips = [ifaddr.IP("127.0.0.1", 8, "lo0")] + mock_lo0.index = 0 mock_eth0 = Mock(spec=ifaddr.Adapter) mock_eth0.nice_name = "eth0" mock_eth0.ips = [ifaddr.IP(("2001:db8::", 1, 1), 8, "eth0")] + mock_eth0.index = 1 mock_eth1 = Mock(spec=ifaddr.Adapter) mock_eth1.nice_name = "eth1" mock_eth1.ips = [ifaddr.IP("192.168.1.5", 23, "eth1")] + mock_eth1.index = 2 mock_vtun0 = Mock(spec=ifaddr.Adapter) mock_vtun0.nice_name = "vtun0" mock_vtun0.ips = [ifaddr.IP("169.254.3.2", 16, "vtun0")] + mock_vtun0.index = 3 return [mock_eth0, mock_lo0, mock_eth1, mock_vtun0] @@ -51,6 +55,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto assert network_obj.adapters == [ { "auto": False, + "index": 1, "default": False, "enabled": False, "ipv4": [], @@ -65,6 +70,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto "name": "eth0", }, { + "index": 0, "auto": False, "default": False, "enabled": False, @@ -73,6 +79,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto "name": "lo0", }, { + "index": 2, "auto": True, "default": True, "enabled": True, @@ -81,6 +88,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto "name": "eth1", }, { + "index": 3, "auto": False, "default": False, "enabled": False, @@ -107,6 +115,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage assert network_obj.configured_adapters == [] assert network_obj.adapters == [ { + "index": 1, "auto": True, "default": False, "enabled": True, @@ -122,6 +131,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage "name": "eth0", }, { + "index": 0, "auto": False, "default": True, "enabled": False, @@ -130,6 +140,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage "name": "lo0", }, { + "index": 2, "auto": True, "default": False, "enabled": True, @@ -138,6 +149,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage "name": "eth1", }, { + "index": 3, "auto": False, "default": False, "enabled": False, @@ -165,6 +177,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): assert network_obj.adapters == [ { "auto": True, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -180,6 +193,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -188,6 +202,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): }, { "auto": True, + "index": 2, "default": False, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -196,6 +211,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): }, { "auto": False, + "index": 3, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -222,6 +238,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): assert network_obj.adapters == [ { "auto": True, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -237,6 +254,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -245,6 +263,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): }, { "auto": True, + "index": 2, "default": False, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -253,6 +272,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): }, { "auto": False, + "index": 3, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -285,6 +305,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): assert network_obj.adapters == [ { "auto": False, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -300,6 +321,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -308,6 +330,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): }, { "auto": True, + "index": 2, "default": True, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -316,6 +339,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): }, { "auto": False, + "index": 3, "default": False, "enabled": True, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -356,6 +380,7 @@ async def test_interfaces_configured_from_storage_websocket_update( assert response["result"][ATTR_ADAPTERS] == [ { "auto": False, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -371,6 +396,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -379,6 +405,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": True, + "index": 2, "default": True, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -387,6 +414,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 3, "default": False, "enabled": True, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -407,6 +435,7 @@ async def test_interfaces_configured_from_storage_websocket_update( assert response["result"][ATTR_ADAPTERS] == [ { "auto": False, + "index": 1, "default": False, "enabled": False, "ipv4": [], @@ -422,6 +451,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -430,6 +460,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": True, + "index": 2, "default": True, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -438,6 +469,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 3, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], diff --git a/tests/components/zeroconf/test_init.py b/tests/components/zeroconf/test_init.py index 3b8cf883a13..e1e346621fe 100644 --- a/tests/components/zeroconf/test_init.py +++ b/tests/components/zeroconf/test_init.py @@ -725,6 +725,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route( _ADAPTERS_WITH_MANUAL_CONFIG = [ { "auto": True, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -746,6 +747,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ }, { "auto": True, + "index": 2, "default": False, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -754,6 +756,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ }, { "auto": True, + "index": 3, "default": False, "enabled": True, "ipv4": [{"address": "172.16.1.5", "network_prefix": 23}], @@ -769,6 +772,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ }, { "auto": False, + "index": 4, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}],