From ea6b0b2665ed95baa41fe813547103f7f1ccb953 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 5 Apr 2021 21:01:09 +0100 Subject: [PATCH] Subtly change behaviour on repeated DNS query. This changes the behaviour introduced in 141a26f979b4bc959d8e866a295e24f8cf456920 We re-introduce the distinction between a query which is retried from the same source, and one which is repeated from different sources. In the later case, we still forward the query, to avoid problems when the reply to the first query is lost (see f8cf456920) but we suppress the behaviour that's used on a retry, when the query is sent to all available servers in parallel. Retry -> all servers. Repeat -> next server. This avoids a significant increase in upstream traffic on busy instances which see lots of queries for common names. It does mean the clients which repeat queries from new source ports, rather than retrying them from the same source port, will see different behaviour, but it in fact restores the pre-2.83 behaviour, so it's not expected to be a practical problem. --- src/forward.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/forward.c b/src/forward.c index 2c0ef7f..ab9df26 100644 --- a/src/forward.c +++ b/src/forward.c @@ -309,6 +309,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, #endif unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL); unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL); + int old_src = 0; + (void)do_bit; if (header->hb4 & HB4_CD) @@ -323,19 +325,24 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, #endif /* Check for retry on existing query */ - if (!forward && (forward = lookup_frec_by_query(hash, fwd_flags))) + if (forward) + old_src = 1; + else if ((forward = lookup_frec_by_query(hash, fwd_flags))) { struct frec_src *src; - + for (src = &forward->frec_src; src; src = src->next) if (src->orig_id == ntohs(header->id) && sockaddr_isequal(&src->source, udpaddr)) break; - - /* Existing query, but from new source, just add this - client to the list that will get the reply.*/ - if (!src) + + if (src) + old_src = 1; + else { + /* Existing query, but from new source, just add this + client to the list that will get the reply.*/ + /* Note whine_malloc() zeros memory. */ if (!daemon->free_frec_src && daemon->frec_src_count < daemon->ftabsize && @@ -400,10 +407,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, } #endif - /* retry on existing query, send to all available servers */ + /* retry on existing query, from original source. Send to all available servers */ domain = forward->sentto->domain; forward->sentto->failed_queries++; - if (!option_bool(OPT_ORDER)) + if (!option_bool(OPT_ORDER) && old_src) { forward->forwardall = 1; daemon->last_server = NULL;