admin管理员组

文章数量:1124806

I'm using the GetAddrInfoExW function in my application to resolve both IPv4 and IPv6 addresses for a given hostname (e.g., google). However, I'm only receiving IPv4 addresses in the results, and I don't see any IPv6 addresses, even though I can see that only ipv4 requests are being queried.

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";
    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.

Sidenote: when I run same resolution using nslookup I am able to resolve both IPv4 and IPv6 addresses.

Is there something wrong with the way I'm setting the hints structure for GetAddrInfoExW 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.

本文标签: cIssue with GetAddrInfoExW Only Receiving IPv4 AddressesNot IPv6Stack Overflow