From: Bill Kelly Date: 2007-11-29T04:17:37+09:00 Subject: Socket.gethostbyname and Reverse Lookups: A Strange and Terrible Saga (with apologies to Hunter Thompson ;) Greetings, I've been using Socket.gethostbyname to perform reverse lookups. The socket.c documentation in the ruby_1_8 branch indicates this usage is allowed: * +host+ can also be an IP address in presentation format, in which case a * reverse lookup is done on the address: * * Socket.gethostbyname("127.0.0.1") * => ["localhost", [], 2, "\177\000\000\001"] * * Socket.gethostbyname("192.0.34.166") * => ["www.example.com", [], 2, "\300\000\"\246"] (Note, this documentation seems to be missing from socket.c in trunk.) Anyway this was working fine for me until I upgraded my OS to the current debian stable (etch). Suddenly Socket.gethostbyname stopped doing reverse lookups and just returned the original IP address that was passed in. Since Socket.gethostbyname uses getaddrinfo() behind the scenes to do the lookup, I made a small C test program. I was able to confirm that getaddrinfo() was doing reverse lookups on older OS versions, but not doing reverse lookups on the new OS: http://cila-search.net/~billk/debug/getaddrinfo/ So I set about debugging the GNU libc getaddrinfo implementation to try to determine why it had stopped working. Just as I was coming to the conclusion that there appeared to be a bug in glibc, I was informed by someone whose email address ends in a rather authoritative-sounding @linux-ipv6.org, that: It is nothing to do with amd64, but the usage; getaddrinfo() is not for reserve DNS lookups. For that purpose, use getnameinfo() instead. And he kindly modified my test program to show getnameinfo() usage: #include #include #include #include #include #include int main () { const char *host = "208.77.188.166"; // www.example.com const char *port = NULL; int socktype = SOCK_STREAM; struct addrinfo hints; struct addrinfo* res = NULL; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = socktype; hints.ai_flags = 0; error = getaddrinfo(host, port, &hints, &res); if (error) { fprintf(stderr, "sock_addrinfo: error=%d: %s\n", error, gai_strerror(error)); return 4; } if (res) { char hostbuf[NI_MAXHOST] = "???"; error = getnameinfo(res->ai_addr, res->ai_addrlen, hostbuf, sizeof(hostbuf), NULL, 0, 0); fprintf(stderr, "sock_nameinfo: error=%d, host=%s\n", error, hostbuf); freeaddrinfo(res); } return 0; } So.... On the one hand I'm left wondering why getaddrinfo() previously used to do reverse lookups, if it's not supposed to. But anyway, if the above information is correct, then it seems Ruby's Socket.gethostbyname should be changed to use getnameinfo() instead of just getaddrinfo() to perform reverse lookups. That's all the information I have so far. Does anyone have any additional or contrary information? It's been a heck of a wild goose chase, so far... :D Regards, Bill