views:

13

answers:

1

GetAdaptersAddresses() will get you addresses in IP_ADAPTER_UNICAST_ADDRESS format, which is defined as:

typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
  union {
    struct {
      ULONG Length;
      DWORD Flags;
    } ;
  } ;
  struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
  SOCKET_ADDRESS                     Address;
  IP_PREFIX_ORIGIN                   PrefixOrigin;
  IP_SUFFIX_ORIGIN                   SuffixOrigin;
  IP_DAD_STATE                       DadState;
  ULONG                              ValidLifetime;
  ULONG                              PreferredLifetime;
  ULONG                              LeaseLifetime;
  UINT8                              OnLinkPrefixLength;
} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;

The only field that seems to suggest the human-readable IP address string is Address, which is a SOCKET_ADDRESS structure defined as:

typedef struct _SOCKET_ADDRESS {
  LPSOCKADDR lpSockaddr;
  INT        iSockaddrLength;
} SOCKET_ADDRESS, *PSOCKET_ADDRESS;

Which, in turn, uses another structure, SOCKADDR, defined as:

Sorry, it's way to complex to post here, as it varies depending on IPv4 vs. IPv6 and the Windows edition... so here is a link to the definition:

http://msdn.microsoft.com/en-us/library/ms740496%28v=VS.85%29.aspx

If you haven't gotten dizzy yet like I did and followed through this maze of definitions, you probably noticed that it's a nightmare to retrieve the good old dotted string style of an IP address, as it used to be much easier using GetAdaptersInfo().

My question is: Is there a truly IP Helper function that can convert IP_ADAPTER_UNICAST_ADDRESS to an IPv4 dotted string (or an IPv6 string)?

+1  A: 

You can use GetIpAddrTable - the returned data structure contains a DWORD dwAddr that is the IPv4 address. The sample code on that first link should show you what you want. Brief excerpt to show you what I mean:

if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) { 
    printf("GetIpAddrTable failed with error %d\n", dwRetVal);
    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),       // Default language
                      (LPTSTR) & lpMsgBuf, 0, NULL)) {
        printf("\tError: %s", lpMsgBuf);
        LocalFree(lpMsgBuf);
    }
    exit(1);
}

printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
    printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
    IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
    printf("\tIP Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );

The IP_ADAPTER_UNICAST_ADDRESS contains a SOCKET_ADDRESS in Address, which in turn contains a LPSOCKADDR in lpSockAddr - you can convert this to the ipv4 string form using WSAAddressToString.

Steve Townsend
@Steve, thanks but this is not really what I was looking for. GetAdaptersAddresses() provides so much more information -- for both IPv4 and IPv6 -- and I would like to stick to it per Microsoft's recommendation. All I am missing is a "translator" convenience function that would take IP_ADAPTER_UNICAST_ADDRESS as a parameter and output a string. Instead of re-inventing the wheel and writing it myself, perhaps you know of such existing function? In the API itself or elsewhere, perhaps some sample?
Android Eve
@Android Eve - see edit, you can use `WSAAddressToString` for this.
Steve Townsend
Once again, you demonstrate an impressive knowledge of PSDK's IP Helper space. Thanks to your answer, I have been able to spot a few more related functions, notably RtlIpv4AddressToString() and RtlIpv6AddressToString() which, unfortunately exist in the WDK, not the PSDK. I will shortly mark your answer as accepted. Unless a newer answer suggests a function that does the same for *both* IPv6 and IPv4.
Android Eve
@Android Eve - see the docs - "While the `inet_ntoa` function works only with IPv4 addresses, the `WSAAddressToString` function works with any socket address supported by a Winsock provider on the local computer including IPv6 addresses."
Steve Townsend
@Steve, thanks so much. I can see that now. You are amazing.
Android Eve
@Android Eve - you are welcome - 13 yrs at Microsoft should have taught me something, I guess
Steve Townsend
Adding one more comment, to memorize in one place a related useful piece of information I just noticed: The IN6_ADDR structure used inRtlIpv6AddressToString() and that's defined in the In6addr.h header file, is a member of the SOCKADDR indirectly returned by GetAdaptersAddresses(). So, if WSAAddressToString() weren't availbe, there would still be a way to convert the addresses return by GetAdaptersAddresses() to strings, without having to write everything from scratch.
Android Eve