Commit ef3d137a authored by Simon Kelley's avatar Simon Kelley

Fix infinite retries in strict-order mode.

 If all configured dns servers return refused in
 response to a query; dnsmasq will end up in an infinite loop
 retransmitting the dns query resulting into high CPU load.
 Problem is caused by the dns refuse retransmission logic which does
 not check for the end of a dns server list iteration in strict mode.
 Having one configured dns server returning a refused reply easily
 triggers this problem in strict order mode. This was introduced in
 9396752c

 Thanks to Hans Dedecker <dedeckeh@gmail.com> for spotting this
 and the initial patch.
parent 8c707e1e
...@@ -794,10 +794,20 @@ void reply_query(int fd, int family, time_t now) ...@@ -794,10 +794,20 @@ void reply_query(int fd, int family, time_t now)
unsigned char *pheader; unsigned char *pheader;
size_t plen; size_t plen;
int is_sign; int is_sign;
/* In strict order mode, there must be a server later in the chain
left to send to, otherwise without the forwardall mechanism,
code further on will cycle around the list forwever if they
all return REFUSED. Note that server is always non-NULL before
this executes. */
if (option_bool(OPT_ORDER))
for (server = forward->sentto->next; server; server = server->next)
if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
break;
/* recreate query from reply */ /* recreate query from reply */
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL); pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
if (!is_sign) if (!is_sign && server)
{ {
header->ancount = htons(0); header->ancount = htons(0);
header->nscount = htons(0); header->nscount = htons(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment