From 6e155c6685a44550bf89e38b8603de82f6d89c2c Mon Sep 17 00:00:00 2001 From: wfurt Date: Tue, 4 Aug 2026 15:42:25 +0200 Subject: [PATCH 1/2] Fix link-layer address enumeration on macOS --- .../Interop.EnumerateInterfaceAddresses.cs | 4 +-- .../System.Native/pal_interfaceaddresses.c | 36 ++++++++++++++++--- .../System.Native/pal_interfaceaddresses.h | 4 +-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs index 99bfb7cba730b5..98b742fd8f47fc 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs @@ -12,7 +12,7 @@ internal static partial class Sys public struct LinkLayerAddressInfo { public int InterfaceIndex; - public InlineArray8 AddressBytes; + public InlineArray12 AddressBytes; public byte NumAddressBytes; private byte __padding; // For native struct-size padding. Does not contain useful data. public ushort HardwareType; @@ -38,7 +38,7 @@ public struct NetworkInterfaceInfo public ushort HardwareType; public byte OperationalState; public byte NumAddressBytes; - public InlineArray8 AddressBytes; + public InlineArray12 AddressBytes; public byte SupportsMulticast; private InlineArray3 __padding; } diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.c b/src/native/libs/System.Native/pal_interfaceaddresses.c index 7bcc865ed177d9..c3c0283686e2a9 100644 --- a/src/native/libs/System.Native/pal_interfaceaddresses.c +++ b/src/native/libs/System.Native/pal_interfaceaddresses.c @@ -109,6 +109,31 @@ static inline uint8_t mask2prefix(uint8_t* mask, int length) } #endif /* TARGET_WASI */ +#if defined(AF_LINK) +static uint8_t GetLinkLayerAddressLength(const struct sockaddr_dl* address, size_t destinationLength) +{ +#if defined(TARGET_SUNOS) + size_t availableLength = sizeof(address->sdl_data) > address->sdl_nlen ? sizeof(address->sdl_data) - address->sdl_nlen : 0; +#else + size_t addressOffset = offsetof(struct sockaddr_dl, sdl_data) + address->sdl_nlen; + size_t availableLength = address->sdl_len > addressOffset ? address->sdl_len - addressOffset : 0; +#endif + size_t addressLength = address->sdl_alen; + + if (addressLength > availableLength) + { + addressLength = availableLength; + } + + if (addressLength > destinationLength) + { + addressLength = destinationLength; + } + + return (uint8_t)addressLength; +} +#endif + int32_t SystemNative_EnumerateInterfaceAddresses(void* context, IPv4AddressFound onIpv4Found, IPv6AddressFound onIpv6Found, @@ -242,7 +267,7 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, LinkLayerAddressInfo lla; memset(&lla, 0, sizeof(LinkLayerAddressInfo)); lla.InterfaceIndex = interfaceIndex; - lla.NumAddressBytes = sadl->sdl_alen; + lla.NumAddressBytes = GetLinkLayerAddressLength(sadl, sizeof(lla.AddressBytes)); lla.HardwareType = MapHardwareType(sadl->sdl_type); #if HAVE_NET_IFMEDIA_H || HAVE_IOS_NET_IFMEDIA_H @@ -265,7 +290,7 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, } } #endif - memcpy_s(&lla.AddressBytes, sizeof_member(LinkLayerAddressInfo, AddressBytes), (uint8_t*)LLADDR(sadl), sadl->sdl_alen); + memcpy_s(&lla.AddressBytes, sizeof_member(LinkLayerAddressInfo, AddressBytes), (uint8_t*)LLADDR(sadl), lla.NumAddressBytes); onLinkLayerFound(context, current->ifa_name, &lla); } } @@ -286,6 +311,9 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, } // See entriesCount, calloc() below. +c_static_assert(sizeof(LinkLayerAddressInfo) == 20); +c_static_assert(sizeof_member(LinkLayerAddressInfo, AddressBytes) == 12); +c_static_assert(sizeof_member(NetworkInterfaceInfo, AddressBytes) == 12); c_static_assert(sizeof(NetworkInterfaceInfo) >= sizeof(IpAddressInfo)); int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInterfaceInfo **interfaceList, int32_t * addressCount, IpAddressInfo **addressList ) @@ -439,8 +467,8 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter struct sockaddr_dl* sadl = (struct sockaddr_dl*)ifaddrsEntry->ifa_addr; nii->HardwareType = MapHardwareType(sadl->sdl_type); - nii->NumAddressBytes = sadl->sdl_alen; - memcpy_s(&nii->AddressBytes, sizeof_member(NetworkInterfaceInfo, AddressBytes), (uint8_t*)LLADDR(sadl), sadl->sdl_alen); + nii->NumAddressBytes = GetLinkLayerAddressLength(sadl, sizeof(nii->AddressBytes)); + memcpy_s(&nii->AddressBytes, sizeof_member(NetworkInterfaceInfo, AddressBytes), (uint8_t*)LLADDR(sadl), nii->NumAddressBytes); #if defined(SIOCGIFMTU) struct ifreq ifr; diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.h b/src/native/libs/System.Native/pal_interfaceaddresses.h index c5dbcd044732a4..7e4f48d83a1f5a 100644 --- a/src/native/libs/System.Native/pal_interfaceaddresses.h +++ b/src/native/libs/System.Native/pal_interfaceaddresses.h @@ -18,7 +18,7 @@ typedef enum typedef struct { uint32_t InterfaceIndex; // The index of the interface to which this address belongs. - uint8_t AddressBytes[8]; // A pointer to the bytes containing the address. + uint8_t AddressBytes[12]; // A pointer to the bytes containing the address. uint8_t NumAddressBytes; // The number of bytes actually stored in the address. uint8_t _padding; uint16_t HardwareType; @@ -42,7 +42,7 @@ typedef struct uint16_t HardwareType; // Interface mapped from L2 to NetworkInterfaceType. uint8_t OperationalState; // Operational status. uint8_t NumAddressBytes; // The number of bytes actually stored in the address. - uint8_t AddressBytes[8]; // Link address. + uint8_t AddressBytes[12]; // Link address. uint8_t SupportsMulticast; // Interface supports multicast. uint8_t _padding[3]; } NetworkInterfaceInfo; From 2f5f97b09fb9987885ff05db38c08f0ec22ec35f Mon Sep 17 00:00:00 2001 From: wfurt Date: Tue, 4 Aug 2026 15:57:49 +0200 Subject: [PATCH 2/2] Address link-layer enumeration review feedback --- src/native/libs/System.Native/pal_interfaceaddresses.c | 10 ++++++++-- src/native/libs/System.Native/pal_interfaceaddresses.h | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.c b/src/native/libs/System.Native/pal_interfaceaddresses.c index c3c0283686e2a9..987014c755e507 100644 --- a/src/native/libs/System.Native/pal_interfaceaddresses.c +++ b/src/native/libs/System.Native/pal_interfaceaddresses.c @@ -290,7 +290,10 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, } } #endif - memcpy_s(&lla.AddressBytes, sizeof_member(LinkLayerAddressInfo, AddressBytes), (uint8_t*)LLADDR(sadl), lla.NumAddressBytes); + if (lla.NumAddressBytes != 0) + { + memcpy_s(&lla.AddressBytes, sizeof_member(LinkLayerAddressInfo, AddressBytes), (uint8_t*)LLADDR(sadl), lla.NumAddressBytes); + } onLinkLayerFound(context, current->ifa_name, &lla); } } @@ -468,7 +471,10 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter nii->HardwareType = MapHardwareType(sadl->sdl_type); nii->NumAddressBytes = GetLinkLayerAddressLength(sadl, sizeof(nii->AddressBytes)); - memcpy_s(&nii->AddressBytes, sizeof_member(NetworkInterfaceInfo, AddressBytes), (uint8_t*)LLADDR(sadl), nii->NumAddressBytes); + if (nii->NumAddressBytes != 0) + { + memcpy_s(&nii->AddressBytes, sizeof_member(NetworkInterfaceInfo, AddressBytes), (uint8_t*)LLADDR(sadl), nii->NumAddressBytes); + } #if defined(SIOCGIFMTU) struct ifreq ifr; diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.h b/src/native/libs/System.Native/pal_interfaceaddresses.h index 7e4f48d83a1f5a..f80add8b948d89 100644 --- a/src/native/libs/System.Native/pal_interfaceaddresses.h +++ b/src/native/libs/System.Native/pal_interfaceaddresses.h @@ -18,7 +18,7 @@ typedef enum typedef struct { uint32_t InterfaceIndex; // The index of the interface to which this address belongs. - uint8_t AddressBytes[12]; // A pointer to the bytes containing the address. + uint8_t AddressBytes[12]; // The bytes containing the address. uint8_t NumAddressBytes; // The number of bytes actually stored in the address. uint8_t _padding; uint16_t HardwareType;