Blame SOURCES/dnsmasq-2.79-fix-infitite-strict-mode-retries.patch

a7b456
From eb79fee19724dcfde162892cfb4b9175a470308a Mon Sep 17 00:00:00 2001
a7b456
From: Simon Kelley <simon@thekelleys.org.uk>
a7b456
Date: Tue, 5 Dec 2017 22:37:29 +0000
a7b456
Subject: [PATCH] Fix infinite retries in strict-order mode.
a7b456
a7b456
 If all configured dns servers return refused in
a7b456
 response to a query; dnsmasq will end up in an infinite loop
a7b456
 retransmitting the dns query resulting into high CPU load.
a7b456
 Problem is caused by the dns refuse retransmission logic which does
a7b456
 not check for the end of a dns server list iteration in strict mode.
a7b456
 Having one configured dns server returning a refused reply easily
a7b456
 triggers this problem in strict order mode. This was introduced in
a7b456
 9396752c115b3ab733fa476b30da73237e12e7ba
a7b456
a7b456
 Thanks to Hans Dedecker <dedeckeh@gmail.com> for spotting this
a7b456
 and the initial patch.
a7b456
a7b456
(cherry picked from commit ef3d137a646fa8309e1ff5184e3e145eef40cc4d)
a7b456
---
a7b456
 src/forward.c | 14 ++++++++++++--
a7b456
 1 file changed, 12 insertions(+), 2 deletions(-)
a7b456
a7b456
diff --git a/src/forward.c b/src/forward.c
a7b456
index 255d6c0..e61cd50 100644
a7b456
--- a/src/forward.c
a7b456
+++ b/src/forward.c
a7b456
@@ -804,10 +804,20 @@ void reply_query(int fd, int family, time_t now)
a7b456
       unsigned char *pheader;
a7b456
       size_t plen;
a7b456
       int is_sign;
a7b456
-      
a7b456
+
a7b456
+      /* In strict order mode, there must be a server later in the chain
a7b456
+	 left to send to, otherwise without the forwardall mechanism,
a7b456
+	 code further on will cycle around the list forwever if they
a7b456
+	 all return REFUSED. Note that server is always non-NULL before 
a7b456
+	 this executes. */
a7b456
+      if (option_bool(OPT_ORDER))
a7b456
+	for (server = forward->sentto->next; server; server = server->next)
a7b456
+	  if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
a7b456
+	    break;
a7b456
+
a7b456
       /* recreate query from reply */
a7b456
       pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
a7b456
-      if (!is_sign)
a7b456
+      if (!is_sign && server)
a7b456
 	{
a7b456
 	  header->ancount = htons(0);
a7b456
 	  header->nscount = htons(0);
a7b456
-- 
a7b456
2.26.2
a7b456