]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: DNS client query type failover management
authorBaptiste Assmann <bedis9@gmail.com>
Wed, 2 Sep 2015 20:20:56 +0000 (22:20 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 Sep 2015 13:04:17 +0000 (15:04 +0200)
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

index ca8c4f88daca24ab66e2fae76d11cc3344f3a2b6..340a310501cb8af384b197b25e49e423b9ed819e 100644 (file)
@@ -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);