nsiproxy: Add support for IPv6 scope ids.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
14fc764756
commit
40a60061d7
|
@ -916,14 +916,12 @@ todo_wine_if( !unstable(0) && row->dwOwningPid )
|
|||
{
|
||||
ok( unstable( !memcmp( row6->ucLocalAddr, keys[i].local.Ipv6.sin6_addr.s6_addr, sizeof(IN6_ADDR) ) ),
|
||||
"mismatch\n" );
|
||||
todo_wine_if( !unstable(0) && row6->dwLocalScopeId )
|
||||
ok( unstable( row6->dwLocalScopeId == keys[i].local.Ipv6.sin6_scope_id ), "%x vs %x\n",
|
||||
row6->dwLocalScopeId, keys[i].local.Ipv6.sin6_scope_id );
|
||||
ok( unstable( row6->dwLocalPort == keys[i].local.Ipv6.sin6_port ), "%d vs %d\n",
|
||||
row6->dwLocalPort, keys[i].local.Ipv6.sin6_port );
|
||||
ok( unstable( !memcmp( row6->ucRemoteAddr, keys[i].remote.Ipv6.sin6_addr.s6_addr, sizeof(IN6_ADDR) ) ),
|
||||
"mismatch\n" );
|
||||
todo_wine_if( !unstable(0) && row6->dwRemoteScopeId )
|
||||
ok( unstable( row6->dwRemoteScopeId == keys[i].remote.Ipv6.sin6_scope_id ), "%x vs %x\n",
|
||||
row6->dwRemoteScopeId, keys[i].remote.Ipv6.sin6_scope_id );
|
||||
ok( unstable( row6->dwRemotePort == keys[i].remote.Ipv6.sin6_port ), "%d vs %d\n",
|
||||
|
|
|
@ -54,6 +54,10 @@
|
|||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
|
@ -209,6 +213,119 @@ static inline MIB_TCP_STATE tcp_state_to_mib_state( int state )
|
|||
}
|
||||
}
|
||||
|
||||
struct ipv6_addr_scope
|
||||
{
|
||||
IN6_ADDR addr;
|
||||
DWORD scope;
|
||||
};
|
||||
|
||||
static struct ipv6_addr_scope *get_ipv6_addr_scope_table( unsigned int *size )
|
||||
{
|
||||
struct ipv6_addr_scope *table = NULL;
|
||||
unsigned int table_size = 0, num = 0;
|
||||
|
||||
#ifdef __linux__
|
||||
{
|
||||
char buf[512], *ptr;
|
||||
FILE *fp;
|
||||
|
||||
if (!(fp = fopen( "/proc/net/if_inet6", "r" ))) goto failed;
|
||||
|
||||
while ((ptr = fgets( buf, sizeof(buf), fp )))
|
||||
{
|
||||
WORD a[8];
|
||||
DWORD scope;
|
||||
struct ipv6_addr_scope *entry;
|
||||
unsigned int i;
|
||||
|
||||
if (sscanf( ptr, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx %*s %*s %x",
|
||||
a, a + 1, a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, &scope ) != 9)
|
||||
continue;
|
||||
|
||||
if (++num > table_size)
|
||||
{
|
||||
if (!table_size) table_size = 4;
|
||||
else table_size *= 2;
|
||||
if (!(table = heap_realloc( table, table_size * sizeof(table[0]) )))
|
||||
{
|
||||
fclose( fp );
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
entry = table + num - 1;
|
||||
for (i = 0; i < 8; i++)
|
||||
entry->addr.u.Word[i] = htons( a[i] );
|
||||
entry->scope = htons( scope );
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
}
|
||||
#elif defined(HAVE_GETIFADDRS)
|
||||
{
|
||||
struct ifaddrs *addrs, *cur;
|
||||
|
||||
if (getifaddrs( &addrs ) == -1) goto failed;
|
||||
|
||||
for (cur = addrs; cur; cur = cur->ifa_next)
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct ipv6_addr_scope *entry;
|
||||
|
||||
if (cur->ifa_addr->sa_family != AF_INET6) continue;
|
||||
|
||||
if (++num > table_size)
|
||||
{
|
||||
if (!table_size) table_size = 4;
|
||||
else table_size *= 2;
|
||||
if (!(table = heap_realloc( table, table_size * sizeof(table[0]) )))
|
||||
{
|
||||
freeifaddrs( addrs );
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)cur->ifa_addr;
|
||||
entry = table + num - 1;
|
||||
memcpy( &entry->addr, &sin6->sin6_addr, sizeof(entry->addr) );
|
||||
entry->scope = sin6->sin6_scope_id;
|
||||
}
|
||||
|
||||
freeifaddrs( addrs );
|
||||
}
|
||||
#else
|
||||
FIXME( "not implemented\n" );
|
||||
goto failed;
|
||||
#endif
|
||||
|
||||
*size = num;
|
||||
return table;
|
||||
|
||||
failed:
|
||||
heap_free( table );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DWORD find_ipv6_addr_scope( const IN6_ADDR *addr, const struct ipv6_addr_scope *table, unsigned int size )
|
||||
{
|
||||
const BYTE multicast_scope_mask = 0x0F;
|
||||
const BYTE multicast_scope_shift = 0;
|
||||
unsigned int i;
|
||||
|
||||
if (WS_IN6_IS_ADDR_UNSPECIFIED( addr )) return 0;
|
||||
|
||||
if (WS_IN6_IS_ADDR_MULTICAST( addr ))
|
||||
return htons( (addr->u.Byte[1] & multicast_scope_mask) >> multicast_scope_shift );
|
||||
|
||||
if (!table) return -1;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (!memcmp( &table[i].addr, addr, sizeof(table[i].addr) ))
|
||||
return table[i].scope;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *key_data, DWORD key_size,
|
||||
void *rw, DWORD rw_size,
|
||||
struct nsi_tcp_conn_dynamic *dynamic_data, DWORD dynamic_size,
|
||||
|
@ -220,6 +337,8 @@ static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *
|
|||
struct nsi_tcp_conn_key key;
|
||||
struct nsi_tcp_conn_dynamic dyn;
|
||||
struct nsi_tcp_conn_static stat;
|
||||
struct ipv6_addr_scope *addr_scopes = NULL;
|
||||
unsigned int addr_scopes_size = 0;
|
||||
|
||||
#ifdef __linux__
|
||||
{
|
||||
|
@ -269,6 +388,8 @@ static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *
|
|||
memset( &dyn, 0, sizeof(dyn) );
|
||||
memset( &stat, 0, sizeof(stat) );
|
||||
|
||||
addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
|
||||
|
||||
/* skip header line */
|
||||
ptr = fgets( buf, sizeof(buf), fp );
|
||||
while ((ptr = fgets( buf, sizeof(buf), fp )))
|
||||
|
@ -286,8 +407,10 @@ static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *
|
|||
key.local.Ipv6.sin6_family = key.remote.Ipv6.sin6_family = WS_AF_INET6;
|
||||
key.local.Ipv6.sin6_port = htons( key.local.Ipv6.sin6_port );
|
||||
key.remote.Ipv6.sin6_port = htons( key.remote.Ipv6.sin6_port );
|
||||
key.local.Ipv6.sin6_scope_id = 0; /* FIXME */
|
||||
key.remote.Ipv6.sin6_scope_id = 0; /* FIXME */
|
||||
key.local.Ipv6.sin6_scope_id = find_ipv6_addr_scope( &key.local.Ipv6.sin6_addr, addr_scopes,
|
||||
addr_scopes_size );
|
||||
key.remote.Ipv6.sin6_scope_id = find_ipv6_addr_scope( &key.remote.Ipv6.sin6_addr, addr_scopes,
|
||||
addr_scopes_size );
|
||||
|
||||
stat.pid = 0; /* FIXME */
|
||||
stat.create_time = 0; /* FIXME */
|
||||
|
@ -335,6 +458,8 @@ static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *
|
|||
/* Might be nothing here; first entry is just a header it seems */
|
||||
if (len <= sizeof(struct xinpgen)) goto err;
|
||||
|
||||
addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
|
||||
|
||||
orig_xig = (struct xinpgen *)buf;
|
||||
xig = orig_xig;
|
||||
|
||||
|
@ -384,10 +509,12 @@ static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *
|
|||
key.local.Ipv6.sin6_family = key.remote.Ipv6.sin6_family = WS_AF_INET6;
|
||||
memcpy( &key.local.Ipv6.sin6_addr, &in->in6p_laddr, sizeof(in->in6p_laddr) );
|
||||
key.local.Ipv6.sin6_port = in->inp_lport;
|
||||
key.local.Ipv6.sin6_scope_id = find_ipv6_addr_scope( &key.local.Ipv6.sin6_addr, addr_scopes,
|
||||
addr_scopes_size );
|
||||
memcpy( &key.remote.Ipv6.sin6_addr, &in->in6p_faddr, sizeof(in->in6p_faddr) );
|
||||
key.remote.Ipv6.sin6_port = in->inp_fport;
|
||||
key.local.Ipv6.sin6_scope_id = 0; /* FIXME */
|
||||
key.remote.Ipv6.sin6_scope_id = 0; /* FIXME */
|
||||
key.remote.Ipv6.sin6_scope_id = find_ipv6_addr_scope( &key.remote.Ipv6.sin6_addr, addr_scopes,
|
||||
addr_scopes_size );
|
||||
}
|
||||
|
||||
stat.pid = 0; /* FIXME */
|
||||
|
@ -413,6 +540,7 @@ static NTSTATUS tcp_conns_enumerate_all( DWORD filter, struct nsi_tcp_conn_key *
|
|||
if (!want_data || num <= *count) *count = num;
|
||||
else status = STATUS_MORE_ENTRIES;
|
||||
|
||||
heap_free( addr_scopes );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue