From 90447582d79a773f66dc3ef1ea2c0cbbc8da5ad3 Mon Sep 17 00:00:00 2001 From: Baptiste Assmann Date: Wed, 2 Sep 2015 22:20:56 +0200 Subject: [PATCH] MINOR: DNS client query type failover management In the first version of the DNS resolver, HAProxy sends an ANY query type and in case of issue fails over to the type pointed by the directive in 'resolve-prefer'. This patch allows the following new failover management: 1. default query type is still ANY 2. if response is truncated or in error because ANY is not supported by the server, then a fail over to a new query type is performed. The new query type is the one pointed by the directive 'resolve-prefer'. 3. if no response or still some errors occurs, then a query type fail over is performed to the remaining IP address family. --- src/server.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index ca8c4f88d..340a31050 100644 --- a/src/server.c +++ b/src/server.c @@ -2112,6 +2112,7 @@ int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code) { struct server *s; struct dns_resolvers *resolvers; + int qtype_any, res_preferred_afinet, res_preferred_afinet6; /* shortcut to the server whose name is being resolved */ s = (struct server *)resolution->requester; @@ -2134,12 +2135,27 @@ int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code) case DNS_RESP_ANCOUNT_ZERO: case DNS_RESP_TRUNCATED: case DNS_RESP_ERROR: - if (resolution->query_type == DNS_RTYPE_ANY) { + qtype_any = resolution->query_type == DNS_RTYPE_ANY; + res_preferred_afinet = resolution->resolver_family_priority == AF_INET && resolution->query_type == DNS_RTYPE_A; + res_preferred_afinet6 = resolution->resolver_family_priority == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA; + + if (qtype_any || res_preferred_afinet || res_preferred_afinet6) { /* let's change the query type */ - if (resolution->resolver_family_priority == AF_INET6) - resolution->query_type = DNS_RTYPE_AAAA; - else + if (qtype_any) { + /* fallback from ANY to resolution preference */ + if (resolution->resolver_family_priority == AF_INET6) + resolution->query_type = DNS_RTYPE_AAAA; + else + resolution->query_type = DNS_RTYPE_A; + } + else if (res_preferred_afinet6) { + /* fallback from AAAA to A */ resolution->query_type = DNS_RTYPE_A; + } + else if (res_preferred_afinet) { + /* fallback from A to AAAA */ + resolution->query_type = DNS_RTYPE_AAAA; + } dns_send_query(resolution);