From d3a8b39c7df2f0debf3b5f274a1c37a9e261f94e Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Wed, 23 Dec 2015 12:27:37 +0000 Subject: [PATCH] More EDNS0 packet-size tweaks. --- src/dnsmasq.c | 7 +++++-- src/dnsmasq.h | 8 +------- src/forward.c | 22 +++++++++++++++------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 81254f6..45761cc 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -91,8 +91,11 @@ int main (int argc, char **argv) if (daemon->edns_pktsz < PACKETSZ) daemon->edns_pktsz = PACKETSZ; - daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? - daemon->edns_pktsz : DNSMASQ_PACKETSZ; + /* Min buffer size: we check after adding each record, so there must be + memory for the largest packet, and the largest record so the + min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000. + This might be increased is EDNS packet size if greater than the minimum. */ + daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ; daemon->packet = safe_malloc(daemon->packet_buff_sz); daemon->addrbuff = safe_malloc(ADDRSTRLEN); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 4503a2d..1c94f2a 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -179,13 +179,6 @@ struct event_desc { #define EC_MISC 5 #define EC_INIT_OFFSET 10 -/* Min buffer size: we check after adding each record, so there must be - memory for the largest packet, and the largest record so the - min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000. - This might be increased is EDNS packet size if greater than the minimum. -*/ -#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ - /* Trust the compiler dead-code eliminator.... */ #define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32))) @@ -594,6 +587,7 @@ struct hostsfile { #define FREC_DO_QUESTION 64 #define FREC_ADDED_PHEADER 128 #define FREC_TEST_PKTSZ 256 +#define FREC_HAS_EXTRADATA 512 #ifdef HAVE_DNSSEC #define HASH_SIZE 20 /* SHA-1 digest size */ diff --git a/src/forward.c b/src/forward.c index e1766b9..c0e4d9a 100644 --- a/src/forward.c +++ b/src/forward.c @@ -389,13 +389,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, { struct server *firstsentto = start; int forwarded = 0; - + size_t edns0_len; + /* If a query is retried, use the log_id for the retry when logging the answer. */ forward->log_id = daemon->log_id; if (option_bool(OPT_ADD_MAC)) { - size_t new = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); + size_t new = add_mac(header, plen, ((char *) header) + PACKETSZ, &forward->source); if (new != plen) { plen = new; @@ -405,7 +406,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, if (option_bool(OPT_CLIENT_SUBNET)) { - size_t new = add_source_addr(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); + size_t new = add_source_addr(header, plen, ((char *) header) + PACKETSZ, &forward->source); if (new != plen) { plen = new; @@ -416,7 +417,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, #ifdef HAVE_DNSSEC if (option_bool(OPT_DNSSEC_VALID)) { - size_t new = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz); + size_t new = add_do_bit(header, plen, ((char *) header) + PACKETSZ); if (new != plen) forward->flags |= FREC_ADDED_PHEADER; @@ -430,6 +431,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, } #endif + + /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */ + if (find_pseudoheader(header, plen, &edns0_len, NULL, NULL, NULL) && edns0_len > 11) + forward->flags |= FREC_HAS_EXTRADATA; while (1) { @@ -769,9 +774,12 @@ void reply_query(int fd, int family, time_t now) check_for_ignored_address(header, n, daemon->ignore_addr)) return; + /* Note: if we send extra options in the EDNS0 header, we can't recreate + the query from the reply. */ if (RCODE(header) == REFUSED && !option_bool(OPT_ORDER) && - forward->forwardall == 0) + forward->forwardall == 0 && + !(forward->flags & FREC_HAS_EXTRADATA)) /* for broken servers, attempt to send to another one. */ { unsigned char *pheader; @@ -919,13 +927,13 @@ void reply_query(int fd, int family, time_t now) if (status == STAT_NEED_KEY) { new->flags |= FREC_DNSKEY_QUERY; - nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz, + nn = dnssec_generate_query(header, ((char *) header) + server->edns_pktsz, daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz); } else { new->flags |= FREC_DS_QUERY; - nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz, + nn = dnssec_generate_query(header,((char *) header) + server->edns_pktsz, daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz); } if ((hash = hash_questions(header, nn, daemon->namebuff)))