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/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
This helps Starlight Re:Volver which otherwise usually shows black screen only (through fixing GetBestRoute() for ipv4 loopback address).
/proc/net/route doesn't have entries for loopback. They are also absent in AF_NETLINK socket output, as far as my brief check goes. It is probably possible to see them someone else (e. g., /proc/net/fib_trie) but trying to do so looks like a pointless exercise to me: we can just return forward rows for loopback with the parameters matching Windows as soon as loopback interface is available and we can get an index for it.
The last patch is unrelated, it is just without that nsi/tests crash on up to date Win11 here.