Subtly change behaviour on repeated DNS query.

This changes the behaviour introduced in
141a26f979

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.
This commit is contained in:
Simon Kelley
2021-04-05 21:01:09 +01:00
parent 89df73ac05
commit ea6b0b2665

View File

@@ -309,6 +309,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
#endif #endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL); unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL); unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
int old_src = 0;
(void)do_bit; (void)do_bit;
if (header->hb4 & HB4_CD) if (header->hb4 & HB4_CD)
@@ -323,7 +325,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
#endif #endif
/* Check for retry on existing query */ /* 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; struct frec_src *src;
@@ -332,10 +336,13 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
sockaddr_isequal(&src->source, udpaddr)) sockaddr_isequal(&src->source, udpaddr))
break; break;
if (src)
old_src = 1;
else
{
/* Existing query, but from new source, just add this /* Existing query, but from new source, just add this
client to the list that will get the reply.*/ client to the list that will get the reply.*/
if (!src)
{
/* Note whine_malloc() zeros memory. */ /* Note whine_malloc() zeros memory. */
if (!daemon->free_frec_src && if (!daemon->free_frec_src &&
daemon->frec_src_count < daemon->ftabsize && daemon->frec_src_count < daemon->ftabsize &&
@@ -400,10 +407,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
} }
#endif #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; domain = forward->sentto->domain;
forward->sentto->failed_queries++; forward->sentto->failed_queries++;
if (!option_bool(OPT_ORDER)) if (!option_bool(OPT_ORDER) && old_src)
{ {
forward->forwardall = 1; forward->forwardall = 1;
daemon->last_server = NULL; daemon->last_server = NULL;