Don't send suspect answer as query to next server in DNS TCP codepath.

This commit is contained in:
Simon Kelley
2024-11-02 22:13:52 +00:00
parent 1b76e1c8ec
commit 09a1839272

View File

@@ -1025,7 +1025,6 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
new->dependent = forward; new->dependent = forward;
/* Make consistent, only replace query copy with unvalidated answer /* Make consistent, only replace query copy with unvalidated answer
when we set ->blocking_query. */ when we set ->blocking_query. */
if (forward->stash)
blockdata_free(forward->stash); blockdata_free(forward->stash);
forward->blocking_query = new; forward->blocking_query = new;
forward->stash_len = plen; forward->stash_len = plen;
@@ -1075,7 +1074,6 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
/* Make consistent, only replace query copy with unvalidated answer /* Make consistent, only replace query copy with unvalidated answer
when we set ->blocking_query. */ when we set ->blocking_query. */
forward->blocking_query = new; forward->blocking_query = new;
if (forward->stash)
blockdata_free(forward->stash); blockdata_free(forward->stash);
forward->stash_len = plen; forward->stash_len = plen;
forward->stash = stash; forward->stash = stash;
@@ -1957,6 +1955,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
unsigned int rsize; unsigned int rsize;
int class, rclass, type, rtype; int class, rclass, type, rtype;
unsigned char *p; unsigned char *p;
struct blockdata *saved_question;
(void)mark; (void)mark;
(void)have_mark; (void)have_mark;
@@ -1968,6 +1967,10 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
GETSHORT(type, p); GETSHORT(type, p);
GETSHORT(class, p); GETSHORT(class, p);
/* Save question for retry. */
if (!(saved_question = blockdata_alloc((char *)header, (size_t)qsize)))
return 0;
while (1) while (1)
{ {
int data_sent = 0, timedout = 0; int data_sent = 0, timedout = 0;
@@ -1989,6 +1992,8 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
serv = daemon->serverarray[start]; serv = daemon->serverarray[start];
retry: retry:
blockdata_retrieve(saved_question, qsize, header);
*length = htons(qsize); *length = htons(qsize);
if (serv->tcpfd == -1) if (serv->tcpfd == -1)
@@ -2071,9 +2076,11 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
serv->flags |= SERV_GOT_TCP; serv->flags |= SERV_GOT_TCP;
*servp = serv; *servp = serv;
blockdata_free(saved_question);
return rsize; return rsize;
} }
blockdata_free(saved_question);
return 0; return 0;
} }
@@ -2131,7 +2138,7 @@ int tcp_from_udp(time_t now, int status, struct dns_header *header, ssize_t *ple
if (n >= daemon->edns_pktsz) if (n >= daemon->edns_pktsz)
{ {
/* still too bug, strip optional sections and try again. */ /* still too bIg, strip optional sections and try again. */
new_header->nscount = htons(0); new_header->nscount = htons(0);
new_header->arcount = htons(0); new_header->arcount = htons(0);
n = resize_packet(new_header, n, NULL, 0); n = resize_packet(new_header, n, NULL, 0);
@@ -2670,7 +2677,6 @@ unsigned char *tcp_request(int confd, time_t now,
close(confd); close(confd);
} }
if (saved_question)
blockdata_free(saved_question); blockdata_free(saved_question);
return packet; return packet;