Tweak handling of duplicate DNS answers via UDP.

If we get a duplicate answer for a query via UDP which we have
either already received and started DNSSEC validation, or was
truncated and we've passed to TCP, then just ignore it.

The code was already in place, but had evolved wonky and
only worked for error replies which would otherwise prompt
a retransmit.
This commit is contained in:
Simon Kelley
2025-01-13 20:22:42 +00:00
parent da58455508
commit 71766c0c35

View File

@@ -822,10 +822,6 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
daemon->log_display_id = forward->frec_src.log_id; daemon->log_display_id = forward->frec_src.log_id;
/* We've had a reply already, which we're validating. Ignore this duplicate */
if (forward->blocking_query || (forward->flags & FREC_GONE_TO_TCP))
return;
/* Find the original query that started it all.... */ /* Find the original query that started it all.... */
for (orig = forward; orig->dependent; orig = orig->dependent); for (orig = forward; orig->dependent; orig = orig->dependent);
@@ -1153,17 +1149,19 @@ void reply_query(int fd, time_t now)
check_for_ignored_address(header, n)) check_for_ignored_address(header, n))
return; return;
if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) && forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
{
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
/* The query MAY have got a good answer, and be awaiting /* The query MAY have got a good answer, and be awaiting
the results of further queries, in which case the results of further queries, in which case
The Stash contains something else and we don't need to retry anyway. */ the stash contains something else and we don't need to retry anyway.
We may also have already got a truncated reply, and be in the process
of doing the query by TCP so can ignore further, probably truncated, UDP answers. */
if (forward->blocking_query || (forward->flags & FREC_GONE_TO_TCP)) if (forward->blocking_query || (forward->flags & FREC_GONE_TO_TCP))
return; return;
#endif #endif
if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) && forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
{
/* Get the saved query back. */ /* Get the saved query back. */
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header); blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);