[PATCH v2 0/1] MR10432: netprofm: Check adapter addresses instead of gateway to guess ipv6 internet connectivity.
-- v2: netprofm: Check adapter addresses instead of gateway to guess ipv6 internet connectivity. https://gitlab.winehq.org/wine/wine/-/merge_requests/10432
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/netprofm/list.c | 51 +++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/dlls/netprofm/list.c b/dlls/netprofm/list.c index 2b156fc562c..cc3fe691e91 100644 --- a/dlls/netprofm/list.c +++ b/dlls/netprofm/list.c @@ -1800,30 +1800,41 @@ static IP_ADAPTER_ADDRESSES *get_network_adapters(void) return NULL; } -static inline BOOL is_link_local( const SOCKADDR *addr ) +static void has_ipv6_address( const IP_ADAPTER_ADDRESSES *aa, BOOL *has_link_local, BOOL *has_global ) { - const struct sockaddr_in6 *in = (const struct sockaddr_in6 *)addr; - return in->sin6_family == AF_INET6 && in->sin6_addr.u.Byte[0] == 0xfe && (in->sin6_addr.u.Byte[1] & 0xc0) == 0x80; + const IP_ADAPTER_UNICAST_ADDRESS *addr = aa->FirstUnicastAddress; + const struct in6_addr *sa6; + + *has_link_local = *has_global = FALSE; + for (addr = aa->FirstUnicastAddress; addr; addr = addr->Next) + { + if (addr->Address.lpSockaddr->sa_family != AF_INET6) continue; + sa6 = &((struct sockaddr_in6 *)addr->Address.lpSockaddr)->sin6_addr; + if (IN6_IS_ADDR_LINKLOCAL(sa6) || IN6_IS_ADDR_SITELOCAL(sa6)) + *has_link_local = TRUE; + else if (!IN6_IS_ADDR_UNSPECIFIED(sa6) && !IN6_IS_ADDR_MULTICAST(sa6) && !IN6_IS_ADDR_LOOPBACK(sa6)) + *has_global = TRUE; + } } -static BOOL has_address( const IP_ADAPTER_ADDRESSES *aa, USHORT family ) +static BOOL has_ipv4_address( const IP_ADAPTER_ADDRESSES *aa ) { const IP_ADAPTER_UNICAST_ADDRESS *addr = aa->FirstUnicastAddress; while (addr) { - if (addr->Address.lpSockaddr->sa_family == family && !is_link_local( addr->Address.lpSockaddr )) + if (addr->Address.lpSockaddr->sa_family == AF_INET) return TRUE; addr = addr->Next; } return FALSE; } -static BOOL has_gateway_address( const IP_ADAPTER_ADDRESSES *aa, USHORT family ) +static BOOL has_ipv4_gateway_address( const IP_ADAPTER_ADDRESSES *aa ) { const IP_ADAPTER_GATEWAY_ADDRESS *addr = aa->FirstGatewayAddress; while (addr) { - if (addr->Address.lpSockaddr->sa_family == family && !is_link_local( addr->Address.lpSockaddr )) + if (addr->Address.lpSockaddr->sa_family == AF_INET) return TRUE; addr = addr->Next; } @@ -1832,6 +1843,7 @@ static BOOL has_gateway_address( const IP_ADAPTER_ADDRESSES *aa, USHORT family ) static void init_networks( struct list_manager *mgr ) { + BOOL has_link_local, has_global; IP_ADAPTER_ADDRESSES *buf, *aa; GUID id; @@ -1862,26 +1874,27 @@ static void init_networks( struct list_manager *mgr ) goto done; } - if (has_address( aa, AF_INET )) - { - network->connected_v4 = VARIANT_TRUE; - connection->connected_v4 = VARIANT_TRUE; - } - if (has_address( aa, AF_INET6 )) + has_ipv6_address( aa, &has_link_local, &has_global ); + if (has_link_local || has_global) { network->connected_v6 = VARIANT_TRUE; connection->connected_v6 = VARIANT_TRUE; } - if (has_gateway_address( aa, AF_INET )) - { - network->connected_to_internet_v4 = VARIANT_TRUE; - connection->connected_to_internet_v4 = VARIANT_TRUE; - } - if (has_gateway_address( aa, AF_INET6 )) + if (has_global) { network->connected_to_internet_v6 = VARIANT_TRUE; connection->connected_to_internet_v6 = VARIANT_TRUE; } + if (has_ipv4_address( aa )) + { + network->connected_v4 = VARIANT_TRUE; + connection->connected_v4 = VARIANT_TRUE; + } + if (has_ipv4_gateway_address( aa )) + { + network->connected_to_internet_v4 = VARIANT_TRUE; + connection->connected_to_internet_v4 = VARIANT_TRUE; + } network->mgr = &mgr->INetworkListManager_iface; INetworkListManager_AddRef( network->mgr ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10432
Hans Leidekker (@hans) commented about dlls/netprofm/list.c:
return NULL; }
static inline BOOL is_link_local( const SOCKADDR *addr )
This function is no longer used. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10432#note_133394
Hans Leidekker (@hans) commented about dlls/netprofm/list.c:
return in->sin6_family == AF_INET6 && in->sin6_addr.u.Byte[0] == 0xfe && (in->sin6_addr.u.Byte[1] & 0xc0) == 0x80; }
-static BOOL has_address( const IP_ADAPTER_ADDRESSES *aa, USHORT family ) +static void has_ipv6_address( const IP_ADAPTER_ADDRESSES *aa, BOOL *has_link_local, BOOL *has_global ) +{ + const IP_ADAPTER_UNICAST_ADDRESS *addr = aa->FirstUnicastAddress; + const struct in6_addr *sa6; + + *has_link_local = *has_global = FALSE; + for (addr = aa->FirstUnicastAddress; addr; addr = addr->Next) + { + if (addr->Address.lpSockaddr->sa_family != AF_INET6) continue; + sa6 = &((struct sockaddr_in6 *)addr->Address.lpSockaddr)->sin6_addr; + if (IN6_IS_ADDR_LINKLOCAL(sa6) || IN6_IS_ADDR_SITELOCAL(sa6)) + *has_link_local = TRUE;
IN6_IS_ADDR_SITELOCAL includes IN6_IS_ADDR_LINKLOCAL so you could omit the latter. Maybe call the parameter has_local or has_sitelocal because it's not just link local? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10432#note_133395
Hans Leidekker (@hans) commented about dlls/netprofm/list.c:
-static BOOL has_address( const IP_ADAPTER_ADDRESSES *aa, USHORT family ) +static void has_ipv6_address( const IP_ADAPTER_ADDRESSES *aa, BOOL *has_link_local, BOOL *has_global ) +{ + const IP_ADAPTER_UNICAST_ADDRESS *addr = aa->FirstUnicastAddress; + const struct in6_addr *sa6; + + *has_link_local = *has_global = FALSE; + for (addr = aa->FirstUnicastAddress; addr; addr = addr->Next) + { + if (addr->Address.lpSockaddr->sa_family != AF_INET6) continue; + sa6 = &((struct sockaddr_in6 *)addr->Address.lpSockaddr)->sin6_addr; + if (IN6_IS_ADDR_LINKLOCAL(sa6) || IN6_IS_ADDR_SITELOCAL(sa6)) + *has_link_local = TRUE; + else if (!IN6_IS_ADDR_UNSPECIFIED(sa6) && !IN6_IS_ADDR_MULTICAST(sa6) && !IN6_IS_ADDR_LOOPBACK(sa6)) + *has_global = TRUE;
We're walking the list of unicast addresses here so if we get a multicast address that's a bug. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10432#note_133396
On Mon Mar 23 18:49:12 2026 +0000, Hans Leidekker wrote:
We're walking the list of unicast addresses here so if we get a multicast address that's a bug. Well, I can certainly remove this but I thought maybe it would be clearer to just check ipv6 address and don't rely on any additional assumptions, since that is easy? I'd even prefer to check for /3 prefix for global address, but global address being 2, 3 is obsolete now and in theory it can start from whatever not explicitly denied.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10432#note_133401
On Mon Mar 23 18:49:12 2026 +0000, Hans Leidekker wrote:
IN6_IS_ADDR_SITELOCAL includes IN6_IS_ADDR_LINKLOCAL so you could omit the latter. Maybe call the parameter has_local or has_sitelocal because it's not just link local? Probably the opposite, IN6_IS_ADDR_LINKLOCAL includes IN6_IS_ADDR_SITELOCAL?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10432#note_133402
On Mon Mar 23 19:10:41 2026 +0000, Paul Gofman wrote:
Probably the opposite, IN6_IS_ADDR_LINKLOCAL includes IN6_IS_ADDR_SITELOCAL? Or, actually, neither, as far as existing macros go:
\`\`\` static inline BOOLEAN WS(IN6_IS_ADDR_LINKLOCAL) ( const IN6_ADDR \*a ) { return ((a-\>s6_bytes\[0\] == 0xfe) && ((a-\>s6_bytes\[1\] & 0xc0) == 0x80)); } static inline BOOLEAN WS(IN6_IS_ADDR_SITELOCAL) ( const IN6_ADDR \*a ) { return ((a-\>s6_bytes\[0\] == 0xfe) && ((a-\>s6_bytes\[1\] & 0xc0) == 0xc0)); } -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10432#note_133403
participants (3)
-
Hans Leidekker (@hans) -
Paul Gofman -
Paul Gofman (@gofman)