Issue with GetAddrInfoExW: Only Receiving IPv4 Addresses, Not IPv6

Harshal Goyal 20 Reputation points
2025-01-09T12:51:37.7033333+00:00

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.

  1. Is there something wrong with the way I'm setting the hints structure for GetAddrInfoExW to properly request both IPv4 and IPv6?
  2. 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!

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,717 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.