Question

For IPAddress 66.249.68.9 ("dig -x" correctly says "crawl-66-249-68-9.googlebot.com") my lovely program is claiming it's ip68-9-0-0.ri.ri.cox.net.

I don't care if I wind up doing it a way resembling the code below, just want to be able to start with an IPV4 IP address and wind up with a hostname.

Bonus question, what's service? I figure I won't need it, and will give getnameinfo NULL. But, the program is outputting "17145" for serviceBuffer.

#include <string>
#include <iostream>
using namespace std;

#include <netdb.h> // struct sockaddr, AF_INET, NI_NAMEREQD, getnameinfo
#include <string.h> // memset
#include <arpa/inet.h> // inet_pton

int main() {
   const string IPAddress { "66.249.68.9" };

   struct sockaddr structSockAddr;
   memset(&structSockAddr, 0, sizeof(structSockAddr));

   structSockAddr.sa_family = AF_INET;
   int inetPtonReturnValue { inet_pton(AF_INET, IPAddress.c_str(), &structSockAddr.sa_data) };
   if(1 != inetPtonReturnValue) {
      cout << "inetPtonReturnValue : " << inetPtonReturnValue << endl; // 0 = src doesn't contain valid address, -1 = af isn't a valid family
   }

   char hostBuffer[10000];
   char serviceBuffer[1000];

   int getNameInfoReturnValue { getnameinfo(&structSockAddr, sizeof(structSockAddr), hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NAMEREQD) };

   if(0 != getNameInfoReturnValue) {
      cout << "getNameInfoReturnValue : " << getNameInfoReturnValue << endl
           << "gai_strerror() : " << gai_strerror(getNameInfoReturnValue) << endl;
   } else {
      cout << "IPAddress : " << IPAddress << endl
           << "hostBuffer : " << hostBuffer << endl
           << "serviceBuffer : " << serviceBuffer << endl;
   }
}
Was it helpful?

Solution

You are using a struct sockaddr when calling inet_pton but the calling signature requires that this is either an struct in_addr for AF_INET (or struct in6_addr for IPv6). And then you'd have to use that in building a struct sockaddr for the later function.

As it currently stands, you are writing some of the bytes for the address into fields before the field containing the actual IP address, so you end up with just the last 2 octets of the IP in your sockaddr field.

OTHER TIPS

Here is a broken down C++ example of reverse DNS lookup

// Variables
WSADATA wsaData = { 0 };
int iResult = 0;
DWORD dwRetval;
struct sockaddr_in saGNI;
char hostname[NI_MAXHOST];
char servInfo[NI_MAXSERV];
std::string ip = "YOUR_SERVER_IP";
int port = 25;

iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult == 0 /*initialization success*/) {
    saGNI.sin_family = AF_INET;
    saGNI.sin_addr.s_addr = inet_addr(ip.c_str());
    saGNI.sin_port = htons(port);

    dwRetval = getnameinfo((struct sockaddr*) & saGNI,
        sizeof(struct sockaddr),
        hostname,
        NI_MAXHOST, servInfo, NI_MAXSERV, NI_NUMERICSERV);

    if (dwRetval == 0) {
        // save hostname result
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top