From 908024345e84aedc69d8a55a217fcde0566a4dd9 Mon Sep 17 00:00:00 2001 From: Christian Manivong Date: Sat, 6 Jun 2026 15:00:38 +0200 Subject: [PATCH] fix: get_interfaces_ip() uses overview/export statt addresses/export Das /api/interfaces/addresses/export Endpoint existiert nicht auf allen OPNsense-Versionen. Stattdessen wird /api/interfaces/overview/export genutzt (gleiche Quelle wie get_interfaces()), um addr4/addr6 zu parsen. Co-Authored-By: Claude Sonnet 4.6 --- napalm_opnsense/opnsense.py | 47 ++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/napalm_opnsense/opnsense.py b/napalm_opnsense/opnsense.py index 3b1ca46..22a0064 100644 --- a/napalm_opnsense/opnsense.py +++ b/napalm_opnsense/opnsense.py @@ -230,7 +230,7 @@ class OPNsenseDriver(FirewallDriver): def get_interfaces_ip(self) -> Dict[str, Dict[str, Any]]: """Return IP addresses grouped by interface name. - Calls ``GET /api/interfaces/addresses/export``. + Uses ``GET /api/interfaces/overview/export`` (same source as get_interfaces). Structure:: @@ -241,17 +241,46 @@ class OPNsenseDriver(FirewallDriver): } } """ - data = self._get("/api/interfaces/addresses/export") + import ipaddress + + data = self._get("/api/interfaces/overview/export") + items: list = data if isinstance(data, list) else data.get("interfaces", []) result: Dict[str, Dict[str, Any]] = {} - for item in data.get("items", []): - ifname: str = item["interface"] - ip: str = item["address"] - prefix: int = int(item["prefix"]) - family = "ipv6" if ":" in ip else "ipv4" + def _add(ifname: str, cidr: str, family: str) -> None: + try: + iface_obj = ipaddress.ip_interface(cidr) + ip = str(iface_obj.ip) + prefix = iface_obj.network.prefixlen + result.setdefault(ifname, {"ipv4": {}, "ipv6": {}}) + result[ifname][family][ip] = {"prefix_length": prefix} + except ValueError: + pass - result.setdefault(ifname, {"ipv4": {}, "ipv6": {}}) - result[ifname][family][ip] = {"prefix_length": prefix} + for iface in items: + name: str = iface.get("device") or iface.get("name", "") + if not name: + continue + addr4: str = iface.get("addr4", "") + addr6: str = iface.get("addr6", "") + if addr4: + _add(name, addr4, "ipv4") + if addr6: + _add(name, addr6, "ipv6") + if not addr4: + for entry in iface.get("ipv4") or []: + ip_field = entry.get("ipaddr") or entry.get("ip", "") + subnet = entry.get("subnetbits") or entry.get("prefix_length") + cidr = f"{ip_field}/{subnet}" if subnet and "/" not in ip_field else ip_field + if cidr: + _add(name, cidr, "ipv4") + if not addr6: + for entry in iface.get("ipv6") or []: + ip_field = entry.get("ipaddr") or entry.get("ip", "") + prefix = entry.get("prefixlen") or entry.get("prefix_length") + cidr = f"{ip_field}/{prefix}" if prefix and "/" not in ip_field else ip_field + if cidr: + _add(name, cidr, "ipv6") return result