ws2_32: Implement AI_DNS_ONLY using DNS APIs.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52133 Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d0acbcb0d7
commit
7c39ce0a6c
|
@ -1,7 +1,7 @@
|
|||
MODULE = ws2_32.dll
|
||||
UNIXLIB = ws2_32.so
|
||||
IMPORTLIB = ws2_32
|
||||
DELAYIMPORTS = advapi32 iphlpapi user32
|
||||
DELAYIMPORTS = dnsapi advapi32 iphlpapi user32
|
||||
|
||||
C_SRCS = \
|
||||
async.c \
|
||||
|
|
|
@ -69,6 +69,84 @@ static int do_getaddrinfo( const char *node, const char *service,
|
|||
}
|
||||
}
|
||||
|
||||
static int dns_only_query( const char *node, const struct addrinfo *hints, struct addrinfo **result )
|
||||
{
|
||||
DNS_STATUS status;
|
||||
DNS_RECORDA *rec = NULL, *rec6 = NULL, *ptr;
|
||||
struct addrinfo *info, *next;
|
||||
struct sockaddr_in *addr;
|
||||
struct sockaddr_in6 *addr6;
|
||||
ULONG count = 0;
|
||||
|
||||
if (hints->ai_family != AF_INET && hints->ai_family != AF_INET6 && hints->ai_family != AF_UNSPEC)
|
||||
{
|
||||
FIXME( "unsupported family %u\n", hints->ai_family );
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC)
|
||||
{
|
||||
status = DnsQuery_A( node, DNS_TYPE_A, DNS_QUERY_NO_NETBT | DNS_QUERY_NO_MULTICAST, NULL, &rec, NULL );
|
||||
if (status != ERROR_SUCCESS && status != DNS_ERROR_RCODE_NAME_ERROR) return EAI_FAIL;
|
||||
}
|
||||
if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC)
|
||||
{
|
||||
status = DnsQuery_A( node, DNS_TYPE_AAAA, DNS_QUERY_NO_NETBT | DNS_QUERY_NO_MULTICAST, NULL, &rec6, NULL );
|
||||
if (status != ERROR_SUCCESS && status != DNS_ERROR_RCODE_NAME_ERROR)
|
||||
{
|
||||
DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
|
||||
return EAI_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
for (ptr = rec; ptr; ptr = ptr->pNext) count++;
|
||||
for (ptr = rec6; ptr; ptr = ptr->pNext) count++;
|
||||
if (!count)
|
||||
{
|
||||
DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
|
||||
DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
|
||||
return WSAHOST_NOT_FOUND;
|
||||
}
|
||||
if (!(info = calloc( count, sizeof(*info) + sizeof(SOCKADDR_STORAGE) )))
|
||||
{
|
||||
DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
|
||||
DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
|
||||
return WSA_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
*result = info;
|
||||
|
||||
for (ptr = rec; ptr; ptr = ptr->pNext)
|
||||
{
|
||||
info->ai_family = AF_INET;
|
||||
info->ai_socktype = hints->ai_socktype;
|
||||
info->ai_protocol = hints->ai_protocol;
|
||||
info->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
info->ai_addr = (struct sockaddr *)(info + 1);
|
||||
addr = (struct sockaddr_in *)info->ai_addr;
|
||||
addr->sin_family = info->ai_family;
|
||||
addr->sin_addr.S_un.S_addr = ptr->Data.A.IpAddress;
|
||||
next = (struct addrinfo *)((char *)info + sizeof(*info) + sizeof(SOCKADDR_STORAGE));
|
||||
if (--count) info->ai_next = next;
|
||||
info = next;
|
||||
}
|
||||
for (ptr = rec6; ptr; ptr = ptr->pNext)
|
||||
{
|
||||
info->ai_family = AF_INET6;
|
||||
info->ai_socktype = hints->ai_socktype;
|
||||
info->ai_protocol = hints->ai_protocol;
|
||||
info->ai_addrlen = sizeof(struct sockaddr_in6);
|
||||
info->ai_addr = (struct sockaddr *)(info + 1);
|
||||
addr6 = (struct sockaddr_in6 *)info->ai_addr;
|
||||
addr6->sin6_family = info->ai_family;
|
||||
memcpy( &addr6->sin6_addr, &ptr->Data.AAAA.Ip6Address, sizeof(addr6->sin6_addr) );
|
||||
next = (struct addrinfo *)((char *)info + sizeof(*info) + sizeof(SOCKADDR_STORAGE));
|
||||
if (--count) info->ai_next = next;
|
||||
info = next;
|
||||
}
|
||||
|
||||
DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
|
||||
DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* getaddrinfo (ws2_32.@)
|
||||
|
@ -96,6 +174,11 @@ int WINAPI getaddrinfo( const char *node, const char *service,
|
|||
if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
|
||||
node = fqdn;
|
||||
}
|
||||
else if (!service && hints && (hints->ai_flags == AI_DNS_ONLY || hints->ai_flags == (AI_ALL | AI_DNS_ONLY)))
|
||||
{
|
||||
ret = dns_only_query( node, hints, info );
|
||||
goto done;
|
||||
}
|
||||
else if (!hints || hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET6)
|
||||
{
|
||||
/* [ipv6] or [ipv6]:portnumber are supported by Windows */
|
||||
|
@ -139,6 +222,7 @@ int WINAPI getaddrinfo( const char *node, const char *service,
|
|||
free( fqdn );
|
||||
free( nodev6 );
|
||||
|
||||
done:
|
||||
if (!ret && TRACE_ON(winsock))
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
|
|
|
@ -2328,6 +2328,26 @@ static void test_getaddrinfo(void)
|
|||
memset(&hint, 0, sizeof(hint));
|
||||
ret = getaddrinfo(NULL, "nonexistentservice", &hint, &result);
|
||||
ok(ret == WSATYPE_NOT_FOUND, "got %d\n", ret);
|
||||
|
||||
result = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
hint.ai_flags = AI_ALL | AI_DNS_ONLY;
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
ret = getaddrinfo("winehq.org", NULL, &hint, &result);
|
||||
ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
|
||||
ok(!result->ai_flags, "ai_flags == %08x\n", result->ai_flags);
|
||||
ok(result->ai_family == AF_INET, "ai_family == %d\n", result->ai_family);
|
||||
ok(result->ai_socktype == SOCK_STREAM, "ai_socktype == %d\n", result->ai_socktype);
|
||||
ok(result->ai_protocol == IPPROTO_TCP, "ai_protocol == %d\n", result->ai_protocol);
|
||||
ok(!result->ai_canonname, "ai_canonname == %s\n", result->ai_canonname);
|
||||
ok(result->ai_addrlen == sizeof(struct sockaddr_in), "ai_addrlen == %d\n", (int)result->ai_addrlen);
|
||||
ok(result->ai_addr != NULL, "ai_addr == NULL\n");
|
||||
sockaddr = (SOCKADDR_IN *)result->ai_addr;
|
||||
ok(sockaddr->sin_family == AF_INET, "ai_addr->sin_family == %d\n", sockaddr->sin_family);
|
||||
ok(sockaddr->sin_port == 0, "ai_addr->sin_port == %d\n", sockaddr->sin_port);
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
|
||||
static void test_dns(void)
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#define USE_WC_PREFIX /* For CMSG_DATA */
|
||||
#include "iphlpapi.h"
|
||||
#include "ip2string.h"
|
||||
#include "windns.h"
|
||||
#include "wine/afd.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unixlib.h"
|
||||
|
|
|
@ -284,6 +284,12 @@ typedef struct _WSAMSG {
|
|||
(((unsigned char*)cmsg + WSA_CMSG_ALIGN(cmsg->cmsg_len)+WSA_CMSG_ALIGN(((WSACMSGHDR*)((unsigned char*)cmsg + WSA_CMSG_ALIGN(cmsg->cmsg_len)))->cmsg_len) > ((unsigned char*)(mhdr)->Control.buf + (mhdr)->Control.len)) ? NULL : \
|
||||
(WSACMSGHDR*)((unsigned char*)cmsg + WSA_CMSG_ALIGN(cmsg->cmsg_len))))))
|
||||
|
||||
#ifndef USE_WS_PREFIX
|
||||
#define AI_DNS_ONLY 0x00000010
|
||||
#else
|
||||
#define WS_AI_DNS_ONLY 0x00000010
|
||||
#endif
|
||||
|
||||
typedef struct addrinfoexA {
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
|
|
Loading…
Reference in New Issue