feat: report listening sockets
CI / test (3.10) (push) Successful in 27s
CI / test (3.11) (push) Successful in 27s
CI / test (3.12) (push) Successful in 37s
CI / test (3.10) (pull_request) Successful in 42s
CI / test (3.11) (pull_request) Successful in 42s
CI / test (3.12) (pull_request) Successful in 38s

get_listening_sockets() in the shape of napalm-device-types'
ListeningSocketsMixin, whose ss/cgroup reading is Linux's, and with its
rule: read as root first, and without root when that brings nothing back,
which the reading reports as `attributed: False`.

- FreeBSD: `sockstat -46lq -P tcp,udp`, which sees every socket either way.
- OpenBSD: `fstat -n` as root (the sockets nothing is connected to; port 0
  is unbound), `netstat -an` without root, as fstat shows a user only
  their own processes; those sockets come without a process.
- Addresses as ss prints them: `*` becomes 0.0.0.0 or :: by family, IPv6
  without brackets, a zone (`fe80::1%lo0`) becomes the interface. One entry
  per socket, the first process holding it.

No get_kernel_facts on purpose: KernelFactsMixin reports a Linux kernel's
modules and CONFIG_ options, which a BSD kernel does not have.

Fixtures recorded on the FreeBSD 15.1 and OpenBSD 7.9 VMs with test
listeners on 127.0.0.1 and ::1 (NetOrk/netork#798).
This commit is contained in:
2026-10-08 09:26:21 +02:00
parent 14afd33798
commit 5f53de0c25
15 changed files with 1009 additions and 0 deletions
+31
View File
@@ -193,3 +193,34 @@ class TestAccountsAndProcesses:
"schedule": "0 4 * * *",
"command": "/home/netork/backup.sh",
} in jobs
class TestListeningSockets:
def test_freebsd_as_root_is_attributed(self):
driver = _driver(FreeBSDDriver, {})
sockstat = _read("freebsd-vm", "sudo_sockstat_46lq_P_tcp_udp.txt")
driver.run_command = lambda command, privileged=False, timeout=60, stdin=None: ( # type: ignore[method-assign]
type("R", (), {"stdout": sockstat, "exit_code": 0})()
)
result = driver.get_listening_sockets()
assert result["attributed"] is True
assert len(result["sockets"]) == 7
def test_openbsd_without_root_falls_back_to_netstat(self):
driver = _driver(OpenBSDDriver, {})
netstat = _read("openbsd-vm", "netstat_an.txt")
calls = []
def run(command, privileged=False, timeout=60, stdin=None):
calls.append((command, privileged))
if privileged: # sudo -n without a password: refused
return type("R", (), {"stdout": "", "exit_code": 1})()
return type("R", (), {"stdout": netstat, "exit_code": 0})()
driver.run_command = run # type: ignore[method-assign]
result = driver.get_listening_sockets()
assert result["attributed"] is False
assert ("tcp", "0.0.0.0", 22) in {
(s["proto"], s["address"], s["port"]) for s in result["sockets"]
}
assert calls == [("fstat -n", True), (OpenBSDDriver.LISTENING_FALLBACK_COMMAND, False)]