From: Nikolai Abdusamatov <nick.luft.work@gmail.com> Sort the adapter list so Ethernet and Wi-Fi interfaces with valid MAC addresses appear before other adapters, followed by tunnel interfaces and loopback. On macOS, tunnel-like interfaces are classified as IF_TYPE_TUNNEL to match Windows behavior. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59614 --- dlls/nsiproxy.sys/ndis.c | 90 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/dlls/nsiproxy.sys/ndis.c b/dlls/nsiproxy.sys/ndis.c index 8c15186ed53..96bea9b77eb 100644 --- a/dlls/nsiproxy.sys/ndis.c +++ b/dlls/nsiproxy.sys/ndis.c @@ -124,6 +124,35 @@ static struct if_entry *find_entry_from_luid( const NET_LUID *luid ) return NULL; } +static BOOL if_phys_addr_empty( const IF_PHYSICAL_ADDRESS *phys_addr ) +{ + UINT i; + + if (!phys_addr->Length) return TRUE; + for (i = 0; i < phys_addr->Length; i++) + if (phys_addr->Address[i]) return FALSE; + return TRUE; +} + +static UINT if_entry_rank( const struct if_entry *entry ) +{ + if ((entry->if_type == MIB_IF_TYPE_ETHERNET || entry->if_type == IF_TYPE_IEEE80211) && + !if_phys_addr_empty( &entry->if_phys_addr )) + return 0; + if (entry->if_type == IF_TYPE_TUNNEL) return 2; + if (entry->if_type == MIB_IF_TYPE_LOOPBACK) return 3; + return 1; +} + +static BOOL if_entry_before( const struct if_entry *entry, const struct if_entry *other ) +{ + UINT rank = if_entry_rank( entry ); + UINT other_rank = if_entry_rank( other ); + + if (rank != other_rank) return rank < other_rank; + return entry->if_index < other->if_index; +} + #if defined (SIOCGIFHWADDR) && defined (HAVE_STRUCT_IFREQ_IFR_HWADDR) static NTSTATUS if_get_physical( const char *name, UINT *type, IF_PHYSICAL_ADDRESS *phys_addr ) { @@ -274,9 +303,46 @@ static WCHAR *strdupAtoW( const char *str ) return ret; } -static struct if_entry *add_entry( UINT index, char *name ) +#ifdef SIOCGIFFLAGS +static BOOL if_is_tunnel_like( int fd, const char *name, const IF_PHYSICAL_ADDRESS *phys_addr, UINT type ) +{ + int name_len; + struct ifreq ifr; + BOOL ret = FALSE; + + if (type == MIB_IF_TYPE_LOOPBACK || type == MIB_IF_TYPE_PPP || phys_addr->Length) return FALSE; + + name_len = strlen( name ) + 1; + if (name_len > sizeof(ifr.ifr_name)) return FALSE; + if (fd == -1) return FALSE; + + memset( &ifr, 0, sizeof(ifr) ); + memcpy( ifr.ifr_name, name, name_len ); + + if (!ioctl( fd, SIOCGIFFLAGS, &ifr )) + { + if ((ifr.ifr_flags & IFF_POINTOPOINT) || + (type == MIB_IF_TYPE_OTHER && !(ifr.ifr_flags & IFF_BROADCAST))) + ret = TRUE; + } + + return ret; +} +#else +static BOOL if_is_tunnel_like( int fd, const char *name, const IF_PHYSICAL_ADDRESS *phys_addr, UINT type ) +{ + (void)fd; + (void)name; + (void)phys_addr; + (void)type; + return FALSE; +} +#endif + +static struct if_entry *add_entry( UINT index, char *name, int fd ) { struct if_entry *entry; + struct if_entry *iter; int name_len = strlen( name ); if (name_len >= sizeof(entry->if_unix_name)) return NULL; @@ -293,6 +359,8 @@ static struct if_entry *add_entry( UINT index, char *name ) } if_get_physical( name, &entry->if_type, &entry->if_phys_addr ); + if (if_is_tunnel_like( fd, name, &entry->if_phys_addr, entry->if_type )) + entry->if_type = IF_TYPE_TUNNEL; entry->if_luid.Info.Reserved = 0; entry->if_luid.Info.NetLuidIndex = index; @@ -302,6 +370,15 @@ static struct if_entry *add_entry( UINT index, char *name ) entry->if_guid.Data1 = index; memcpy( entry->if_guid.Data4 + 2, "NetDev", 6 ); + LIST_FOR_EACH_ENTRY( iter, &if_list, struct if_entry, entry ) + { + if (if_entry_before( entry, iter )) + { + list_add_before( &iter->entry, &entry->entry ); + return entry; + } + } + list_add_tail( &if_list, &entry->entry ); return entry; } @@ -310,13 +387,22 @@ static unsigned int update_if_table( void ) { struct if_nameindex *indices = if_nameindex(), *entry; unsigned int append_count = 0; +#ifdef SIOCGIFFLAGS + int fd = socket( PF_INET, SOCK_DGRAM, 0 ); +#else + int fd = -1; +#endif for (entry = indices; entry->if_index; entry++) { - if (!find_entry_from_index( entry->if_index ) && add_entry( entry->if_index, entry->if_name )) + if (!find_entry_from_index( entry->if_index ) && add_entry( entry->if_index, entry->if_name, fd )) ++append_count; } +#ifdef SIOCGIFFLAGS + if (fd != -1) close( fd ); +#endif + if_freenameindex( indices ); return append_count; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10553