mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 09:35:52 +00:00
nsiproxy.sys: Add static ARP entries which are always present on Windows.
Some apps (Roon or SCP: Secret Laboratory are examples) depend on ARP table always containing some entries if there is a network adapter present. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53175 Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
This commit is contained in:
parent
88b77020f2
commit
9a11957bab
|
@ -120,6 +120,11 @@ static const char *ntoa6( IN6_ADDR *ip )
|
||||||
return buffers[i];
|
return buffers[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD ipv4_addr( BYTE b1, BYTE b2, BYTE b3, BYTE b4 )
|
||||||
|
{
|
||||||
|
return htonl( (b1 << 24) | (b2 << 16) | (b3 << 8) | b4 );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
still-to-be-tested 98-only functions:
|
still-to-be-tested 98-only functions:
|
||||||
GetUniDirectionalAdapterInfo
|
GetUniDirectionalAdapterInfo
|
||||||
|
@ -369,10 +374,16 @@ static void testGetIpForwardTable(void)
|
||||||
|
|
||||||
static void testGetIpNetTable(void)
|
static void testGetIpNetTable(void)
|
||||||
{
|
{
|
||||||
DWORD apiReturn;
|
DWORD apiReturn, ret, prev_idx;
|
||||||
|
BOOL igmp3_found, ssdp_found;
|
||||||
|
DWORD igmp3_addr, ssdp_addr;
|
||||||
|
MIB_IPNET_TABLE2 *table2;
|
||||||
ULONG dwSize = 0;
|
ULONG dwSize = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
igmp3_addr = ipv4_addr( 224, 0, 0, 22 );
|
||||||
|
ssdp_addr = ipv4_addr( 239, 255, 255, 250 );
|
||||||
|
|
||||||
apiReturn = GetIpNetTable(NULL, NULL, FALSE);
|
apiReturn = GetIpNetTable(NULL, NULL, FALSE);
|
||||||
if (apiReturn == ERROR_NOT_SUPPORTED) {
|
if (apiReturn == ERROR_NOT_SUPPORTED) {
|
||||||
skip("GetIpNetTable is not supported\n");
|
skip("GetIpNetTable is not supported\n");
|
||||||
|
@ -406,6 +417,45 @@ static void testGetIpNetTable(void)
|
||||||
ok(ntohl(buf->table[i].dwAddr) <= ntohl(buf->table[i + 1].dwAddr),
|
ok(ntohl(buf->table[i].dwAddr) <= ntohl(buf->table[i + 1].dwAddr),
|
||||||
"Entries are not sorted by address, i %u.\n", i );
|
"Entries are not sorted by address, i %u.\n", i );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
igmp3_found = ssdp_found = FALSE;
|
||||||
|
prev_idx = ~0ul;
|
||||||
|
for (i = 0; i < buf->dwNumEntries; ++i)
|
||||||
|
{
|
||||||
|
if (buf->table[i].dwIndex != prev_idx)
|
||||||
|
{
|
||||||
|
if (prev_idx != ~0ul)
|
||||||
|
{
|
||||||
|
ok( igmp3_found, "%s not found, iface index %lu.\n", ntoa( igmp3_addr ), prev_idx);
|
||||||
|
ok( ssdp_found || broken(!ssdp_found) /* 239.255.255.250 is always present since Win10 */,
|
||||||
|
"%s not found.\n", ntoa( ssdp_addr ));
|
||||||
|
}
|
||||||
|
prev_idx = buf->table[i].dwIndex;
|
||||||
|
igmp3_found = ssdp_found = FALSE;
|
||||||
|
}
|
||||||
|
if (buf->table[i].dwAddr == igmp3_addr)
|
||||||
|
igmp3_found = TRUE;
|
||||||
|
else if (buf->table[i].dwAddr == ssdp_addr)
|
||||||
|
ssdp_found = TRUE;
|
||||||
|
}
|
||||||
|
ok( igmp3_found, "%s not found.\n", ntoa( igmp3_addr ));
|
||||||
|
ok( ssdp_found || broken(!ssdp_found) /* 239.255.255.250 is always present since Win10 */,
|
||||||
|
"%s not found.\n", ntoa( ssdp_addr ));
|
||||||
|
|
||||||
|
ret = GetIpNetTable2( AF_INET, &table2 );
|
||||||
|
ok( !ret, "got ret %lu.\n", ret );
|
||||||
|
for (i = 0; i < table2->NumEntries; ++i)
|
||||||
|
{
|
||||||
|
MIB_IPNET_ROW2 *row = &table2->Table[i];
|
||||||
|
if (row->Address.Ipv4.sin_addr.s_addr == igmp3_addr
|
||||||
|
|| row->Address.Ipv4.sin_addr.s_addr == ssdp_addr)
|
||||||
|
{
|
||||||
|
ok( row->State == NlnsPermanent, "got state %d.\n", row->State );
|
||||||
|
ok( !row->IsRouter, "IsRouter is set.\n" );
|
||||||
|
ok( !row->IsUnreachable, "IsUnreachable is set.\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeMibTable( table2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiReturn == NO_ERROR && winetest_debug > 1)
|
if (apiReturn == NO_ERROR && winetest_debug > 1)
|
||||||
|
|
|
@ -1000,18 +1000,75 @@ static void ipv4_neighbour_fill_entry( struct ipv4_neighbour_data *entry, struct
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARP entries for these multicast addresses are always present on Windows for each interface. */
|
||||||
|
static DWORD ipv4_multicast_addresses[] =
|
||||||
|
{
|
||||||
|
IPV4_ADDR(224, 0, 0, 22),
|
||||||
|
IPV4_ADDR(239, 255, 255, 250),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void update_static_address_found( DWORD address, UINT if_index, struct nsi_ndis_ifinfo_static *iface,
|
||||||
|
unsigned int iface_count )
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ipv4_multicast_addresses); ++i)
|
||||||
|
if (ipv4_multicast_addresses[i] == address) break;
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(ipv4_multicast_addresses)) return;
|
||||||
|
|
||||||
|
for (j = 0; j < iface_count; ++j)
|
||||||
|
{
|
||||||
|
if (iface[j].if_index == if_index)
|
||||||
|
{
|
||||||
|
iface[j].unk |= 1 << i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, void *rw_data, UINT rw_size,
|
static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, void *rw_data, UINT rw_size,
|
||||||
void *dynamic_data, UINT dynamic_size,
|
void *dynamic_data, UINT dynamic_size,
|
||||||
void *static_data, UINT static_size, UINT_PTR *count )
|
void *static_data, UINT static_size, UINT_PTR *count )
|
||||||
{
|
{
|
||||||
UINT num = 0;
|
UINT num = 0, iface_count;
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
BOOL want_data = key_size || rw_size || dynamic_size || static_size;
|
BOOL want_data = key_size || rw_size || dynamic_size || static_size;
|
||||||
|
struct nsi_ndis_ifinfo_static *iface_static;
|
||||||
struct ipv4_neighbour_data entry;
|
struct ipv4_neighbour_data entry;
|
||||||
|
NET_LUID *luid_tbl;
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data, key_size, rw_data, rw_size,
|
TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data, key_size, rw_data, rw_size,
|
||||||
dynamic_data, dynamic_size, static_data, static_size, count );
|
dynamic_data, dynamic_size, static_data, static_size, count );
|
||||||
|
|
||||||
|
iface_count = 0;
|
||||||
|
if ((status = nsi_enumerate_all( 1, 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, NULL, 0, NULL, 0,
|
||||||
|
NULL, 0, NULL, 0, &iface_count )))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (!(luid_tbl = malloc( iface_count * sizeof(*luid_tbl) )))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
if (!(iface_static = malloc( iface_count * sizeof(*iface_static) )))
|
||||||
|
{
|
||||||
|
free( luid_tbl );
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status = nsi_enumerate_all( 1, 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl, sizeof(*luid_tbl),
|
||||||
|
NULL, 0, NULL, 0, iface_static, sizeof(*iface_static), &iface_count ))
|
||||||
|
&& status != STATUS_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
free( luid_tbl );
|
||||||
|
free( iface_static );
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use unk field to indicate whether we found mandatory multicast addresses in the host ARP table. */
|
||||||
|
for (i = 0; i < iface_count; ++i)
|
||||||
|
iface_static[i].unk = 0;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{
|
{
|
||||||
char buf[512], *ptr, *s;
|
char buf[512], *ptr, *s;
|
||||||
|
@ -1059,6 +1116,8 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
|
||||||
if (!convert_unix_name_to_luid( ptr, &entry.luid )) continue;
|
if (!convert_unix_name_to_luid( ptr, &entry.luid )) continue;
|
||||||
if (!convert_luid_to_index( &entry.luid, &entry.if_index )) continue;
|
if (!convert_luid_to_index( &entry.luid, &entry.if_index )) continue;
|
||||||
|
|
||||||
|
update_static_address_found( entry.addr.s_addr, entry.if_index, iface_static, iface_count );
|
||||||
|
|
||||||
if (num < *count)
|
if (num < *count)
|
||||||
{
|
{
|
||||||
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
|
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
|
||||||
|
@ -1119,6 +1178,8 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
|
||||||
#endif
|
#endif
|
||||||
entry.is_unreachable = 0; /* FIXME */
|
entry.is_unreachable = 0; /* FIXME */
|
||||||
|
|
||||||
|
update_static_address_found( entry.addr.s_addr, entry.if_index, iface_static, iface_count );
|
||||||
|
|
||||||
if (num < *count)
|
if (num < *count)
|
||||||
{
|
{
|
||||||
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
|
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
|
||||||
|
@ -1136,9 +1197,42 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
FIXME( "not implemented\n" );
|
FIXME( "not implemented\n" );
|
||||||
|
free( luid_tbl );
|
||||||
|
free( iface_static );
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!want_data || num <= *count)
|
||||||
|
{
|
||||||
|
/* Certain ipv4 multicast addresses are always present on Windows for each interface.
|
||||||
|
* Add those if they weren't added already. */
|
||||||
|
memset( &entry, 0, sizeof(entry) );
|
||||||
|
entry.state = NlnsPermanent;
|
||||||
|
for (i = 0; i < iface_count; ++i)
|
||||||
|
{
|
||||||
|
entry.if_index = iface_static[i].if_index;
|
||||||
|
entry.luid = luid_tbl[i];
|
||||||
|
for (j = 0; j < ARRAY_SIZE(ipv4_multicast_addresses); ++j)
|
||||||
|
{
|
||||||
|
if (iface_static[i].unk & (1 << j)) continue;
|
||||||
|
if (num <= *count)
|
||||||
|
{
|
||||||
|
entry.addr.s_addr = ipv4_multicast_addresses[j];
|
||||||
|
ipv4_neighbour_fill_entry( &entry, key_data, rw_data, dynamic_data, static_data );
|
||||||
|
|
||||||
|
if (key_data) key_data = (BYTE *)key_data + key_size;
|
||||||
|
if (rw_data) rw_data = (BYTE *)rw_data + rw_size;
|
||||||
|
if (dynamic_data) dynamic_data = (BYTE *)dynamic_data + dynamic_size;
|
||||||
|
if (static_data) static_data = (BYTE *)static_data + static_size;
|
||||||
|
}
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free( luid_tbl );
|
||||||
|
free( iface_static );
|
||||||
|
|
||||||
if (!want_data || num <= *count) *count = num;
|
if (!want_data || num <= *count) *count = num;
|
||||||
else status = STATUS_BUFFER_OVERFLOW;
|
else status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
#define IPV4_ADDR(b1, b2, b3, b4) (((unsigned int)b1 << 24) | (b2 << 16) | (b3 << 8) | b4)
|
||||||
|
#else
|
||||||
|
#define IPV4_ADDR(b1, b2, b3, b4) (((unsigned int)b4 << 24) | (b3 << 16) | (b2 << 8) | b1)
|
||||||
|
#endif
|
||||||
|
|
||||||
NTSTATUS nsi_enumerate_all_ex( struct nsi_enumerate_all_ex *params ) DECLSPEC_HIDDEN;
|
NTSTATUS nsi_enumerate_all_ex( struct nsi_enumerate_all_ex *params ) DECLSPEC_HIDDEN;
|
||||||
NTSTATUS nsi_get_all_parameters_ex( struct nsi_get_all_parameters_ex *params ) DECLSPEC_HIDDEN;
|
NTSTATUS nsi_get_all_parameters_ex( struct nsi_get_all_parameters_ex *params ) DECLSPEC_HIDDEN;
|
||||||
NTSTATUS nsi_get_parameter_ex( struct nsi_get_parameter_ex *params ) DECLSPEC_HIDDEN;
|
NTSTATUS nsi_get_parameter_ex( struct nsi_get_parameter_ex *params ) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in a new issue