-- v2: nsi: Match struct nsi_tcp_conn_dynamic size to up to date Win11. nsiproxy.sys: Explicitly add loopback entries to ipv4 forward table on Linux. iphlpapi: Fix ipforward_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