From 3b84df525877e2fa39c0e56fdd705262739163cb Mon Sep 17 00:00:00 2001 From: Jesse London Date: Tue, 11 Jun 2024 17:52:56 -0500 Subject: [PATCH] dev: add timeout (default 45s) to nmap in case of unusual networking resolves #54 --- src/netrics/measurement/dev.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/netrics/measurement/dev.py b/src/netrics/measurement/dev.py index 5c9a393..a5addbf 100644 --- a/src/netrics/measurement/dev.py +++ b/src/netrics/measurement/dev.py @@ -7,7 +7,7 @@ import netifaces from descriptors import classonlymethod -from schema import Optional +from schema import Optional, Or from netrics import task @@ -16,6 +16,13 @@ PARAMS = task.schema.extend('connected_devices_arp', { Optional('iface', default='eth0'): task.schema.Text, + + # timeout: seconds after which nmap is killed + # (0, None, False, etc. to disable timeout) + Optional('timeout', default=45): Or(task.schema.GTZero(), + task.schema.falsey, + error='timeout: seconds greater than zero or ' + 'falsey to disable'), }) @@ -32,6 +39,10 @@ def main(nmap, arp, params): local network. The network interface to query may be configured (`iface`). + Should nmap not return within `timeout` seconds, an error + is returned. (This may be disabled by setting a "falsey" timeout + value.) + Devices are recorded by MAC address, their most recent timestamp of detection persisted to task state. @@ -73,11 +84,22 @@ def main(nmap, arp, params): '-sn', # no port scan subnet, ), + timeout=(params.timeout or None), # note: we don't actually want output -- unless there's an error capture_output=True, check=True, text=True, ) + except subprocess.TimeoutExpired as exc: + # nmap took longer than it should / than is allowed + task.log.critical( + cmd=exc.cmd, + elapsed=exc.timeout, + stdout=exc.stdout, + stderr=exc.stderr, + status='timeout', + ) + return task.status.timeout except subprocess.CalledProcessError as exc: # nmap shouldn't really error this way: this is serious task.log.critical(