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: