Issue with GetAddrInfoExW: Only Receiving IPv4 Addresses, Not IPv6
Hello,
I'm using the GetAddrInfoExW
function in my application to resolve both IPv4 and IPv6 addresses for a given hostname (e.g., google.com
). However, I'm only receiving IPv4 addresses in the results, and I don't see any IPv6 addresses, even though I am setting AF_UNSPEC as hint, I can see that only ipv4 requests are being queried on Wireshark.
Here is a snippet of the relevant code I'm using to perform the query:
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <thread>
#include <atomic>
#pragma comment(lib, "ws2_32.lib")
#define MAX_ADDRESS_STRING_LENGTH 64
struct DNS_QUERY_CONTEXT
{
OVERLAPPED uOverlapped;
PADDRINFOEX uResult;
HANDLE uCancelOpsHandle;
};
bool InitWinsock()
{
WSADATA wsaData;
return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
}
void CALLBACK LookupServiceCompletionRoutine(DWORD dwError, DWORD dwBytes, LPWSAOVERLAPPED lpOverlapped)
{
if (dwError != 0) {
std::cout << "Failed to resolve DNS "<< dwError;
return;
}
DNS_QUERY_CONTEXT * context = (DNS_QUERY_CONTEXT *) lpOverlapped;
ADDRINFOEX * ptr = context->uResult;
if (ptr == NULL) {
std::cout << "No results found\n";
return;
}
int i = 1;
wchar_t ipstringbuffer [128];
while (ptr != NULL) {
std::cout << "GetAddrInfoEx response " << i++ << std::endl;
std::cout << "\tFlags: " << ptr->ai_flags << std::endl;
std::cout << "\tFamily: ";
switch (ptr->ai_family) {
case AF_UNSPEC:
std::cout << "UNSPEC (Unspecified)" << std::endl;
break;
case AF_INET:
{
std::cout << "AF_INET (IPv4)" << std::endl;
struct sockaddr_in * sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
InetNtop(AF_INET, &(sockaddr_ipv4->sin_addr), ipstringbuffer, INET_ADDRSTRLEN);
std::wcout << L"\tIPv4 Address: " << ipstringbuffer << std::endl;
break;
}
case AF_INET6:
{ // IPv6
std::cout << "AF_INET6 (IPv6)" << std::endl;
struct sockaddr_in6 * sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
InetNtop(AF_INET6, &(sockaddr_ipv6->sin6_addr), ipstringbuffer, INET6_ADDRSTRLEN);
std::wcout << L"\tIPv6 Address: " << ipstringbuffer << std::endl;
break;
}
default:
std::cout << "Unknown Family: " << ptr->ai_family << std::endl;
break;
}
ptr = ptr->ai_next;
}
FreeAddrInfoEx(context->uResult);
delete context;
}
int main()
{
DNS_QUERY_CONTEXT * context;
ADDRINFOEXW hints;
const wchar_t * query = L"google.com";
int error;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
hints.ai_socktype = 0;
hints.ai_protocol = 0;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
context = new DNS_QUERY_CONTEXT;
ZeroMemory(context, sizeof(DNS_QUERY_CONTEXT));
if (!InitWinsock()) {
std::cerr << "WSAStartup failed" << std::endl;
return 1;
}
context->uOverlapped.hEvent = NULL;
error = GetAddrInfoExW(
query, // Hostname to resolve
NULL, // Service name
NS_DNS, // Namespace
NULL, // Query context
&hints, // Hints
&context->uResult, // Result
NULL, // Timeout
&context->uOverlapped, // Overlapped structure
LookupServiceCompletionRoutine, // Completion routine
&context->uCancelOpsHandle // Cancel handle
);
if (error != WSA_IO_PENDING) {
std::cerr << "GetAddrInfoExW failed: " << WSAGetLastError() << std::endl;
delete context;
WSACleanup();
return 1;
}
std::cout << "DNS query initiated, waiting for results..." << std::endl;
while (true);
WSACleanup();
return 0;
}
Despite specifying AF_UNSPEC it only queries for ipv4 addresses in callback function. When I try to specify the hints as AF_INET6 the query fails with error code 11004. I have confirmed that GetAddrInfoExW
returns the correct response code and that ai_family
in the returned ADDRINFOEX
structure is set to AF_INET
.
- Is there something wrong with the way I'm setting the
hints
structure forGetAddrInfoExW
to properly request both IPv4 and IPv6? - Is there any other possible issue that could cause the function to ignore the IPv6 results?
Any help or insight would be greatly appreciated. Thanks in advance!