"""FreeBSD: kenv for the hardware, freebsd-version for base and kernel.""" from __future__ import annotations from napalm_device_types import FingerprintRule from napalm_bsd import parse from napalm_bsd.base import BsdDriver class FreeBSDDriver(BsdDriver): """NAPALM driver for FreeBSD hosts, over SSH.""" TYPE_LABEL = "FreeBSD" VENDOR = "FreeBSD" DRIVER_NAME = "freebsd" SNMP_FINGERPRINT = [FingerprintRule("freebsd", weight=5.0)] # OpenSSH in FreeBSD's base names it in its banner ("OpenSSH_9.9 FreeBSD-20250219"). SSH_FINGERPRINT = [FingerprintRule("freebsd", weight=3.0)] HOSTNAME_COMMAND = "sysctl -n kern.hostname" # Userland and running kernel; both carry the patch level (15.1-RELEASE-p4). OS_VERSION_COMMAND = "freebsd-version -u" KERNEL_COMMAND = "freebsd-version -r" # kenv takes one variable per call, and a missing one fails the call. PLATFORM_COMMAND = ( "for k in maker product serial; do " 'printf "%s=%s\\n" "$k" "$(kenv -q smbios.system.$k)"; done' ) # -W: FreeBSD cuts long destinations to the column width otherwise. ROUTES_COMMAND = "netstat -rnW" # sockstat names the process of every socket it can see; root sees them all. LISTENING_COMMAND = "sockstat -46lq -P tcp,udp" def _parse_listening(self, output: str, *, attributed: bool) -> list[dict]: return parse.sockstat(output) def _os_version(self) -> str: version = super()._os_version() return f"FreeBSD {version}" if version else "" def _hardware(self) -> tuple[str, str, str]: smbios = self._platform() return smbios.get("maker", ""), smbios.get("product", ""), smbios.get("serial", "")