aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/dnsmasq/patches/0003-Add-logging-for-DNS-error-returns-from-upstream-and-.patch
blob: 72f259f31e757f175f73836c0569429608a79bb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
From 07ed585c38d8f7c0a18470d2e79cf46ea92ea96a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 4 May 2018 21:52:22 +0100
Subject: [PATCH 03/17] Add logging for DNS error returns from upstream and
 local configuration.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
 src/cache.c   | 13 +++++++++++++
 src/dnsmasq.h |  7 ++++++-
 src/forward.c | 25 +++++++++++++++++++------
 src/rfc1035.c | 19 ++++++++++++++-----
 4 files changed, 52 insertions(+), 12 deletions(-)

--- a/src/cache.c
+++ b/src/cache.c
@@ -1598,6 +1598,19 @@ void log_query(unsigned int flags, char
     {
       if (flags & F_KEYTAG)
 	sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
+      else if (flags & F_RCODE)
+	{
+	  unsigned int rcode = addr->addr.rcode.rcode;
+
+	   if (rcode == SERVFAIL)
+	     dest = "SERVFAIL";
+	   else if (rcode == REFUSED)
+	     dest = "REFUSED";
+	   else if (rcode == NOTIMP)
+	     dest = "not implemented";
+	   else
+	     sprintf(daemon->addrbuff, "%u", rcode);
+	}
       else
 	{
 #ifdef HAVE_IPV6
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -268,7 +268,11 @@ struct all_addr {
     /* for log_query */
     struct {
       unsigned short keytag, algo, digest;
-    } log; 
+    } log;
+    /* for log_query */
+    struct {
+      unsigned int rcode;
+    } rcode;
     /* for cache_insert of DNSKEY, DS */
     struct {
       unsigned short class, type;
@@ -459,6 +463,7 @@ struct crec {
 #define F_IPSET     (1u<<26)
 #define F_NOEXTRA   (1u<<27)
 #define F_SERVFAIL  (1u<<28)
+#define F_RCODE     (1u<<29)
 
 /* Values of uid in crecs with F_CONFIG bit set. */
 #define SRC_INTERFACE 0
--- a/src/forward.c
+++ b/src/forward.c
@@ -563,6 +563,7 @@ static size_t process_reply(struct dns_h
   unsigned char *pheader, *sizep;
   char **sets = 0;
   int munged = 0, is_sign;
+  unsigned int rcode = RCODE(header);
   size_t plen; 
   
   (void)ad_reqd;
@@ -593,6 +594,9 @@ static size_t process_reply(struct dns_h
   
   if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
     {
+      /* Get extended RCODE. */
+      rcode |= sizep[2] << 4;
+
       if (check_subnet && !check_source(header, plen, pheader, query_source))
 	{
 	  my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
@@ -641,11 +645,20 @@ static size_t process_reply(struct dns_h
   if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
      header->hb4 &= ~HB4_AD;
   
-  if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
+  if (OPCODE(header) != QUERY)
     return resize_packet(header, n, pheader, plen);
+
+  if (rcode != NOERROR && rcode != NXDOMAIN)
+    {
+      struct all_addr a;
+      a.addr.rcode.rcode = rcode;
+      log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
+      
+      return resize_packet(header, n, pheader, plen);
+    }
   
   /* Complain loudly if the upstream server is non-recursive. */
-  if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
+  if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
       server && !(server->flags & SERV_WARNED_RECURSIVE))
     {
       prettyprint_addr(&server->addr, daemon->namebuff);
@@ -654,7 +667,7 @@ static size_t process_reply(struct dns_h
 	server->flags |= SERV_WARNED_RECURSIVE;
     }  
 
-  if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
+  if (daemon->bogus_addr && rcode != NXDOMAIN &&
       check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
     {
       munged = 1;
@@ -666,7 +679,7 @@ static size_t process_reply(struct dns_h
     {
       int doctored = 0;
       
-      if (RCODE(header) == NXDOMAIN && 
+      if (rcode == NXDOMAIN && 
 	  extract_request(header, n, daemon->namebuff, NULL) &&
 	  check_for_local_domain(daemon->namebuff, now))
 	{
@@ -1090,7 +1103,7 @@ void reply_query(int fd, int family, tim
 	      if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
 		domain = daemon->namebuff;
 	      
-	      log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
+	      log_query(F_SECSTAT, domain, NULL, result);
 	    }
 	  
 	  if (status == STAT_SECURE)
@@ -1948,7 +1961,7 @@ unsigned char *tcp_request(int confd, ti
 			  if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
 			    domain = daemon->namebuff;
 
-			  log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
+			  log_query(F_SECSTAT, domain, NULL, result);
 			  
 			  if (status == STAT_BOGUS)
 			    {
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -926,12 +926,11 @@ unsigned int extract_request(struct dns_
   return F_QUERY;
 }
 
-
 size_t setup_reply(struct dns_header *header, size_t qlen,
 		struct all_addr *addrp, unsigned int flags, unsigned long ttl)
 {
   unsigned char *p;
-
+  
   if (!(p = skip_questions(header, qlen)))
     return 0;
   
@@ -948,7 +947,12 @@ size_t setup_reply(struct dns_header *he
   else if (flags == F_NXDOMAIN)
     SET_RCODE(header, NXDOMAIN);
   else if (flags == F_SERVFAIL)
-    SET_RCODE(header, SERVFAIL);
+    {
+      struct all_addr a;
+      a.addr.rcode.rcode = SERVFAIL;
+      log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
+      SET_RCODE(header, SERVFAIL);
+    }
   else if (flags == F_IPV4)
     { /* we know the address */
       SET_RCODE(header, NOERROR);
@@ -966,8 +970,13 @@ size_t setup_reply(struct dns_header *he
     }
 #endif
   else /* nowhere to forward to */
-    SET_RCODE(header, REFUSED);
- 
+    {
+      struct all_addr a;
+      a.addr.rcode.rcode = REFUSED;
+      log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
+      SET_RCODE(header, REFUSED);
+    }
+  
   return p - (unsigned char *)header;
 }