mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-02 14:13:48 +00:00
wpcap: Build pcap_address structure from IP_ADAPTER_UNICAST_ADDRESS.
This commit is contained in:
parent
6d01d01455
commit
382dbe77f6
|
@ -17,18 +17,13 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct sockaddr_hdr
|
|
||||||
{
|
|
||||||
unsigned short sa_family;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pcap_address
|
struct pcap_address
|
||||||
{
|
{
|
||||||
struct pcap_address *next;
|
struct pcap_address *next;
|
||||||
struct sockaddr_hdr *addr;
|
struct sockaddr *addr;
|
||||||
struct sockaddr_hdr *netmask;
|
struct sockaddr *netmask;
|
||||||
struct sockaddr_hdr *broadaddr;
|
struct sockaddr *broadaddr;
|
||||||
struct sockaddr_hdr *dstaddr;
|
struct sockaddr *dstaddr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcap_interface
|
struct pcap_interface
|
||||||
|
@ -57,7 +52,6 @@ struct pcap
|
||||||
struct pcap_pkthdr_win32 hdr;
|
struct pcap_pkthdr_win32 hdr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct compile_params
|
struct compile_params
|
||||||
{
|
{
|
||||||
struct pcap *pcap;
|
struct pcap *pcap;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "winsock2.h"
|
#include "winsock2.h"
|
||||||
#include "ws2ipdef.h"
|
#include "ws2ipdef.h"
|
||||||
#include "iphlpapi.h"
|
#include "iphlpapi.h"
|
||||||
|
#include "netioapi.h"
|
||||||
|
|
||||||
#include "wine/unixlib.h"
|
#include "wine/unixlib.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
@ -236,59 +237,109 @@ static char *build_win32_description( const struct pcap_interface *unix_dev )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sockaddr_hdr *dup_sockaddr( const struct sockaddr_hdr *addr )
|
static struct sockaddr *get_address( const IP_ADAPTER_UNICAST_ADDRESS *addr )
|
||||||
{
|
{
|
||||||
struct sockaddr_hdr *ret;
|
struct sockaddr *ret;
|
||||||
|
if (!(ret = malloc( addr->Address.iSockaddrLength ))) return NULL;
|
||||||
|
memcpy( ret, addr->Address.lpSockaddr, addr->Address.iSockaddrLength );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr->sa_family)
|
static void convert_length_to_ipv6_mask( ULONG length, IN6_ADDR *mask )
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < length / 8; i++) mask->u.Byte[i] = 0xff;
|
||||||
|
mask->u.Byte[i] = 0xff << (8 - length % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sockaddr *get_netmask( const IP_ADAPTER_UNICAST_ADDRESS *addr )
|
||||||
|
{
|
||||||
|
struct sockaddr *ret;
|
||||||
|
|
||||||
|
switch (addr->Address.lpSockaddr->sa_family)
|
||||||
{
|
{
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
{
|
{
|
||||||
struct sockaddr_in *dst, *src = (struct sockaddr_in *)addr;
|
struct sockaddr_in *netmask_addr_in;
|
||||||
if (!(dst = calloc( 1, sizeof(*dst) ))) return NULL;
|
|
||||||
dst->sin_family = src->sin_family;
|
if (!(netmask_addr_in = calloc( 1, sizeof(*netmask_addr_in) ))) return NULL;
|
||||||
dst->sin_port = src->sin_port;
|
netmask_addr_in->sin_family = AF_INET;
|
||||||
dst->sin_addr = src->sin_addr;
|
ConvertLengthToIpv4Mask( addr->OnLinkPrefixLength, &netmask_addr_in->sin_addr.S_un.S_addr );
|
||||||
ret = (struct sockaddr_hdr *)dst;
|
ret = (struct sockaddr *)netmask_addr_in;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
{
|
{
|
||||||
struct sockaddr_in6 *dst, *src = (struct sockaddr_in6 *)addr;
|
struct sockaddr_in6 *netmask_addr_in6;
|
||||||
if (!(dst = malloc( sizeof(*dst) ))) return NULL;
|
|
||||||
dst->sin6_family = src->sin6_family;
|
if (!(netmask_addr_in6 = calloc( 1, sizeof(*netmask_addr_in6) ))) return NULL;
|
||||||
dst->sin6_port = src->sin6_port;
|
netmask_addr_in6->sin6_family = AF_INET6;
|
||||||
dst->sin6_flowinfo = src->sin6_flowinfo;
|
convert_length_to_ipv6_mask( addr->OnLinkPrefixLength, &netmask_addr_in6->sin6_addr );
|
||||||
dst->sin6_addr = src->sin6_addr;
|
ret = (struct sockaddr *)netmask_addr_in6;
|
||||||
dst->sin6_scope_id = src->sin6_scope_id;
|
|
||||||
ret = (struct sockaddr_hdr *)dst;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
FIXME( "address family %u not supported\n", addr->sa_family );
|
FIXME( "address family %u not supported\n", addr->Address.lpSockaddr->sa_family );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pcap_address *build_win32_address( struct pcap_address *src )
|
static struct sockaddr *get_broadcast( const IP_ADAPTER_UNICAST_ADDRESS *addr )
|
||||||
{
|
{
|
||||||
struct pcap_address *dst;
|
struct sockaddr *ret;
|
||||||
|
|
||||||
if (!(dst = calloc( 1, sizeof(*dst) ))) return NULL;
|
switch (addr->Address.lpSockaddr->sa_family)
|
||||||
if (src->addr && !(dst->addr = dup_sockaddr( src->addr ))) goto err;
|
{
|
||||||
if (src->netmask && !(dst->netmask = dup_sockaddr( src->netmask ))) goto err;
|
case AF_INET:
|
||||||
if (src->broadaddr && !(dst->broadaddr = dup_sockaddr( src->broadaddr ))) goto err;
|
{
|
||||||
if (src->dstaddr && !(dst->dstaddr = dup_sockaddr( src->dstaddr ))) goto err;
|
struct sockaddr_in *broadcast_addr_in, *addr_in = (struct sockaddr_in *)addr->Address.lpSockaddr;
|
||||||
return dst;
|
ULONG netmask;
|
||||||
|
|
||||||
|
if (!(broadcast_addr_in = calloc( 1, sizeof(*broadcast_addr_in) ))) return FALSE;
|
||||||
|
broadcast_addr_in->sin_family = AF_INET;
|
||||||
|
ConvertLengthToIpv4Mask( addr->OnLinkPrefixLength, &netmask );
|
||||||
|
broadcast_addr_in->sin_addr.S_un.S_addr = addr_in->sin_addr.S_un.S_addr | ~netmask;
|
||||||
|
ret = (struct sockaddr *)broadcast_addr_in;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *broadcast_addr_in6, *addr_in6 = (struct sockaddr_in6 *)addr->Address.lpSockaddr;
|
||||||
|
IN6_ADDR netmask, *address = (IN6_ADDR *)&addr_in6->sin6_addr;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!(broadcast_addr_in6 = calloc( 1, sizeof(*broadcast_addr_in6) ))) return NULL;
|
||||||
|
broadcast_addr_in6->sin6_family = AF_INET6;
|
||||||
|
convert_length_to_ipv6_mask( addr->OnLinkPrefixLength, &netmask );
|
||||||
|
for (i = 0; i < 8; i++) broadcast_addr_in6->sin6_addr.u.Word[i] = address->u.Word[i] | ~netmask.u.Word[i];
|
||||||
|
ret = (struct sockaddr *)broadcast_addr_in6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
FIXME( "address family %u not supported\n", addr->Address.lpSockaddr->sa_family );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pcap_address *build_win32_address( const IP_ADAPTER_UNICAST_ADDRESS *addr )
|
||||||
|
{
|
||||||
|
struct pcap_address *ret;
|
||||||
|
|
||||||
|
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
|
||||||
|
if (!(ret->addr = get_address( addr ))) goto err;
|
||||||
|
if (!(ret->netmask = get_netmask( addr ))) goto err;
|
||||||
|
if (!(ret->broadaddr = get_broadcast( addr ))) goto err;
|
||||||
|
return ret;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free( dst->addr );
|
free( ret->addr );
|
||||||
free( dst->netmask );
|
free( ret->netmask );
|
||||||
free( dst->broadaddr );
|
free( ret->broadaddr );
|
||||||
free( dst->dstaddr );
|
free( ret );
|
||||||
free( dst );
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,27 +354,27 @@ static void add_win32_address( struct pcap_address **list, struct pcap_address *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pcap_address *build_win32_addresses( struct pcap_address *addrs )
|
static struct pcap_address *build_win32_addresses( const IP_ADAPTER_ADDRESSES *adapter )
|
||||||
{
|
{
|
||||||
struct pcap_address *src, *dst, *ret = NULL;
|
struct pcap_address *dst, *ret = NULL;
|
||||||
src = addrs;
|
IP_ADAPTER_UNICAST_ADDRESS *src = adapter->FirstUnicastAddress;
|
||||||
while (src)
|
while (src)
|
||||||
{
|
{
|
||||||
if ((dst = build_win32_address( src ))) add_win32_address( &ret, dst );
|
if ((dst = build_win32_address( src ))) add_win32_address( &ret, dst );
|
||||||
src = src->next;
|
src = src->Next;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pcap_interface *build_win32_device( const struct pcap_interface *unix_dev, const char *source,
|
static struct pcap_interface *build_win32_device( const struct pcap_interface *unix_dev, const char *source,
|
||||||
const char *adapter_name )
|
const IP_ADAPTER_ADDRESSES *adapter )
|
||||||
{
|
{
|
||||||
struct pcap_interface *ret;
|
struct pcap_interface *ret;
|
||||||
|
|
||||||
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
|
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
|
||||||
if (!(ret->name = build_win32_name( source, adapter_name ))) goto err;
|
if (!(ret->name = build_win32_name( source, adapter->AdapterName ))) goto err;
|
||||||
if (!(ret->description = build_win32_description( unix_dev ))) goto err;
|
if (!(ret->description = build_win32_description( unix_dev ))) goto err;
|
||||||
ret->addresses = build_win32_addresses( unix_dev->addresses );
|
ret->addresses = build_win32_addresses( adapter );
|
||||||
ret->flags = unix_dev->flags;
|
ret->flags = unix_dev->flags;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -364,7 +415,7 @@ static int find_all_devices( const char *source, struct pcap_interface **devs, c
|
||||||
cur = unix_devs;
|
cur = unix_devs;
|
||||||
while (cur)
|
while (cur)
|
||||||
{
|
{
|
||||||
if ((ptr = find_adapter( adapters, cur->name )) && (dev = build_win32_device( cur, source, ptr->AdapterName )))
|
if ((ptr = find_adapter( adapters, cur->name )) && (dev = build_win32_device( cur, source, ptr )))
|
||||||
{
|
{
|
||||||
add_win32_device( &win32_devs, dev );
|
add_win32_device( &win32_devs, dev );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue