refactor utils
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 9s
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 9s
This commit is contained in:
@@ -5,6 +5,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
import asyncpg
|
import asyncpg
|
||||||
|
from src.utilities.interface_bridge_helpers import check_interface_exists, check_interface_up, get_bridge_ports_once
|
||||||
from scapy.all import (
|
from scapy.all import (
|
||||||
Ether,
|
Ether,
|
||||||
ARP,
|
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).
|
# 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()
|
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/<iface> 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/<iface>/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
|
# Database insertion
|
||||||
|
|||||||
54
backend/src/utilities/interface_bridge_helpers.py
Normal file
54
backend/src/utilities/interface_bridge_helpers.py
Normal file
@@ -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/<iface> 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/<iface>/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)
|
||||||
Reference in New Issue
Block a user