Do not listen for dhcp packets if the filter cannot be setup (#46006)
This commit is contained in:
parent
097a4e6b59
commit
01e73911d6
2 changed files with 57 additions and 6 deletions
|
@ -7,6 +7,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
from scapy.arch.common import compile_filter
|
||||||
from scapy.config import conf
|
from scapy.config import conf
|
||||||
from scapy.error import Scapy_Exception
|
from scapy.error import Scapy_Exception
|
||||||
from scapy.layers.dhcp import DHCP
|
from scapy.layers.dhcp import DHCP
|
||||||
|
@ -217,6 +218,15 @@ class DHCPWatcher(WatcherBase):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
await _async_verify_working_pcap(self.hass, FILTER)
|
||||||
|
except (Scapy_Exception, ImportError) as ex:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Cannot watch for dhcp packets without a functional packet filter: %s",
|
||||||
|
ex,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
self._sniffer = AsyncSniffer(
|
self._sniffer = AsyncSniffer(
|
||||||
filter=FILTER,
|
filter=FILTER,
|
||||||
started_callback=self._started.set,
|
started_callback=self._started.set,
|
||||||
|
@ -285,3 +295,12 @@ def _verify_l2socket_creation_permission():
|
||||||
# disable scapy promiscuous mode as we do not need it
|
# disable scapy promiscuous mode as we do not need it
|
||||||
conf.sniff_promisc = 0
|
conf.sniff_promisc = 0
|
||||||
conf.L2socket()
|
conf.L2socket()
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_verify_working_pcap(hass, cap_filter):
|
||||||
|
"""Verify we can create a packet filter.
|
||||||
|
|
||||||
|
If we cannot create a filter we will be listening for
|
||||||
|
all traffic which is too intensive.
|
||||||
|
"""
|
||||||
|
await hass.async_add_executor_job(compile_filter, cap_filter)
|
||||||
|
|
|
@ -280,7 +280,11 @@ async def test_setup_and_stop(hass):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
with patch("homeassistant.components.dhcp.AsyncSniffer.start") as start_call:
|
with patch("homeassistant.components.dhcp.AsyncSniffer.start") as start_call, patch(
|
||||||
|
"homeassistant.components.dhcp._verify_l2socket_creation_permission",
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.dhcp.compile_filter",
|
||||||
|
):
|
||||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -325,21 +329,49 @@ async def test_setup_fails_non_root(hass, caplog):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
wait_event = threading.Event()
|
|
||||||
|
|
||||||
with patch("os.geteuid", return_value=10), patch(
|
with patch("os.geteuid", return_value=10), patch(
|
||||||
"homeassistant.components.dhcp._verify_l2socket_creation_permission",
|
"homeassistant.components.dhcp._verify_l2socket_creation_permission",
|
||||||
side_effect=Scapy_Exception,
|
side_effect=Scapy_Exception,
|
||||||
):
|
):
|
||||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
wait_event.set()
|
|
||||||
assert "Cannot watch for dhcp packets without root or CAP_NET_RAW" in caplog.text
|
assert "Cannot watch for dhcp packets without root or CAP_NET_RAW" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup_fails_with_broken_libpcap(hass, caplog):
|
||||||
|
"""Test we abort if libpcap is missing or broken."""
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
dhcp.DOMAIN,
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.dhcp._verify_l2socket_creation_permission",
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.dhcp.compile_filter",
|
||||||
|
side_effect=ImportError,
|
||||||
|
) as compile_filter, patch(
|
||||||
|
"homeassistant.components.dhcp.AsyncSniffer",
|
||||||
|
) as async_sniffer:
|
||||||
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert compile_filter.called
|
||||||
|
assert not async_sniffer.called
|
||||||
|
assert (
|
||||||
|
"Cannot watch for dhcp packets without a functional packet filter"
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_device_tracker_hostname_and_macaddress_exists_before_start(hass):
|
async def test_device_tracker_hostname_and_macaddress_exists_before_start(hass):
|
||||||
"""Test matching based on hostname and macaddress before start."""
|
"""Test matching based on hostname and macaddress before start."""
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue