Resolving Host Names

Environment: Visual C++ 6.0

Introduction

Most of the code that I’ve come across to resolve the name of an IP address uses the gethostbyaddr API to accomplish this task. gethostbyaddr may eventually resort to using NetBIOS (port 137) to come up with the name. According to MSDN, gethostbyaddr is actually deprecated by the getnameinfo API. getnameinfo does a reverse lookup of an IP Address without using NetBIOS.

I recently had a request to put together a DLL that implements the getnameinfo API to be used by a VB application. Given the IP address as a string, the resolved name was to be returned (also as a string). The reason for the getnameinfo implementation was to avoid an unwanted “NetBIOS echo” on port 137 that could occur using gethostbyaddr. I conducted various searches on the Net and although I found some code implementing getnameinfo, there was nothing I found that started with an IP address as a string. So, I went to work and came up with this implementation.

Testing Results

Extensive testing was conducted to compare the difference in behavior of the two APIs. What was discovered was the following: First, despite MSDN’s specification that getnameinfo was not supported by Win9x, it does appear to work under that OS. There is some speculation that under the unsupported OS’s, the getnameinfo API operates like gethostbyaddr. In addition, there has been inconsistent behavior observed running under Windows NT 4. MSDN does not mention whether getnameinfo specifically supports NT 4 or not. In one case it worked fine on a plain system with NT Workstation 4 SP6. Using a different system with NT Server 4 SP6, it crashed. Any additional information that anyone could provide on this issue would be appreciated. Second, there were some significant differences between the results returned using the two APIs (see below). Over 7000 IP’s were processed and the following was noted:

  1. getnameinfo is not always instantaneous. It often takes over 3 seconds (usually to fail), and sometimes over 15 seconds (always to fail). Most of the time, it takes a fraction of a second.
  2. gethostbyaddr often succeeds where getnameinfo fails. The difference is significant (perhaps 25%).
  3. When getnameinfo fails and gethostbyaddr succeeds, it’s usually because the address is for a page server, of the kind supplied by Akami. Many big operations use these outside servers for speed. The IP, probably obtained months ago, was for whatever server happened to respond from an outgoing request. This is not a symmetrical pair, however: the URL resolves to different IPs at different moments, but those IP’s don’t resolve to anything when you use getnameinfo. gethostbyaddr doesn’t stop at the Nameserver, but asks the IP to identify itself, and the answer usually is Akami, even though the original URL may have been Symantec or Microsoft.
  4. During the second part of this test, the program only used getnameinfo, but never used gethostbyaddr. It ran much faster, which confirms that the getnameinfo lookups are subject to shorter delays than the gethostbyaddr lookups. There was no record of ANY Outbound port 137 activity, which was the main reason to use getnameinfo.

Again, any information anyone can provide explaining these differences or observations would be appreciated.

The provided code is not within a DLL for simplicity’s sake. I have created a class called “FindName” that implements both the getnameinfo and gethostbyaddr APIs and creates a simple dialog based project to demo the class. The class has a dependency on the Ws2_32.lib library, so any project you include it in will have to have this dependency specified in the library modules option under the Link tab of the Project settings (General category). The Platform SDK needs to be installed for this to build properly. If you find that the project still does not build properly after installing the Platform SDK, try moving the Platform SDK include directory to the top of the order in Visual Studio, under Tools->Options->Directories->Include Files.


#define MAXADDRSTR 16

void FindName::getName(const std::string szIPAddress,
std::string& szURL)
{
char strURL[NI_MAXSERV];
char strDestMulti[MAXADDRSTR];
int iLen = MAXADDRSTR;

// intitialize the URL to nothing
strncpy(strURL, “”, NI_MAXSERV);

// copy provided IP address into a char* so we can use it
strncpy(strDestMulti, szIPAddress.c_str(), MAXADDRSTR);

SOCKADDR_IN stDestAddr;
WSADATA stWSAData;

// init WinSock
int err = WSAStartup(0x0202, &stWSAData);

// convert address string to value
stDestAddr.sin_family = AF_INET;
int nRet = WSAStringToAddress(strDestMulti, AF_INET, NULL,
(LPSOCKADDR)&stDestAddr, &iLen);

if(getnameinfo((LPSOCKADDR)&stDestAddr,
sizeof(stDestAddr),
strURL,
sizeof(strURL),
NULL,
0,
NI_NAMEREQD) != 0)
{
szURL = “not found”;
}
else
{
// we’ve resolved the name. Pass it back
szURL = strURL;
}

// terminate winsock
err = WSACleanup();
}

Downloads


Download demo project – 12 Kb


Download source – 2 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read