Get IPv6 DNS Server Addresses using GetAdaptersAddresses()

Viewed 187

I am trying to get the DNS Server IPv6 addresses in C++, and I found this article showing how to get the information using GetAdaptersAddresses(): GetAdaptersAddresses function (iphlpapi.h). This article also provides example code. Going through the instructions, it says the FirstDnsServerAddress member of the IP_ADAPTER_ADDRESSES structure is a pointer to a linked list of IP_ADAPTER_DNS_SERVER_ADDRESS structures. The SOCKET_ADDRESS structure is used in the IP_ADAPTER_DNS_SERVER_ADDRESS structure. The SOCKADDR structure pointed to by the lpSockaddr member varies depending on the protocol or address family selected. For example, the sockaddr_in6 structure is used for an IPv6 socket address while the sockaddr_in4 structure is used for an IPv4 socket address. Based on those instructions I modified the example code to get the IP addresses as follows:

pDnServer = pCurrAddresses->FirstDnsServerAddress;
if (pDnServer) {
    for (i = 0; pDnServer != NULL; i++) {
        switch (pDnServer->Address.lpSockaddr->sa_family) {
            case AF_INET:
                if (pDnServer->Address.lpSockaddr) {
                    char* ipv4_addrstr = (char*)malloc(INET_ADDRSTRLEN * sizeof(char));
                    inet_ntop(AF_INET, (struct sockaddr_in*)pDnServer->Address.lpSockaddr->sa_data, ipv4_addrstr, INET_ADDRSTRLEN);
                    printf("IPv4 Address: %s\n", ipv4_addrstr);
                    free(ipv4_addrstr);
                }
                break;
            case AF_INET6: 
                if (pDnServer->Address.lpSockaddr) {
                    char* ipv6_addrstr = (char*)malloc(INET6_ADDRSTRLEN * sizeof(char));
                    memset(ipv6_addrstr, 0, sizeof(char) * INET6_ADDRSTRLEN);
                    inet_ntop(AF_INET6, (struct sockaddr_in6*)pDnServer->Address.lpSockaddr->sa_data, ipv6_addrstr, INET6_ADDRSTRLEN);
                    printf("IPv6 Address: %s\n", ipv6_addrstr);
                    free(ipv6_addrstr);
                }
                break;

            default:
                printf("\tAddress Family Name: Unknown\n");
                break;
        } // End switch
        pDnServer = pDnServer->Next;
    } // End for loop
        
    printf("\tNumber of DNS Server Addresses: %d\n", i);
}

The code gets the IPv4 DNS Server addresses correctly. However, the code is returning incorrect IPv6 addresses. For example, the Google DNS Server addresses are 2001:4860:4860::8888 and 2001:4860:4860::8844. If I enter these addresses as my IPv4 DNS Server addresses, the code returns ::2001:4860:4860:0:0.

Does anyone know what I might have wrong in this code?

1 Answers

You're passing the wrong data to inet_ntop. You should pass the sin_addr or sin6_addr member, depending on the protocol.

inet_ntop(AF_INET, &((struct sockaddr_in*)pDnServer->Address.lpSockaddr)->sin_addr, ipv4_addrstr, INET_ADDRSTRLEN);
inet_ntop(AF_INET6, &((struct sockaddr_in6*)pDnServer->Address.lpSockaddr)->sin6_addr, ipv6_addrstr, INET6_ADDRSTRLEN);
Related