From: Baptiste Assmann Date: Tue, 8 Sep 2015 22:46:58 +0000 (+0200) Subject: MINOR: dns: no expected DNS record type found X-Git-Tag: v1.6-dev5~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96972bcd36a718954d7664484f17fb564534d617;p=thirdparty%2Fhaproxy.git MINOR: dns: no expected DNS record type found Some DNS responses may be valid from a protocol point of view, but may not contain any information considered as interested by the requester.. Purpose of the flag DNS_RESP_NO_EXPECTED_RECORD introduced by this patch is to allow reporting such situation. When this happens, a new DNS query is sent with a new query type. For now, the function only expect A and AAAA query types which is enough to cover current cases. In a next future, it will be up to the caller to tell the function which query types are expected. --- diff --git a/include/types/dns.h b/include/types/dns.h index 3ec3492520..59b59c7654 100644 --- a/include/types/dns.h +++ b/include/types/dns.h @@ -199,6 +199,7 @@ enum { DNS_RESP_CNAME_ERROR, /* error when resolving a CNAME in an atomic response */ DNS_RESP_TIMEOUT, /* DNS server has not answered in time */ DNS_RESP_TRUNCATED, /* DNS response is truncated */ + DNS_RESP_NO_EXPECTED_RECORD, /* No expected records were found in the response */ }; /* return codes after searching an IP in a DNS response buffer, using a family preference */ diff --git a/src/dns.c b/src/dns.c index ec3c9d1ee3..4dfe697906 100644 --- a/src/dns.c +++ b/src/dns.c @@ -222,6 +222,11 @@ void dns_resolve_recv(struct dgram_conn *dgram) nameserver->counters.truncated += 1; resolution->requester_error_cb(resolution, DNS_RESP_TRUNCATED); continue; + + case DNS_RESP_NO_EXPECTED_RECORD: + nameserver->counters.other += 1; + resolution->requester_error_cb(resolution, DNS_RESP_NO_EXPECTED_RECORD); + continue; } nameserver->counters.valid += 1; @@ -334,12 +339,18 @@ void dns_update_resolvers_timeout(struct dns_resolvers *resolvers) int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, char *dn_name, int dn_name_len) { unsigned char *reader, *cname, *ptr; - int i, len, flags, type, ancount, cnamelen; + int i, len, flags, type, ancount, cnamelen, expected_record; reader = resp; cname = NULL; cnamelen = 0; len = 0; + expected_record = 0; /* flag to report if at least one expected record type is found in the response. + * For now, only records containing an IP address (A and AAAA) are + * considered as expected. + * Later, this function may be updated to let the caller decide what type + * of record is expected to consider the response as valid. (SRV or TXT types) + */ /* move forward 2 bytes for the query id */ reader += 2; @@ -540,6 +551,7 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, char * /* ipv4 is stored on 4 bytes */ if (len != 4) return DNS_RESP_INVALID; + expected_record = 1; break; case DNS_RTYPE_CNAME: @@ -551,6 +563,7 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, char * /* ipv6 is stored on 16 bytes */ if (len != 16) return DNS_RESP_INVALID; + expected_record = 1; break; } /* switch (record type) */ @@ -558,6 +571,9 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, char * reader += len; } /* for i 0 to ancount */ + if (expected_record == 0) + return DNS_RESP_NO_EXPECTED_RECORD; + return DNS_RESP_VALID; } diff --git a/src/server.c b/src/server.c index f8fbe6a9a1..4e06ad22af 100644 --- a/src/server.c +++ b/src/server.c @@ -2120,6 +2120,7 @@ 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: + 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;