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
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:
@@ -42,6 +42,10 @@ class BsdDriver(OSDriver):
|
||||
#: Prints ``key=value`` lines; see :meth:`_platform`.
|
||||
PLATFORM_COMMAND = ""
|
||||
ROUTES_COMMAND = "netstat -rn"
|
||||
#: Lists listening sockets with their processes; as root it names them all.
|
||||
LISTENING_COMMAND = ""
|
||||
#: Lists them without root, if the command above needs it to see them all.
|
||||
LISTENING_FALLBACK_COMMAND = ""
|
||||
#: lstart is five words; :func:`parse.processes` reads it as one field.
|
||||
PS_COMMAND = "ps -axww -o user,pid,ppid,%cpu,%mem,vsz,rss,stat,lstart,command"
|
||||
|
||||
@@ -245,6 +249,34 @@ class BsdDriver(OSDriver):
|
||||
"""Neither BSD ships an LLDP daemon in its base system."""
|
||||
return {}
|
||||
|
||||
# -- listening sockets -------------------------------------------------------
|
||||
|
||||
def _parse_listening(self, output: str, *, attributed: bool) -> list[dict[str, Any]]:
|
||||
"""Parse :attr:`LISTENING_COMMAND` (*attributed*) or its fallback."""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_listening_sockets(self) -> dict[str, Any]:
|
||||
"""Every listening TCP and bound UDP socket, with the process holding it.
|
||||
|
||||
Same shape as napalm-device-types' ``ListeningSocketsMixin`` -- whose
|
||||
``ss``/cgroup reading is Linux's -- and the same rule: read as root
|
||||
first, and without root when that brings nothing back, which the
|
||||
reading then says (``attributed: False``). BSD has no systemd units or
|
||||
container IDs to name.
|
||||
"""
|
||||
privileged = self.run_command(self.LISTENING_COMMAND, privileged=True)
|
||||
if privileged.exit_code == 0 and privileged.stdout.strip():
|
||||
return {
|
||||
"attributed": True,
|
||||
"sockets": self._parse_listening(privileged.stdout, attributed=True),
|
||||
}
|
||||
command = self.LISTENING_FALLBACK_COMMAND or self.LISTENING_COMMAND
|
||||
plain = self.run_command(command, privileged=False)
|
||||
return {
|
||||
"attributed": False,
|
||||
"sockets": self._parse_listening(plain.stdout, attributed=False),
|
||||
}
|
||||
|
||||
# -- accounts, processes, cron -----------------------------------------------
|
||||
|
||||
def get_users(self) -> list[dict[str, Any]]:
|
||||
|
||||
Reference in New Issue
Block a user