Hi Maksim,
On Fri, Dec 23, 2016 at 12:59:05PM +0300, ???????????? ?????????????????? wrote:
> Hi!
>
> Since I've installed 1.7.1 version of haproxy over 1.6.10 ??? it stopped
> working with ipv6-only backends (no A-record in DNS at all, only AAAA),
> even with USE_GETADDRINFO=1 set. Haproxy says, that it 'could not resolve
> address' and exits on a parsing phase.
>
> The problem is in fuction str2sa_range, and a quick and ugly hack, which
> made me happy (all my backends are dual-stack, or ipv6-only):
> --- haproxy-1.7.1.orig/src/standard.c
> +++ haproxy-1.7.1/src/standard.c
> @@ -963,7 +963,7 @@ struct sockaddr_storage *str2sa_range(co
> * force it to IPv4 for now.
> */
> memset(&ss, 0, sizeof(ss));
> - ss.ss_family = AF_INET;
> + ss.ss_family = AF_INET6;
> }
> else if ((!resolve && !fqdn) ||
> (resolve && str2ip2(str2, &ss, 1) == NULL)) {
>
> Please, fix it.
I could reproduce it with the following config, which I guess matches your
use case :
backend b1
timeout connect 5s
timeout server 10s
server s1 www6.1wt.eu:80
Indeed it fails to resolve. Now I see why. The problem is that in order not
to lose the port which was already parsed, we temporarily set the family to
AF_INET and store the port in the sockaddr. The problem is that by doing so
we lose the initial value of this family and we believe it was forced as if
you had had "[email protected]", so the error is valid in str2ip2. If we think
about it for a moment, we need to store the port only for :
AF_INET (no change needed)
AF_INET6 (no change needed)
AF_UNSPEC
It's the last case which causes trouble in fact. We only need to be able to
store the information that the family is unknown and that we already have a
port. We could even hijack an existing family for this but that's not clean.
We cannot leave AF_UNSPEC here as it's used when we pass an fd. I'll have to
think about it a bit :-/
In the mean time you can apply the following patch which will let you force
"ipv4@" or "ipv6@" to work around the issue. It's probably part of the final
fix in that we don't want to lose the family.
diff --git a/src/standard.c b/src/standard.c
index 079aef8..db26e0d 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -962,8 +962,11 @@ struct sockaddr_storage *str2sa_range(const char *str, int
*low, int *high, char
/* we'll still want to store the port, so let's
* force it to IPv4 for now.
*/
+ sa_family_t family = ss.ss_family;
memset(&ss, 0, sizeof(ss));
- ss.ss_family = AF_INET;
+ ss.ss_family = family;
+ if (ss.ss_family != AF_INET && ss.ss_family !=
AF_INET6)
+ ss.ss_family = AF_INET;
}
else if ((!resolve && !fqdn) ||
(resolve && str2ip2(str2, &ss, 1) == NULL)) {
Thanks,
Willy