[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#160596: workaround for problems with getaddrinfo and IPv6



Many users have suffered because getaddrinfo insists on doing
IPv6 lookup.  Suffering may be the price of abstraction, but
you don't in fact have to live with it.  If you're willing
to forgo IPv6 answers to unspecified queries, you can change
the behavior of getaddrinfo.  The following LJ article
explains the general technique:

http://www.linuxjournal.com/article/7795

And I have attached C code that, when compiled to .so and 
included in LD_PRELOAD, prevents getaddrinfo from doing IPv6 lookups
on requests for unspecified families.  For those of us using home
networks, especially if we are stuck behind a hardware router
that doesn't respond to AAAA DNS queries (thanks Microsoft),
this fix is a godsend.


Norman

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

/* if getaddrinfo() is called with explicit hints and unspecified
   family, don't even think about using IPv6 */

int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res) {
  static int (*libgetaddrinfo)(const char *node, const char *service,
                               const struct addrinfo *hints,
                               struct addrinfo **res);
  struct addrinfo myhints;
  const struct addrinfo *myhintsp = &myhints;
  if (hints && hints->ai_family == AF_UNSPEC) {
    myhints = *hints;
    myhints.ai_family = AF_INET;
  } else {
    myhintsp = hints;
  }
  if (!libgetaddrinfo) {
    void *handle;
    char *error;
    handle = dlopen("libc.so.6", RTLD_LAZY);
    if (!handle) {
      fputs(dlerror(), stderr);
      exit(1);
    }
    libgetaddrinfo = dlsym(handle, "getaddrinfo");
    if ((error = dlerror()) != NULL) {
      fprintf(stderr, "%s\n", error);
      exit(1);
    }
  }
  return libgetaddrinfo(node, service, myhintsp, res);
}

Reply to: