Hi Andrew,

There is a bug repeated twice in your code.
In both dns_reset_resolution() and trigger_resolution(), you use
"resolution->resolver_family_priority" before it is positioned. This
may lead to using the last resolution->resolver_family_priority, which
may be different than the server one.
Please move the line "resolution->resolver_family_priority =
s->resolver_family_priority;" before using the value stored in it.

Appart this, it looks good.

Baptiste


On Tue, Oct 20, 2015 at 12:39 AM, Andrew Hayworth
<andrew.haywo...@getbraintree.com> wrote:
> The ANY query type is weird, and some resolvers don't 'do the legwork'
> of resolving useful things like CNAMEs. Given that upstream resolver
> behavior is not always under the control of the HAProxy administrator,
> we should not use the ANY query type. Rather, we should use A or AAAA
> according to either the explicit preferences of the operator, or the
> implicit default (AAAA/IPv6).
>
> - Andrew Hayworth
>
> From 8ed172424cbd79197aacacd1fd89ddcfa46e213d Mon Sep 17 00:00:00 2001
> From: Andrew Hayworth <andrew.haywo...@getbraintree.com>
> Date: Mon, 19 Oct 2015 22:29:51 +0000
> Subject: [PATCH] MEDIUM: dns: Don't use the ANY query type
>
> Basically, it's ill-defined and shouldn't really be used going forward.
> We can't guarantee that resolvers will do the 'legwork' for us and
> actually resolve CNAMES when we request the ANY query-type. Case in point
> (obfuscated, clearly):
>
>   PRODUCTION! ahaywo...@secret-hostname.com:~$
>   dig @10.11.12.53 ANY api.somestartup.io
>
>   ; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @10.11.12.53 ANY api.somestartup.io
>   ; (1 server found)
>   ;; global options: +cmd
>   ;; Got answer:
>   ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62454
>   ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 0
>
>   ;; QUESTION SECTION:
>   ;api.somestartup.io.                        IN      ANY
>
>   ;; ANSWER SECTION:
>   api.somestartup.io.         20      IN      CNAME
> api-somestartup-production.ap-southeast-2.elb.amazonaws.com.
>
>   ;; AUTHORITY SECTION:
>   somestartup.io.               166687  IN      NS      ns-1254.awsdns-28.org.
>   somestartup.io.               166687  IN      NS      
> ns-1884.awsdns-43.co.uk.
>   somestartup.io.               166687  IN      NS      ns-440.awsdns-55.com.
>   somestartup.io.               166687  IN      NS      ns-577.awsdns-08.net.
>
>   ;; Query time: 1 msec
>   ;; SERVER: 10.11.12.53#53(10.11.12.53)
>   ;; WHEN: Mon Oct 19 22:02:29 2015
>   ;; MSG SIZE  rcvd: 242
>
> HAProxy can't handle that response correctly.
>
> Rather than try to build in support for resolving CNAMEs presented
> without an A record in an answer section (which may be a valid
> improvement further on), this change just skips ANY record types
> altogether. A and AAAA are much more well-defined and predictable.
>
> Notably, this commit preserves the implicit "Prefer IPV6 behavior."
> ---
>  include/types/dns.h |  3 ++-
>  src/checks.c        |  6 +++++-
>  src/dns.c           |  6 +++++-
>  src/server.c        | 18 +++++++-----------
>  4 files changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/include/types/dns.h b/include/types/dns.h
> index f8edb73..ea1a9f9 100644
> --- a/include/types/dns.h
> +++ b/include/types/dns.h
> @@ -161,7 +161,8 @@ struct dns_resolution {
>   unsigned int last_status_change; /* time of the latest DNS
> resolution status change */
>   int query_id; /* DNS query ID dedicated for this resolution */
>   struct eb32_node qid; /* ebtree query id */
> - int query_type; /* query type to send. By default DNS_RTYPE_ANY */
> + int query_type;
> + /* query type to send. By default DNS_RTYPE_A or DNS_RTYPE_AAAA
> depending on resolver_family_priority */
>   int status; /* status of the resolution being processed RSLV_STATUS_* */
>   int step; /* */
>   int try; /* current resolution try */
> diff --git a/src/checks.c b/src/checks.c
> index ade2428..d3cd567 100644
> --- a/src/checks.c
> +++ b/src/checks.c
> @@ -2214,7 +2214,11 @@ int trigger_resolution(struct server *s)
>   resolution->query_id = query_id;
>   resolution->qid.key = query_id;
>   resolution->step = RSLV_STEP_RUNNING;
> - resolution->query_type = DNS_RTYPE_ANY;
> + if (resolution->resolver_family_priority == AF_INET) {
> + resolution->query_type = DNS_RTYPE_A;
> + } else {
> + resolution->query_type = DNS_RTYPE_AAAA;
> + }
>   resolution->try = resolvers->resolve_retries;
>   resolution->try_cname = 0;
>   resolution->nb_responses = 0;
> diff --git a/src/dns.c b/src/dns.c
> index 7f71ac7..53b65ab 100644
> --- a/src/dns.c
> +++ b/src/dns.c
> @@ -102,7 +102,11 @@ void dns_reset_resolution(struct dns_resolution
> *resolution)
>   resolution->qid.key = 0;
>
>   /* default values */
> - resolution->query_type = DNS_RTYPE_ANY;
> + if (resolution->resolver_family_priority == AF_INET) {
> + resolution->query_type = DNS_RTYPE_A;
> + } else {
> + resolution->query_type = DNS_RTYPE_AAAA;
> + }
>
>   /* the second resolution in the queue becomes the first one */
>   LIST_DEL(&resolution->list);
> diff --git a/src/server.c b/src/server.c
> index 8ddff00..33d6922 100644
> --- a/src/server.c
> +++ b/src/server.c
> @@ -2692,21 +2692,13 @@ int snr_resolution_error_cb(struct
> dns_resolution *resolution, int error_code)
>   case DNS_RESP_TRUNCATED:
>   case DNS_RESP_ERROR:
>   case DNS_RESP_NO_EXPECTED_RECORD:
> - 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)
> + if ((res_preferred_afinet || res_preferred_afinet6)
>         || (resolution->try > 0)) {
>   /* let's change the query type */
> - 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) {
> + if (res_preferred_afinet6) {
>   /* fallback from AAAA to A */
>   resolution->query_type = DNS_RTYPE_A;
>   }
> @@ -2716,7 +2708,11 @@ int snr_resolution_error_cb(struct
> dns_resolution *resolution, int error_code)
>   }
>   else {
>   resolution->try -= 1;
> - resolution->query_type = DNS_RTYPE_ANY;
> + if (resolution->resolver_family_priority == AF_INET) {
> + resolution->query_type = DNS_RTYPE_A;
> + } else {
> + resolution->query_type = DNS_RTYPE_AAAA;
> + }
>   }
>
>   dns_send_query(resolution);
> --
> 2.1.3

Reply via email to