]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: dns: handling of truncated response
authorBaptiste Assmann <bedis9@gmail.com>
Wed, 2 Sep 2015 20:08:38 +0000 (22:08 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 Sep 2015 12:59:49 +0000 (14:59 +0200)
First dns client implementation simply ignored most of DNS response
flags.
This patch changes the way the flags are parsed, using bit masks and
also take care of truncated responses.
Such response are reported to the above layer which can handle it
properly.

src/dns.c

index d1952175efa5fb78d33d6eae8c608c68467010bd..ec3c9d1ee3ad96987a577184595f8acb74051d19 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -334,7 +334,7 @@ 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, type, ancount, cnamelen;
+       int i, len, flags, type, ancount, cnamelen;
 
        reader = resp;
        cname = NULL;
@@ -347,29 +347,33 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, char *
                return DNS_RESP_INVALID;
 
        /*
-        * analyzing flags
-        * 1st byte can be ignored for now
-        * rcode is at the beginning of the second byte
+        * flags are stored over 2 bytes
+        * First byte contains:
+        *  - response flag (1 bit)
+        *  - opcode (4 bits)
+        *  - authoritative (1 bit)
+        *  - truncated (1 bit)
+        *  - recursion desired (1 bit)
         */
-       reader += 1;
-       if (reader >= bufend)
+       if (reader + 2 >= bufend)
                return DNS_RESP_INVALID;
 
-       /*
-        * rcode is 4 latest bits
-        * ignore response if it contains an error
-        */
-       if ((*reader & 0x0f) != DNS_RCODE_NO_ERROR) {
-               if ((*reader & 0x0f) == DNS_RCODE_NX_DOMAIN)
+       flags = reader[0] * 256 + reader[1];
+
+       if (flags & DNS_FLAG_TRUNCATED)
+               return DNS_RESP_TRUNCATED;
+
+       if ((flags & DNS_FLAG_REPLYCODE) != DNS_RCODE_NO_ERROR) {
+               if ((flags & DNS_FLAG_REPLYCODE) == DNS_RCODE_NX_DOMAIN)
                        return DNS_RESP_NX_DOMAIN;
-               else if ((*reader & 0x0f) == DNS_RCODE_REFUSED)
+               else if ((flags & DNS_FLAG_REPLYCODE) == DNS_RCODE_REFUSED)
                        return DNS_RESP_REFUSED;
 
                return DNS_RESP_ERROR;
        }
 
-       /* move forward 1 byte for rcode */
-       reader += 1;
+       /* move forward 2 bytes for flags */
+       reader += 2;
        if (reader >= bufend)
                return DNS_RESP_INVALID;