From fb33aadc79ad336f9ed825d10f5a28c7e7d7131a Mon Sep 17 00:00:00 2001 From: malmert Date: Wed, 3 Dec 2025 19:00:26 +0100 Subject: [PATCH] refactor utils --- backend/src/network_sniffer.py | 64 +------------------ .../src/utilities/interface_bridge_helpers.py | 54 ++++++++++++++++ 2 files changed, 55 insertions(+), 63 deletions(-) create mode 100644 backend/src/utilities/interface_bridge_helpers.py diff --git a/backend/src/network_sniffer.py b/backend/src/network_sniffer.py index b128ba7..0c9172b 100644 --- a/backend/src/network_sniffer.py +++ b/backend/src/network_sniffer.py @@ -5,6 +5,7 @@ import os import time from typing import List, Dict, Optional import asyncpg +from src.utilities.interface_bridge_helpers import check_interface_exists, check_interface_up, get_bridge_ports_once from scapy.all import ( Ether, ARP, @@ -67,69 +68,6 @@ def start_async_loop(loop: asyncio.AbstractEventLoop) -> None: # Start the background asyncio loop thread (daemon so it doesn't block process exit). threading.Thread(target=start_async_loop, args=(async_loop,), daemon=True).start() -# ------------------------- -# Interface / bridge helpers -# ------------------------- -def check_interface_exists(iface: str) -> bool: - """ - Check for the presence of a network interface by testing sysfs. - Returns True if /sys/class/net/ exists. - """ - return os.path.isdir(f"/sys/class/net/{iface}") - - -def check_interface_up(iface: str) -> bool: - """ - Check whether the given interface is administratively/operationally up - by reading /sys/class/net//operstate. - Returns False if the path does not exist. - """ - try: - with open(f"/sys/class/net/{iface}/operstate", "r") as f: - return f.read().strip() == "up" - except FileNotFoundError: - return False - - -def _read_bridge_ports_from_sysfs(bridge: str) -> List[str]: - """ - Read bridge member interfaces from sysfs. Internal helper that always reads. - """ - base = f"/sys/class/net/{bridge}/brif/" - if not os.path.isdir(base): - return [] - - try: - ports = [p for p in os.listdir(base) if check_interface_exists(p)] - except Exception: - logger.exception("Error reading bridge ports for %s", bridge) - ports = [] - return ports - - -def get_bridge_ports_once(bridge: str) -> List[str]: - """ - Convenience: read bridge ports (no caching here) used when preparing the fixed snapshot. - """ - return _read_bridge_ports_from_sysfs(bridge) - - -def determine_direction(pkt_iface: str, bridge: str): - """ - Determine ingress/egress using the fixed snapshot of bridge ports - taken when the sniffer started. This avoids reading sysfs for every - packet and prevents noisy logs when bridge ports are static. - - If snapshot is missing (defensive), fall back to a direct sysfs read. - """ - ports = fixed_bridge_ports.get(bridge) - if ports is None: - # Defensive fallback (should not happen if start_afpacket_sniffer was used) - ports = _read_bridge_ports_from_sysfs(bridge) - ingress = pkt_iface - egress = [p for p in ports if p != pkt_iface] - return ingress, egress - # ------------------------------------------------------------------- # Database insertion diff --git a/backend/src/utilities/interface_bridge_helpers.py b/backend/src/utilities/interface_bridge_helpers.py new file mode 100644 index 0000000..50f1740 --- /dev/null +++ b/backend/src/utilities/interface_bridge_helpers.py @@ -0,0 +1,54 @@ +from typing import List, Dict, Optional +import logging +import os + +# ---- Logging ---------------------------------------------------------- +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger("af_packet_sniffer") + +# ------------------------- +# Interface / bridge helpers +# ------------------------- + +def check_interface_exists(iface: str) -> bool: + """ + Check for the presence of a network interface by testing sysfs. + Returns True if /sys/class/net/ exists. + """ + return os.path.isdir(f"/sys/class/net/{iface}") + + +def check_interface_up(iface: str) -> bool: + """ + Check whether the given interface is administratively/operationally up + by reading /sys/class/net//operstate. + Returns False if the path does not exist. + """ + try: + with open(f"/sys/class/net/{iface}/operstate", "r") as f: + return f.read().strip() == "up" + except FileNotFoundError: + return False + + +def _read_bridge_ports_from_sysfs(bridge: str) -> List[str]: + """ + Read bridge member interfaces from sysfs. Internal helper that always reads. + """ + base = f"/sys/class/net/{bridge}/brif/" + if not os.path.isdir(base): + return [] + + try: + ports = [p for p in os.listdir(base) if check_interface_exists(p)] + except Exception: + logger.exception("Error reading bridge ports for %s", bridge) + ports = [] + return ports + + +def get_bridge_ports_once(bridge: str) -> List[str]: + """ + Convenience: read bridge ports (no caching here) used when preparing the fixed snapshot. + """ + return _read_bridge_ports_from_sysfs(bridge)