From 053144e7ef99047bb8a3958ed483422b5ede6f35 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Wed, 7 Oct 2026 00:03:09 +0000 Subject: [PATCH] libpcap: get MAC addresses on Darwin, *BSD and illumos correctly It fixes a bug where scapy ended up with "00:00:00:00:00:00" on Darwin and *BSD and with MAC addresses like "04:00:06:03:06:00" (where 4, 6, 3 and 6 were the ifindex, the type, the name length and the address length accordingly) on illumos. With this patch applied scapy extracts the lengths from the sockaddr_dl structure, skips the names and gets the MAC addresses by analogy with what it already did before 07dedfded9ae364ba246be402ebf7b4d2670153b was merged. The bug didn't affect Linux because AF_LINK isn't there so ioctl with SIOCGIFHWADDR is used instead. It was tested on Darwin, FreeBSD, NetBSD, OpenBSD, illumos and Linux. AI-Assisted: no --- scapy/arch/libpcap.py | 13 ++++++++++--- scapy/libs/winpcapy.py | 10 ---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/scapy/arch/libpcap.py b/scapy/arch/libpcap.py index 4c5b2f00efd..bf49ec6d3ef 100644 --- a/scapy/arch/libpcap.py +++ b/scapy/arch/libpcap.py @@ -232,8 +232,15 @@ def load_winpcapy(): elif family == socket.AF_LINK: # Special case: MAC # (AF_LINK is mostly BSD specific) - val = ap.contents.sa_data - mac = str2mac(bytes(bytearray(val[:6]))) + # https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/net/if_dl.h#L93-L112 + # https://github.com/freebsd/freebsd-src/blob/ab7249c288a4d7d09c88f4de705b58a2afbf35f9/sys/net/if_dl.h#L55-L68 + # https://github.com/illumos/illumos-gate/blob/6a2df4aa5381599179ab6afb3165db81960dee35/usr/src/uts/common/net/if_dl.h#L65-L76 + # https://github.com/NetBSD/src/blob/bc2d21a8880597d1affe4ec581e0b65637258dc4/sys/net/if_dl.h#L78-L91 + # https://github.com/openbsd/src/blob/ce063bbc9d6190c8ba255f11feb6910dc3541f29/sys/net/if_dl.h#L56-L70 + sockaddr_dl = ccast(ap, POINTER(c_ubyte)) + nlen = sockaddr_dl[5] + alen = sockaddr_dl[6] + mac = str2mac(bytes(sockaddr_dl[8 + nlen:8 + nlen + alen])) a = a.contents.next continue else: @@ -491,7 +498,7 @@ def load(self): for ifname, dat in conf.cache_pcapiflist.items(): description, ips, flags, mac, itype = dat i += 1 - if LINUX or BSD or SOLARIS and not mac: + if (LINUX or BSD or SOLARIS) and not mac: from scapy.arch.unix import get_if_raw_hwaddr try: itype, _mac = get_if_raw_hwaddr(ifname) diff --git a/scapy/libs/winpcapy.py b/scapy/libs/winpcapy.py index 17a0474a7fc..e6f3f52018c 100644 --- a/scapy/libs/winpcapy.py +++ b/scapy/libs/winpcapy.py @@ -124,16 +124,6 @@ class sockaddr_in6(Structure): ("sin6_addr", 16 * c_ubyte), ("sin6_scope", c_uint32)] - class sockaddr_dl(Structure): - _fields_ = [("sdl_len", c_ubyte), - ("sdl_family", c_ubyte), - ("sdl_index", c_ushort), - ("sdl_type", c_ubyte), - ("sdl_nlen", c_ubyte), - ("sdl_alen", c_ubyte), - ("sdl_slen", c_ubyte), - ("sdl_data", 46 * c_ubyte)] - else: # https://github.com/torvalds/linux/blob/master/include/linux/socket.h # https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2