]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: dns: update dns response buffer reading pointer due to SRV record
authorBaptiste Assmann <bedis9@gmail.com>
Fri, 11 Aug 2017 08:37:20 +0000 (10:37 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 18 Aug 2017 09:24:57 +0000 (11:24 +0200)
DNS SRV records uses "dns name compression" to store the target name.
"dns compression" principle is simple. Let's take the name below:
  3336633266663038.red.default.svc.cluster.local.
It can be stored "as is" in the response or it can be compressed like
this:
  3336633266663038<POINTER>
and <POINTER> would point to the string
'.red.default.svc.cluster.local.' availble in the question section for
example.
This mechanism allows storing much more data in a single DNS response.

This means the flag "record->data_len" which stores the size of the
record (hence the whole string, uncompressed) can't be used to move the
pointer forward when reading responses. We must use the "offset" integer
which means the real number of bytes occupied by the target name.

If we don't do that, we can properly read the first SRV record, then we
loose alignment and we start reading unrelated data (still in the
response) leading to a false negative error treated as an "invalid"
response...

src/dns.c

index 765c787d6a001f57332f650703481132e5727572..9eff60ed873ce7268f2582ab72bb9316c7c44c23 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -1302,7 +1302,6 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct
                                        free_dns_answer_item(dns_answer_record);
                                        return DNS_RESP_INVALID;
                                }
-                               reader++;
                                dns_answer_record->data_len = len;
                                memcpy(dns_answer_record->target, tmpname, len);
                                dns_answer_record->target[len] = 0;
@@ -1324,7 +1323,10 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct
                nb_saved_records += 1;
 
                /* move forward dns_answer_record->data_len for analyzing next record in the response */
-               reader += dns_answer_record->data_len;
+               if (dns_answer_record->type == DNS_RTYPE_SRV)
+                       reader += offset;
+               else
+                       reader += dns_answer_record->data_len;
 
                /* Lookup to see if we already had this entry */