Hello, On 04/11/2014 12:23 PM, Manuel Bauer wrote: > Good idea, but that seems to work only with ip addresses, and not hostnames. > If I try it haproxy complains about an error in its config and refuses to > start. > > > On Fri, 11 Apr 2014 12:04:40 +0200, Nenad Merdanovic <ni...@nimzo.info> wrote: > >> Hello, >> >> On 04/11/2014 11:15 AM, Manuel Bauer wrote: >>> sorry for what is probably a pretty noob question, but could anyone tell me >>> why haproxy resolves the hostnames in my config to ipv4 addresses, and not >>> ipv6? If I run a tcpdump on port 53 during a haproxy restart I can see that >>> only the A records are being queried. >>> >>> However, if I curl one of the URLs manually on that server I see that both >>> A and AAAA records are queried, and that ipv6 is being used successfully >>> when making the connection. >>> >>> Is there a setting or patch I can use to convince haproxy to use ipv6? >>> >>> I use haproxy 1.5-dev22, compiled it with GETADDRINFO=1, and run it on >>> Debian 7 stable, 32-bit >>> >>> Thanks >>> >> >> Try adding the 'ipv6@' keyword in front of the hostname as shown here: >> http://cbonte.github.io/haproxy-dconv/snapshot/configuration-1.5.html#4.2-server >> >> Regards, >> -- >> Nenad Merdanovic | PGP: 0x423edcb2 | Web: http://nimzo.info >> Linkedin: http://www.linkedin.com/in/nenadmerdanovic >
// CCing Willy Why are we using gethostbyname() first if USE_GETADDRINFO is enabled? This causes problems with IPv6 lookups in a sense that IPv4 will get returned if it exists, before trying IPv6 (If options inet6 is not set in /etc/resolv.conf). When this happens, we fail on (src/standard.c): 561 else if (sa->ss_family != he->h_addrtype) 562 goto fail; Since gethostbyname() is depreciated, I think we should be using getaddrinfo() first (if USE_GETADDRINFO=1) I have attached a quick and super-dirty fix, so whoever wants to rewrite it go ahead. If it's OK, I'll submit it properly. Regards, -- Nenad Merdanovic | PGP: 0x423edcb2 | Web: http://nimzo.info Linkedin: http://www.linkedin.com/in/nenadmerdanovic
diff --git a/src/standard.c b/src/standard.c index 569ecaa..5f43a4e 100644 --- a/src/standard.c +++ b/src/standard.c @@ -520,7 +520,12 @@ const char *invalid_domainchar(const char *name) { */ static struct sockaddr_storage *str2ip(const char *str, struct sockaddr_storage *sa) { + +#ifdef USE_GETADDRINFO + struct addrinfo hints, *result; +#else struct hostent *he; +#endif /* Any IPv6 address */ if (str[0] == ':' && str[1] == ':' && !str[2]) { @@ -552,6 +557,33 @@ static struct sockaddr_storage *str2ip(const char *str, struct sockaddr_storage return sa; } +#ifdef USE_GETADDRINFO + memset(&result, 0, sizeof(result)); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = sa->ss_family ? sa->ss_family : AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = 0; + + if (getaddrinfo(str, NULL, &hints, &result) == 0) { + if (!sa->ss_family || sa->ss_family == AF_UNSPEC) + sa->ss_family = result->ai_family; + else if (sa->ss_family != result->ai_family) + goto fail; + + switch (result->ai_family) { + case AF_INET: + memcpy((struct sockaddr_in *)sa, result->ai_addr, result->ai_addrlen); + return sa; + case AF_INET6: + memcpy((struct sockaddr_in6 *)sa, result->ai_addr, result->ai_addrlen); + return sa; + } + } + + if (result) + freeaddrinfo(result); +#else /* try to resolve an IPv4/IPv6 hostname */ he = gethostbyname(str); if (he) { @@ -569,36 +601,7 @@ static struct sockaddr_storage *str2ip(const char *str, struct sockaddr_storage return sa; } } -#ifdef USE_GETADDRINFO - else { - struct addrinfo hints, *result; - - memset(&result, 0, sizeof(result)); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = sa->ss_family ? sa->ss_family : AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; - hints.ai_protocol = 0; - - if (getaddrinfo(str, NULL, &hints, &result) == 0) { - if (!sa->ss_family || sa->ss_family == AF_UNSPEC) - sa->ss_family = result->ai_family; - else if (sa->ss_family != result->ai_family) - goto fail; - - switch (result->ai_family) { - case AF_INET: - memcpy((struct sockaddr_in *)sa, result->ai_addr, result->ai_addrlen); - return sa; - case AF_INET6: - memcpy((struct sockaddr_in6 *)sa, result->ai_addr, result->ai_addrlen); - return sa; - } - } - if (result) - freeaddrinfo(result); - } #endif /* unsupported address family */ fail: