Handle truncated response UDP-to-TCP to downstream queries when validating.

A relatively common situation is that the reply to a downstream query
will fit in a UDP packet when no DNSSEC RRs are present, but overflows
when the RRSIGS, NSEC ect are added. This extends the automatic
move from UDP to TCP to downstream queries which get truncated replies,
in the hope that once stripped of the DNSSEC RRs, the reply can be returned
via UDP, nwithout making the downstream retry with TCP.

If the downstream sets the DO bit, (ie it wants the DNSSEC RRs, then
this path is not taken, since the downstream will have to get a truncated
repsonse and retry to get a correct answer.
This commit is contained in:
Simon Kelley
2024-10-12 22:25:06 +01:00
parent 1c26ec2876
commit d15d371051
6 changed files with 193 additions and 88 deletions

View File

@@ -2074,7 +2074,7 @@ static void check_dns_listeners(time_t now)
cache_recv_insert() calls pop_and_retry_query() after the result
arrives via the pipe to the parent. */
int swap_to_tcp(struct frec *forward, time_t now, int status, struct dns_header *header,
size_t plen, int class, struct server *server, int *keycount, int *validatecount)
ssize_t *plen, int class, struct server *server, int *keycount, int *validatecount)
{
struct server *s;
@@ -2148,8 +2148,8 @@ int swap_to_tcp(struct frec *forward, time_t now, int status, struct dns_header
}
}
status = tcp_key_recurse(now, status, header, plen, class, daemon->namebuff, daemon->keyname,
server, 0, 0, keycount, validatecount);
status = tcp_from_udp(now, status, header, plen, class, daemon->namebuff, daemon->keyname,
server, keycount, validatecount);
/* close upstream connections. */
for (s = daemon->servers; s; s = s->next)
@@ -2167,6 +2167,8 @@ int swap_to_tcp(struct frec *forward, time_t now, int status, struct dns_header
/* tell our parent we're done, and what the result was then exit. */
read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&status, sizeof(status), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)plen, sizeof(*plen), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)header, *plen, 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&forward, sizeof(forward), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&forward->uid, sizeof(forward->uid), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)keycount, sizeof(*keycount), 0);