-- v3: iphlpapi: Fix udp_row_cmp().
From: Paul Gofman pgofman@codeweavers.com
--- dlls/iphlpapi/tests/iphlpapi.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index e8386f52822..7bd079cd458 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -1877,26 +1877,34 @@ static void testGetBestInterfaceEx(void)
static void testGetBestRoute(void) { - DWORD apiReturn; + MIB_IFROW if_row; + DWORD err; MIB_IPFORWARDROW bestRoute;
- apiReturn = GetBestRoute( INADDR_ANY, 0, &bestRoute ); - trace( "GetBestRoute([0.0.0.0], 0, [...]) = %lu\n", apiReturn ); - if (apiReturn == ERROR_NOT_SUPPORTED) + err = GetBestRoute( INADDR_ANY, 0, &bestRoute ); + trace( "GetBestRoute([0.0.0.0], 0, [...]) = %lu\n", err ); + if (err == ERROR_NOT_SUPPORTED) { skip( "GetBestRoute is not supported\n" ); return; }
- apiReturn = GetBestRoute( INADDR_ANY, 0, NULL ); - ok( apiReturn == ERROR_INVALID_PARAMETER, + err = GetBestRoute( INADDR_ANY, 0, NULL ); + ok( err == ERROR_INVALID_PARAMETER, "GetBestRoute([0.0.0.0], 0, NULL) returned %lu, expected %d\n", - apiReturn, ERROR_INVALID_PARAMETER ); + err, ERROR_INVALID_PARAMETER );
- apiReturn = GetBestRoute( INADDR_LOOPBACK, 0, &bestRoute ); - ok( apiReturn == NO_ERROR, + memset( &bestRoute, 0xcc, sizeof(bestRoute)); + err = GetBestRoute( htonl( INADDR_LOOPBACK ), 0, &bestRoute ); + ok( err == NO_ERROR, "GetBestRoute([127.0.0.1], 0, NULL) returned %lu, expected %d\n", - apiReturn, NO_ERROR ); + err, NO_ERROR ); + todo_wine ok( bestRoute.dwForwardMask == 0xffffffff, "got %#lx.\n", bestRoute.dwForwardMask ); + + if_row.dwIndex = bestRoute.dwForwardIfIndex; + err = GetIfEntry( &if_row ); + ok( !err, "got %lu.\n", err ); + todo_wine ok( if_row.dwType == IF_TYPE_SOFTWARE_LOOPBACK, "got %#lx.\n", if_row.dwType ); }
/*
From: Paul Gofman pgofman@codeweavers.com
--- dlls/nsi/tests/Makefile.in | 2 +- dlls/nsi/tests/nsi.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/dlls/nsi/tests/Makefile.in b/dlls/nsi/tests/Makefile.in index 45a7d77668f..50e331b3c3b 100644 --- a/dlls/nsi/tests/Makefile.in +++ b/dlls/nsi/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = nsi.dll -IMPORTS = nsi uuid iphlpapi +IMPORTS = nsi uuid iphlpapi ws2_32
SOURCES = \ nsi.c diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c index 6e10b4edad7..a5f257b9965 100644 --- a/dlls/nsi/tests/nsi.c +++ b/dlls/nsi/tests/nsi.c @@ -709,6 +709,7 @@ static void test_ip_forward( int family ) const NPI_MODULEID *mod = (family == AF_INET) ? &NPI_MS_IPV4_MODULEID : &NPI_MS_IPV6_MODULEID; DWORD key_size = (family == AF_INET) ? sizeof(*key4) : sizeof(*key6); DWORD err, count, i, rw_size, dyn_size; + BOOL ipv4_loopback_mask_found = FALSE, ipv4_loopback_found = FALSE;
winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
@@ -760,6 +761,18 @@ static void test_ip_forward( int family ) ok( row->NextHop.Ipv4.sin_addr.s_addr == key4->next_hop.s_addr, "mismatch\n" ); ok( row->NextHop.Ipv4.sin_port == 0, "mismatch\n" ); ok( row->Age == dyn4->age, "mismatch\n" ); + if (key4->prefix.s_addr == htonl( 0x7f000000 )) + { + ipv4_loopback_mask_found = TRUE; + ok( key4->prefix_len == 8, "got %u.\n", key4->prefix_len ); + ok( !key4->next_hop.s_addr, "got %#lx.\n", key4->next_hop.s_addr ); + } + if (key4->prefix.s_addr == htonl( INADDR_LOOPBACK )) + { + ipv4_loopback_found = TRUE; + ok( key4->prefix_len == 32, "got %u.\n", key4->prefix_len ); + ok( !key4->next_hop.s_addr, "got %#lx.\n", key4->next_hop.s_addr ); + } } else { @@ -796,6 +809,11 @@ static void test_ip_forward( int family )
winetest_pop_context(); } + if (family == AF_INET) + { + todo_wine ok( ipv4_loopback_mask_found, "127.0.0.0/8 not found.\n" ); + todo_wine ok( ipv4_loopback_found, "127.0.0.1/32 not found.\n" ); + }
FreeMibTable( table ); NsiFreeTable( key_tbl, rw_tbl, dyn_tbl, stat_tbl );
From: Paul Gofman pgofman@codeweavers.com
--- dlls/iphlpapi/iphlpapi_main.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 7b0384a7d1f..0de9b5172ab 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2080,10 +2080,15 @@ DWORD WINAPI AllocateAndGetIpAddrTableFromStack( MIB_IPADDRTABLE **table, BOOL s static int ipforward_row_cmp( const void *a, const void *b ) { const MIB_IPFORWARDROW *rowA = a, *rowB = b; - return DWORD_cmp(RtlUlongByteSwap( rowA->dwForwardDest ), RtlUlongByteSwap( rowB->dwForwardDest )) || - DWORD_cmp(rowA->dwForwardProto, rowB->dwForwardProto) || - DWORD_cmp(rowA->dwForwardPolicy, rowB->dwForwardPolicy) || - DWORD_cmp(RtlUlongByteSwap( rowA->dwForwardNextHop ), RtlUlongByteSwap( rowB->dwForwardNextHop )); + int ret; + + if ((ret = DWORD_cmp(RtlUlongByteSwap( rowA->dwForwardDest ), RtlUlongByteSwap( rowB->dwForwardDest )))) + return ret; + if ((ret = DWORD_cmp(rowA->dwForwardProto, rowB->dwForwardProto))) + return ret; + if ((ret = DWORD_cmp(rowA->dwForwardPolicy, rowB->dwForwardPolicy))) + return ret; + return DWORD_cmp(RtlUlongByteSwap( rowA->dwForwardNextHop ), RtlUlongByteSwap( rowB->dwForwardNextHop )); }
/******************************************************************
From: Paul Gofman pgofman@codeweavers.com
--- dlls/iphlpapi/tests/iphlpapi.c | 4 ++-- dlls/nsi/tests/nsi.c | 4 ++-- dlls/nsiproxy.sys/ip.c | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index 7bd079cd458..ebd69a37ad8 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -1899,12 +1899,12 @@ static void testGetBestRoute(void) ok( err == NO_ERROR, "GetBestRoute([127.0.0.1], 0, NULL) returned %lu, expected %d\n", err, NO_ERROR ); - todo_wine ok( bestRoute.dwForwardMask == 0xffffffff, "got %#lx.\n", bestRoute.dwForwardMask ); + ok( bestRoute.dwForwardMask == 0xffffffff, "got %#lx.\n", bestRoute.dwForwardMask );
if_row.dwIndex = bestRoute.dwForwardIfIndex; err = GetIfEntry( &if_row ); ok( !err, "got %lu.\n", err ); - todo_wine ok( if_row.dwType == IF_TYPE_SOFTWARE_LOOPBACK, "got %#lx.\n", if_row.dwType ); + ok( if_row.dwType == IF_TYPE_SOFTWARE_LOOPBACK, "got %#lx.\n", if_row.dwType ); }
/* diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c index a5f257b9965..dc7868ffcb5 100644 --- a/dlls/nsi/tests/nsi.c +++ b/dlls/nsi/tests/nsi.c @@ -811,8 +811,8 @@ static void test_ip_forward( int family ) } if (family == AF_INET) { - todo_wine ok( ipv4_loopback_mask_found, "127.0.0.0/8 not found.\n" ); - todo_wine ok( ipv4_loopback_found, "127.0.0.1/32 not found.\n" ); + ok( ipv4_loopback_mask_found, "127.0.0.0/8 not found.\n" ); + ok( ipv4_loopback_found, "127.0.0.1/32 not found.\n" ); }
FreeMibTable( table ); diff --git a/dlls/nsiproxy.sys/ip.c b/dlls/nsiproxy.sys/ip.c index b7b285e67f6..6d285dcfaca 100644 --- a/dlls/nsiproxy.sys/ip.c +++ b/dlls/nsiproxy.sys/ip.c @@ -59,6 +59,10 @@ #include <netinet6/ip6_var.h> #endif
+#ifdef HAVE_NET_IF_H +# include <net/if.h> +#endif + #ifdef __APPLE__ /* For reasons unknown, Mac OS doesn't export <netinet6/ip6_var.h> to user- * space. We'll have to define the needed struct ourselves. @@ -1495,11 +1499,50 @@ static NTSTATUS ipv4_forward_enumerate_all( void *key_data, UINT key_size, void
#ifdef __linux__ { + struct ifaddrs *addrs, *ifentry; char buf[512], *ptr; struct in_addr mask; UINT rtf_flags; FILE *fp;
+ /* Loopback routes are not present in /proc/net/routes, add those explicitly. */ + if (getifaddrs( &addrs )) return STATUS_NO_MORE_ENTRIES; + for (ifentry = addrs; ifentry; ifentry = ifentry->ifa_next) + { + if (!(ifentry->ifa_flags & IFF_LOOPBACK)) continue; + if (!convert_unix_name_to_luid( ifentry->ifa_name, &entry.luid )) continue; + if (!convert_luid_to_index( &entry.luid, &entry.if_index )) continue; + + if (num < *count) + { + entry.prefix.s_addr = htonl( 0x7f000000 ); + entry.next_hop.s_addr = 0; + entry.metric = 256; + entry.prefix_len = 8; + entry.protocol = MIB_IPPROTO_LOCAL; + entry.loopback = 1; + ipv4_forward_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data ); + key_data = (BYTE *)key_data + key_size; + rw_data = (BYTE *)rw_data + rw_size; + dynamic_data = (BYTE *)dynamic_data + dynamic_size; + static_data = (BYTE *)static_data + static_size; + } + num++; + if (num < *count) + { + entry.prefix.s_addr = htonl( INADDR_LOOPBACK ); + entry.prefix_len = 32; + ipv4_forward_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data ); + key_data = (BYTE *)key_data + key_size; + rw_data = (BYTE *)rw_data + rw_size; + dynamic_data = (BYTE *)dynamic_data + dynamic_size; + static_data = (BYTE *)static_data + static_size; + } + num++; + break; + } + freeifaddrs( addrs ); + if (!(fp = fopen( "/proc/net/route", "r" ))) return STATUS_NOT_SUPPORTED;
/* skip header line */
From: Paul Gofman pgofman@codeweavers.com
Fixes a crash in test_tcp_tables() on up to date Win11. --- dlls/nsi/tests/nsi.c | 4 ++-- include/wine/nsi.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c index dc7868ffcb5..8b480baca39 100644 --- a/dlls/nsi/tests/nsi.c +++ b/dlls/nsi/tests/nsi.c @@ -926,7 +926,7 @@ static void test_tcp_stats( int family ) static void test_tcp_tables( int family, int table_type ) { DWORD dyn_sizes[] = { FIELD_OFFSET(struct nsi_tcp_conn_dynamic, unk[2]), FIELD_OFFSET(struct nsi_tcp_conn_dynamic, unk[3]), - sizeof(struct nsi_tcp_conn_dynamic) }; + FIELD_OFFSET(struct nsi_tcp_conn_dynamic, unk[4]), sizeof(struct nsi_tcp_conn_dynamic) }; DWORD i, err, count, table_num, dyn_size, size; struct nsi_tcp_conn_key *keys; struct nsi_tcp_conn_dynamic *dyn_tbl, *dyn; @@ -949,7 +949,7 @@ static void test_tcp_tables( int family, int table_type ) for (i = 0; i < ARRAY_SIZE(dyn_sizes); i++) { err = NsiAllocateAndGetTable( 1, &NPI_MS_TCP_MODULEID, table_num, (void **)&keys, sizeof(*keys), NULL, 0, - (void **)&dyn_tbl, dyn_sizes[i], (void **)&stat, sizeof(*stat), &count, 0 ); + (void **)&dyn_tbl, dyn_sizes[i] + 4, (void **)&stat, sizeof(*stat), &count, 0 ); if (!err) break; } ok( !err, "got %ld\n", err ); diff --git a/include/wine/nsi.h b/include/wine/nsi.h index e281321b026..5028bbf9e19 100644 --- a/include/wine/nsi.h +++ b/include/wine/nsi.h @@ -376,7 +376,7 @@ struct nsi_tcp_conn_key struct nsi_tcp_conn_dynamic { UINT state; - UINT unk[4]; + UINT unk[5]; };
struct nsi_tcp_conn_static
From: Paul Gofman pgofman@codeweavers.com
--- dlls/iphlpapi/iphlpapi_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 0de9b5172ab..0abf8c55299 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -3552,9 +3552,12 @@ static void udp_row_fill( void *table, DWORD num, ULONG family, ULONG table_clas static int udp_row_cmp( const void *a, const void *b ) { const MIB_UDPROW *rowA = a, *rowB = b; + int ret; + + if ((ret = DWORD_cmp(RtlUlongByteSwap( rowA->dwLocalAddr), RtlUlongByteSwap( rowB->dwLocalAddr )))) + return ret;
- return DWORD_cmp(RtlUlongByteSwap( rowA->dwLocalAddr), RtlUlongByteSwap( rowB->dwLocalAddr )) || - RtlUshortByteSwap( rowA->dwLocalPort ) - RtlUshortByteSwap( rowB->dwLocalPort ); + return RtlUshortByteSwap( rowA->dwLocalPort ) - RtlUshortByteSwap( rowB->dwLocalPort ); }
static int udp6_row_cmp( const void *a, const void *b )
v3:
- add patch "iphlpapi: Fix ipforward_row_cmp()."; - add patch "iphlpapi: Fix udp_row_cmp().".
The initial version of patches resulted in a test failure in inetmib1 tests. While I could not reproduce the failure itself locally I think I figured what's going on. While no test failures the test (with some extra output) wasn't showing much of actual data from ip forward table (while that works on Windows with Wine's inetmib1.dll). inetmib1 depends on the sort in GetIpForwardTable() (so that the result is sorted by dest address as primary key). That sort got broken a while ago with commit 3aa18cc5d01028bda126624ba5f5bfb11ebc4f77 . Adding loopback entries to the forward table accidentally revealed the breakage by failing test on one machine.
"iphlpapi: Fix ipforward_row_cmp()." fixes test failure on Testbot and the actual output of the forward table query in inetmib1. "iphlpapi: Fix udp_row_cmp().". is unrelated but I added it while I am there since there is the same issue.
Could we take the two iphlpapi cmp fixes into a separate MR, that I'll approve first?
Huw Davies (@huw) commented about dlls/nsi/tests/nsi.c:
for (i = 0; i < ARRAY_SIZE(dyn_sizes); i++) { err = NsiAllocateAndGetTable( 1, &NPI_MS_TCP_MODULEID, table_num, (void **)&keys, sizeof(*keys), NULL, 0,
(void **)&dyn_tbl, dyn_sizes[i], (void **)&stat, sizeof(*stat), &count, 0 );
(void **)&dyn_tbl, dyn_sizes[i] + 4, (void **)&stat, sizeof(*stat), &count, 0 );
This doesn't look right.