nsiproxy: Implement IPv4 forward enumerate_all.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4df04dbdd6
commit
f1793fd8bc
|
@ -485,6 +485,121 @@ static void test_ip_unicast( int family )
|
||||||
winetest_pop_context();
|
winetest_pop_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_ip_forward( int family )
|
||||||
|
{
|
||||||
|
DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ip_forward_rw, unk),
|
||||||
|
FIELD_OFFSET(struct nsi_ip_forward_rw, unk2), sizeof(struct nsi_ip_forward_rw) };
|
||||||
|
DWORD dyn_sizes4[] = { sizeof(struct nsi_ipv4_forward_dynamic) - 3 * sizeof(DWORD),
|
||||||
|
sizeof(struct nsi_ipv4_forward_dynamic) };
|
||||||
|
DWORD dyn_sizes6[] = { sizeof(struct nsi_ipv6_forward_dynamic) - 3 * sizeof(DWORD),
|
||||||
|
sizeof(struct nsi_ipv6_forward_dynamic) };
|
||||||
|
DWORD *dyn_sizes = family == AF_INET ? dyn_sizes4 : dyn_sizes6;
|
||||||
|
struct nsi_ipv4_forward_key *key_tbl, *key4;
|
||||||
|
struct nsi_ipv6_forward_key *key6;
|
||||||
|
struct nsi_ip_forward_rw *rw_tbl, *rw;
|
||||||
|
struct nsi_ipv4_forward_dynamic *dyn_tbl, *dyn4;
|
||||||
|
struct nsi_ipv6_forward_dynamic *dyn6;
|
||||||
|
struct nsi_ip_forward_static *stat_tbl, *stat;
|
||||||
|
MIB_IPFORWARD_TABLE2 *table;
|
||||||
|
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;
|
||||||
|
|
||||||
|
winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
|
||||||
|
{
|
||||||
|
err = NsiAllocateAndGetTable( 1, mod, NSI_IP_FORWARD_TABLE, (void **)&key_tbl, key_size,
|
||||||
|
(void **)&rw_tbl, rw_sizes[i], NULL, 0,
|
||||||
|
NULL, 0, &count, 0 );
|
||||||
|
if (!err) break;
|
||||||
|
}
|
||||||
|
todo_wine_if (family == AF_INET6)
|
||||||
|
ok( !err, "got %d\n", err );
|
||||||
|
if (err) { winetest_pop_context(); return; }
|
||||||
|
rw_size = rw_sizes[i];
|
||||||
|
NsiFreeTable( key_tbl, rw_tbl, NULL, NULL );
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dyn_sizes4); i++)
|
||||||
|
{
|
||||||
|
err = NsiAllocateAndGetTable( 1, mod, NSI_IP_FORWARD_TABLE, (void **)&key_tbl, key_size,
|
||||||
|
(void **)&rw_tbl, rw_size, (void **)&dyn_tbl, dyn_sizes[i],
|
||||||
|
(void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
|
||||||
|
if (!err) break;
|
||||||
|
}
|
||||||
|
ok( !err, "got %d\n", err );
|
||||||
|
dyn_size = dyn_sizes[i];
|
||||||
|
|
||||||
|
err = GetIpForwardTable2( family, &table );
|
||||||
|
todo_wine
|
||||||
|
ok( !err, "got %d\n", err );
|
||||||
|
if (err) { winetest_pop_context(); return; }
|
||||||
|
ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
MIB_IPFORWARD_ROW2 *row = table->Table + i;
|
||||||
|
rw = (struct nsi_ip_forward_rw *)((BYTE *)rw_tbl + i * rw_size);
|
||||||
|
stat = stat_tbl + i;
|
||||||
|
winetest_push_context( "%d", i );
|
||||||
|
|
||||||
|
ok( row->DestinationPrefix.Prefix.si_family == family, "mismatch\n" );
|
||||||
|
|
||||||
|
if (family == AF_INET)
|
||||||
|
{
|
||||||
|
key4 = key_tbl + i;
|
||||||
|
dyn4 = (struct nsi_ipv4_forward_dynamic *)((BYTE *)dyn_tbl + i * dyn_size);
|
||||||
|
|
||||||
|
ok( row->InterfaceLuid.Value == key4->luid.Value, "mismatch\n" );
|
||||||
|
ok( row->InterfaceLuid.Value == key4->luid2.Value, "mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr == key4->prefix.s_addr, "mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.Prefix.Ipv4.sin_port == 0, "mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.PrefixLength == key4->prefix_len, "mismatch\n" );
|
||||||
|
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" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key6 = (struct nsi_ipv6_forward_key *)key_tbl + i;
|
||||||
|
dyn6 = (struct nsi_ipv6_forward_dynamic *)((BYTE *)dyn_tbl + i * dyn_size);
|
||||||
|
|
||||||
|
ok( row->InterfaceLuid.Value == key6->luid.Value, "mismatch\n" );
|
||||||
|
ok( row->InterfaceLuid.Value == key6->luid2.Value, "mismatch\n" );
|
||||||
|
ok( !memcmp( &row->DestinationPrefix.Prefix.Ipv6.sin6_addr, &key6->prefix, sizeof(key6->prefix) ),
|
||||||
|
"mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.Prefix.Ipv6.sin6_port == 0, "mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.Prefix.Ipv6.sin6_flowinfo == 0, "mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.Prefix.Ipv6.sin6_scope_id == 0, "mismatch\n" );
|
||||||
|
ok( row->DestinationPrefix.PrefixLength == key6->prefix_len, "mismatch\n" );
|
||||||
|
ok( !memcmp( &row->NextHop.Ipv6.sin6_addr, &key6->next_hop, sizeof(key6->next_hop) ), "mismatch\n" );
|
||||||
|
ok( row->NextHop.Ipv6.sin6_port == 0, "mismatch\n" );
|
||||||
|
ok( row->NextHop.Ipv6.sin6_flowinfo == 0, "mismatch\n" );
|
||||||
|
ok( row->NextHop.Ipv6.sin6_scope_id == 0, "mismatch\n" );
|
||||||
|
ok( row->Age == dyn6->age, "mismatch\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
ok( row->InterfaceIndex == stat->if_index, "mismatch\n" );
|
||||||
|
ok( row->SitePrefixLength == rw->site_prefix_len, "mismatch\n" );
|
||||||
|
ok( row->ValidLifetime == rw->valid_lifetime, "mismatch\n" );
|
||||||
|
ok( row->PreferredLifetime == rw->preferred_lifetime, "mismatch\n" );
|
||||||
|
|
||||||
|
ok( row->Metric == rw->metric, "mismatch\n" );
|
||||||
|
ok( row->Protocol == rw->protocol, "mismatch\n" );
|
||||||
|
ok( row->Loopback == rw->loopback, "mismatch\n" );
|
||||||
|
ok( row->AutoconfigureAddress == rw->autoconf, "mismatch\n" );
|
||||||
|
ok( row->Publish == rw->publish, "mismatch\n" );
|
||||||
|
ok( row->Immortal == rw->immortal, "mismatch\n" );
|
||||||
|
ok( row->Origin == stat->origin, "mismatch\n" );
|
||||||
|
|
||||||
|
winetest_pop_context();
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeMibTable( table );
|
||||||
|
NsiFreeTable( key_tbl, rw_tbl, dyn_tbl, stat_tbl );
|
||||||
|
winetest_pop_context();
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST( nsi )
|
START_TEST( nsi )
|
||||||
{
|
{
|
||||||
test_nsi_api();
|
test_nsi_api();
|
||||||
|
@ -494,4 +609,6 @@ START_TEST( nsi )
|
||||||
|
|
||||||
test_ip_unicast( AF_INET );
|
test_ip_unicast( AF_INET );
|
||||||
test_ip_unicast( AF_INET6 );
|
test_ip_unicast( AF_INET6 );
|
||||||
|
test_ip_forward( AF_INET );
|
||||||
|
test_ip_forward( AF_INET6 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,14 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_ROUTE_H
|
||||||
|
#include <net/route.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SYSCTL_H
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +53,7 @@
|
||||||
#include "nldef.h"
|
#include "nldef.h"
|
||||||
#include "ifdef.h"
|
#include "ifdef.h"
|
||||||
#include "netiodef.h"
|
#include "netiodef.h"
|
||||||
|
#include "wine/heap.h"
|
||||||
#include "wine/nsi.h"
|
#include "wine/nsi.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -221,6 +230,249 @@ static NTSTATUS ip_unicast_get_all_parameters( const void *key, DWORD key_size,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ipv4_route_data
|
||||||
|
{
|
||||||
|
NET_LUID luid;
|
||||||
|
DWORD if_index;
|
||||||
|
struct in_addr prefix;
|
||||||
|
DWORD prefix_len;
|
||||||
|
struct in_addr next_hop;
|
||||||
|
DWORD metric;
|
||||||
|
DWORD protocol;
|
||||||
|
BYTE loopback;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ipv4_forward_fill_entry( struct ipv4_route_data *entry, struct nsi_ipv4_forward_key *key,
|
||||||
|
struct nsi_ip_forward_rw *rw, struct nsi_ipv4_forward_dynamic *dyn,
|
||||||
|
struct nsi_ip_forward_static *stat )
|
||||||
|
{
|
||||||
|
if (key)
|
||||||
|
{
|
||||||
|
key->unk = 0;
|
||||||
|
key->prefix.WS_s_addr = entry->prefix.s_addr;
|
||||||
|
key->prefix_len = entry->prefix_len;
|
||||||
|
memset( key->unk2, 0, sizeof(key->unk2) );
|
||||||
|
memset( key->unk3, 0, sizeof(key->unk3) );
|
||||||
|
key->luid = entry->luid;
|
||||||
|
key->luid2 = entry->luid;
|
||||||
|
key->next_hop.WS_s_addr = entry->next_hop.s_addr;
|
||||||
|
key->pad = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rw)
|
||||||
|
{
|
||||||
|
rw->site_prefix_len = 0;
|
||||||
|
rw->valid_lifetime = ~0u;
|
||||||
|
rw->preferred_lifetime = ~0u;
|
||||||
|
rw->metric = entry->metric;
|
||||||
|
rw->protocol = entry->protocol;
|
||||||
|
rw->loopback = entry->loopback;
|
||||||
|
rw->autoconf = 1;
|
||||||
|
rw->publish = 0;
|
||||||
|
rw->immortal = 1;
|
||||||
|
memset( rw->unk, 0, sizeof(rw->unk) );
|
||||||
|
rw->unk2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dyn)
|
||||||
|
{
|
||||||
|
memset( dyn, 0, sizeof(*dyn) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat)
|
||||||
|
{
|
||||||
|
stat->origin = NlroManual;
|
||||||
|
stat->if_index = entry->if_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS ipv4_forward_enumerate_all( void *key_data, DWORD key_size, void *rw_data, DWORD rw_size,
|
||||||
|
void *dynamic_data, DWORD dynamic_size,
|
||||||
|
void *static_data, DWORD static_size, DWORD_PTR *count )
|
||||||
|
{
|
||||||
|
DWORD num = 0;
|
||||||
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
|
BOOL want_data = key_size || rw_size || dynamic_size || static_size;
|
||||||
|
struct ipv4_route_data entry;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
char buf[512], *ptr;
|
||||||
|
struct in_addr mask;
|
||||||
|
DWORD rtf_flags;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (!(fp = fopen( "/proc/net/route", "r" ))) return STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
/* skip header line */
|
||||||
|
fgets( buf, sizeof(buf), fp );
|
||||||
|
while ((ptr = fgets( buf, sizeof(buf), fp )))
|
||||||
|
{
|
||||||
|
while (!isspace( *ptr )) ptr++;
|
||||||
|
*ptr++ = '\0';
|
||||||
|
|
||||||
|
if (!convert_unix_name_to_luid( buf, &entry.luid )) continue;
|
||||||
|
if (!convert_luid_to_index( &entry.luid, &entry.if_index )) continue;
|
||||||
|
|
||||||
|
entry.prefix.s_addr = strtoul( ptr, &ptr, 16 );
|
||||||
|
entry.next_hop.s_addr = strtoul( ptr + 1, &ptr, 16 );
|
||||||
|
rtf_flags = strtoul( ptr + 1, &ptr, 16 );
|
||||||
|
strtoul( ptr + 1, &ptr, 16 ); /* refcount, skip */
|
||||||
|
strtoul( ptr + 1, &ptr, 16 ); /* use, skip */
|
||||||
|
entry.metric = strtoul( ptr + 1, &ptr, 16 );
|
||||||
|
mask.s_addr = strtoul( ptr + 1, &ptr, 16 );
|
||||||
|
entry.prefix_len = mask_v4_to_prefix( &mask );
|
||||||
|
entry.protocol = (rtf_flags & RTF_GATEWAY) ? MIB_IPPROTO_NETMGMT : MIB_IPPROTO_LOCAL;
|
||||||
|
entry.loopback = entry.protocol == MIB_IPPROTO_LOCAL && entry.prefix_len == 32;
|
||||||
|
|
||||||
|
if (num < *count)
|
||||||
|
{
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
fclose( fp );
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
||||||
|
{
|
||||||
|
int mib[6] = { CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0 };
|
||||||
|
size_t needed;
|
||||||
|
char *buf = NULL, *lim, *next, *addr_ptr;
|
||||||
|
struct rt_msghdr *rtm;
|
||||||
|
|
||||||
|
if (sysctl( mib, ARRAY_SIZE(mib), NULL, &needed, NULL, 0 ) < 0) return STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
buf = heap_alloc( needed );
|
||||||
|
if (!buf) return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
if (sysctl( mib, 6, buf, &needed, NULL, 0 ) < 0)
|
||||||
|
{
|
||||||
|
heap_free( buf );
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
lim = buf + needed;
|
||||||
|
for (next = buf; next < lim; next += rtm->rtm_msglen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
sa_family_t dst_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
rtm = (struct rt_msghdr *)next;
|
||||||
|
|
||||||
|
if (rtm->rtm_type != RTM_GET)
|
||||||
|
{
|
||||||
|
WARN( "Got unexpected message type 0x%x!\n", rtm->rtm_type );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore gateway routes which are multicast */
|
||||||
|
if ((rtm->rtm_flags & RTF_GATEWAY) && (rtm->rtm_flags & RTF_MULTICAST)) continue;
|
||||||
|
|
||||||
|
entry.if_index = rtm->rtm_index;
|
||||||
|
if (!convert_index_to_luid( entry.if_index, &entry.luid )) continue;
|
||||||
|
entry.protocol = (rtm->rtm_flags & RTF_GATEWAY) ? MIB_IPPROTO_NETMGMT : MIB_IPPROTO_LOCAL;
|
||||||
|
entry.metric = rtm->rtm_rmx.rmx_hopcount;
|
||||||
|
|
||||||
|
addr_ptr = (char *)(rtm + 1);
|
||||||
|
|
||||||
|
for (i = 1; i; i <<= 1)
|
||||||
|
{
|
||||||
|
struct sockaddr *sa;
|
||||||
|
struct in_addr addr;
|
||||||
|
|
||||||
|
if (!(i & rtm->rtm_addrs)) continue;
|
||||||
|
|
||||||
|
sa = (struct sockaddr *)addr_ptr;
|
||||||
|
if (addr_ptr + sa->sa_len > next + rtm->rtm_msglen)
|
||||||
|
{
|
||||||
|
ERR( "struct sockaddr extends beyond the route message, %p > %p\n",
|
||||||
|
addr_ptr + sa->sa_len, next + rtm->rtm_msglen );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa->sa_len) addr_ptr += (sa->sa_len + sizeof(int)-1) & ~(sizeof(int)-1);
|
||||||
|
else addr_ptr += sizeof(int);
|
||||||
|
/* Apple's netstat prints the netmask together with the destination
|
||||||
|
* and only looks at the destination's address family. The netmask's
|
||||||
|
* sa_family sometimes contains the non-existent value 0xff. */
|
||||||
|
switch (i == RTA_NETMASK ? dst_family : sa->sa_family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
/* Netmasks (and possibly other addresses) have only enough size
|
||||||
|
* to represent the non-zero bits, e.g. a netmask of 255.0.0.0 has
|
||||||
|
* 5 bytes (1 sa_len, 1 sa_family, 2 sa_port and 1 for the first
|
||||||
|
* byte of sin_addr). */
|
||||||
|
struct sockaddr_in sin = {0};
|
||||||
|
memcpy( &sin, sa, sa->sa_len );
|
||||||
|
addr = sin.sin_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef AF_LINK
|
||||||
|
case AF_LINK:
|
||||||
|
if (i == RTA_GATEWAY && entry.protocol == MIB_IPPROTO_NETMGMT)
|
||||||
|
{
|
||||||
|
/* For direct route we may simply use dest addr as next hop */
|
||||||
|
C_ASSERT(RTA_DST < RTA_GATEWAY);
|
||||||
|
addr = entry.prefix;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fallthrough */
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
WARN( "Received unsupported sockaddr family 0x%x\n", sa->sa_family );
|
||||||
|
addr.s_addr = 0;
|
||||||
|
}
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case RTA_DST:
|
||||||
|
entry.prefix = addr;
|
||||||
|
dst_family = sa->sa_family;
|
||||||
|
break;
|
||||||
|
case RTA_GATEWAY: entry.next_hop = addr; break;
|
||||||
|
case RTA_NETMASK: entry.prefix_len = mask_v4_to_prefix( &addr ); break;
|
||||||
|
default:
|
||||||
|
WARN( "Unexpected address type 0x%x\n", i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < *count)
|
||||||
|
{
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap (), 0, buf );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FIXME( "not implemented\n" );
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!want_data || num <= *count) *count = num;
|
||||||
|
else status = STATUS_MORE_ENTRIES;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS ipv6_forward_enumerate_all( void *key_data, DWORD key_size, void *rw_data, DWORD rw_size,
|
||||||
|
void *dynamic_data, DWORD dynamic_size,
|
||||||
|
void *static_data, DWORD static_size, DWORD_PTR *count )
|
||||||
|
{
|
||||||
|
FIXME( "not implemented\n" );
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
static struct module_table ipv4_tables[] =
|
static struct module_table ipv4_tables[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -232,6 +484,14 @@ static struct module_table ipv4_tables[] =
|
||||||
ip_unicast_enumerate_all,
|
ip_unicast_enumerate_all,
|
||||||
ip_unicast_get_all_parameters,
|
ip_unicast_get_all_parameters,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
NSI_IP_FORWARD_TABLE,
|
||||||
|
{
|
||||||
|
sizeof(struct nsi_ipv4_forward_key), sizeof(struct nsi_ip_forward_rw),
|
||||||
|
sizeof(struct nsi_ipv4_forward_dynamic), sizeof(struct nsi_ip_forward_static)
|
||||||
|
},
|
||||||
|
ipv4_forward_enumerate_all,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
~0u
|
~0u
|
||||||
}
|
}
|
||||||
|
@ -254,6 +514,14 @@ static struct module_table ipv6_tables[] =
|
||||||
ip_unicast_enumerate_all,
|
ip_unicast_enumerate_all,
|
||||||
ip_unicast_get_all_parameters,
|
ip_unicast_get_all_parameters,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
NSI_IP_FORWARD_TABLE,
|
||||||
|
{
|
||||||
|
sizeof(struct nsi_ipv6_forward_key), sizeof(struct nsi_ip_forward_rw),
|
||||||
|
sizeof(struct nsi_ipv6_forward_dynamic), sizeof(struct nsi_ip_forward_static)
|
||||||
|
},
|
||||||
|
ipv6_forward_enumerate_all,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
~0u
|
~0u
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,44 @@ NTSTATUS nsi_get_parameter_ex( struct nsi_get_parameter_ex *params ) DECLSPEC_HI
|
||||||
BOOL convert_luid_to_unix_name( const NET_LUID *luid, const char **unix_name ) DECLSPEC_HIDDEN;
|
BOOL convert_luid_to_unix_name( const NET_LUID *luid, const char **unix_name ) DECLSPEC_HIDDEN;
|
||||||
BOOL convert_unix_name_to_luid( const char *unix_name, NET_LUID *luid ) DECLSPEC_HIDDEN;
|
BOOL convert_unix_name_to_luid( const char *unix_name, NET_LUID *luid ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
static inline BOOL convert_luid_to_index( const NET_LUID *luid, DWORD *index )
|
||||||
|
{
|
||||||
|
struct nsi_get_parameter_ex params;
|
||||||
|
params.unknown[0] = 0;
|
||||||
|
params.unknown[1] = 0;
|
||||||
|
params.first_arg = 1;
|
||||||
|
params.unknown2 = 0;
|
||||||
|
params.module = &NPI_MS_NDIS_MODULEID;
|
||||||
|
params.table = NSI_NDIS_IFINFO_TABLE;
|
||||||
|
params.key = luid;
|
||||||
|
params.key_size = sizeof(*luid);
|
||||||
|
params.param_type = NSI_PARAM_TYPE_STATIC;
|
||||||
|
params.data = index;
|
||||||
|
params.data_size = sizeof(*index);
|
||||||
|
params.data_offset = FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_index);
|
||||||
|
|
||||||
|
return !nsi_get_parameter_ex( ¶ms );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOL convert_index_to_luid( DWORD index, NET_LUID *luid )
|
||||||
|
{
|
||||||
|
struct nsi_get_parameter_ex params;
|
||||||
|
params.unknown[0] = 0;
|
||||||
|
params.unknown[1] = 0;
|
||||||
|
params.first_arg = 1;
|
||||||
|
params.unknown2 = 0;
|
||||||
|
params.module = &NPI_MS_NDIS_MODULEID;
|
||||||
|
params.table = NSI_NDIS_INDEX_LUID_TABLE;
|
||||||
|
params.key = &index;
|
||||||
|
params.key_size = sizeof(index);
|
||||||
|
params.param_type = NSI_PARAM_TYPE_STATIC;
|
||||||
|
params.data = luid;
|
||||||
|
params.data_size = sizeof(*luid);
|
||||||
|
params.data_offset = 0;
|
||||||
|
|
||||||
|
return !nsi_get_parameter_ex( ¶ms );
|
||||||
|
}
|
||||||
|
|
||||||
struct module_table
|
struct module_table
|
||||||
{
|
{
|
||||||
DWORD table;
|
DWORD table;
|
||||||
|
|
|
@ -254,6 +254,8 @@ DWORD WINAPI GetIfEntry2(MIB_IF_ROW2*);
|
||||||
DWORD WINAPI GetIfEntry2Ex(MIB_IF_TABLE_LEVEL,MIB_IF_ROW2*);
|
DWORD WINAPI GetIfEntry2Ex(MIB_IF_TABLE_LEVEL,MIB_IF_ROW2*);
|
||||||
DWORD WINAPI GetIfTable2(MIB_IF_TABLE2**);
|
DWORD WINAPI GetIfTable2(MIB_IF_TABLE2**);
|
||||||
DWORD WINAPI GetIfTable2Ex(MIB_IF_TABLE_LEVEL,MIB_IF_TABLE2**);
|
DWORD WINAPI GetIfTable2Ex(MIB_IF_TABLE_LEVEL,MIB_IF_TABLE2**);
|
||||||
|
DWORD WINAPI GetIpForwardEntry2(MIB_IPFORWARD_ROW2*);
|
||||||
|
DWORD WINAPI GetIpForwardTable2(ADDRESS_FAMILY,MIB_IPFORWARD_TABLE2**);
|
||||||
DWORD WINAPI GetIpInterfaceTable(ADDRESS_FAMILY,MIB_IPINTERFACE_TABLE**);
|
DWORD WINAPI GetIpInterfaceTable(ADDRESS_FAMILY,MIB_IPINTERFACE_TABLE**);
|
||||||
DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW*);
|
DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW*);
|
||||||
DWORD WINAPI GetUnicastIpAddressTable(ADDRESS_FAMILY,MIB_UNICASTIPADDRESS_TABLE**);
|
DWORD WINAPI GetUnicastIpAddressTable(ADDRESS_FAMILY,MIB_UNICASTIPADDRESS_TABLE**);
|
||||||
|
|
|
@ -98,6 +98,7 @@ struct nsi_ndis_ifinfo_static
|
||||||
|
|
||||||
/* Undocumented NSI IP tables */
|
/* Undocumented NSI IP tables */
|
||||||
#define NSI_IP_UNICAST_TABLE 10
|
#define NSI_IP_UNICAST_TABLE 10
|
||||||
|
#define NSI_IP_FORWARD_TABLE 16
|
||||||
|
|
||||||
struct nsi_ipv4_unicast_key
|
struct nsi_ipv4_unicast_key
|
||||||
{
|
{
|
||||||
|
@ -133,6 +134,67 @@ struct nsi_ip_unicast_static
|
||||||
ULONG64 creation_time;
|
ULONG64 creation_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nsi_ipv4_forward_key
|
||||||
|
{
|
||||||
|
DWORD unk;
|
||||||
|
IN_ADDR prefix;
|
||||||
|
BYTE prefix_len;
|
||||||
|
BYTE unk2[3];
|
||||||
|
DWORD unk3[3];
|
||||||
|
NET_LUID luid;
|
||||||
|
NET_LUID luid2;
|
||||||
|
IN_ADDR next_hop;
|
||||||
|
DWORD pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nsi_ipv6_forward_key
|
||||||
|
{
|
||||||
|
DWORD unk;
|
||||||
|
IN6_ADDR prefix;
|
||||||
|
BYTE prefix_len;
|
||||||
|
BYTE unk2[3];
|
||||||
|
DWORD unk3[3];
|
||||||
|
DWORD pad;
|
||||||
|
NET_LUID luid;
|
||||||
|
NET_LUID luid2;
|
||||||
|
IN6_ADDR next_hop;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nsi_ip_forward_rw
|
||||||
|
{
|
||||||
|
DWORD site_prefix_len;
|
||||||
|
DWORD valid_lifetime;
|
||||||
|
DWORD preferred_lifetime;
|
||||||
|
DWORD metric;
|
||||||
|
DWORD protocol;
|
||||||
|
BYTE loopback;
|
||||||
|
BYTE autoconf;
|
||||||
|
BYTE publish;
|
||||||
|
BYTE immortal;
|
||||||
|
BYTE unk[4];
|
||||||
|
DWORD unk2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nsi_ipv4_forward_dynamic
|
||||||
|
{
|
||||||
|
DWORD age;
|
||||||
|
DWORD unk[3];
|
||||||
|
IN_ADDR addr2; /* often a repeat of prefix */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nsi_ipv6_forward_dynamic
|
||||||
|
{
|
||||||
|
DWORD age;
|
||||||
|
DWORD unk[3];
|
||||||
|
IN6_ADDR addr2; /* often a repeat of prefix */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nsi_ip_forward_static
|
||||||
|
{
|
||||||
|
DWORD origin;
|
||||||
|
DWORD if_index;
|
||||||
|
};
|
||||||
|
|
||||||
/* Wine specific ioctl interface */
|
/* Wine specific ioctl interface */
|
||||||
|
|
||||||
#define IOCTL_NSIPROXY_WINE_ENUMERATE_ALL CTL_CODE(FILE_DEVICE_NETWORK, 0x400, METHOD_BUFFERED, 0)
|
#define IOCTL_NSIPROXY_WINE_ENUMERATE_ALL CTL_CODE(FILE_DEVICE_NETWORK, 0x400, METHOD_BUFFERED, 0)
|
||||||
|
|
Loading…
Reference in New Issue