(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 <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

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