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


Comments

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • Due to internal controls and regulations, the amount of long term archival data is increasing every year. Since magnetic tape does not need to be periodically operated or connected to a power source, there will be no data loss because of performance degradation due to the drive actuator. Read this white paper to learn about a series of tests that determined magnetic tape is a reliable long-term storage solution for up to 30 years.

Most Popular Programming Stories

More for Developers

RSS Feeds