150cd91c6a7479263d39ebb1b568bd7b83c117ef
[librecmc/librecmc.git] /
1 From 07ed585c38d8f7c0a18470d2e79cf46ea92ea96a Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Fri, 4 May 2018 21:52:22 +0100
4 Subject: [PATCH 03/10] Add logging for DNS error returns from upstream and
5  local configuration.
6
7 Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
8 ---
9  src/cache.c   | 13 +++++++++++++
10  src/dnsmasq.h |  7 ++++++-
11  src/forward.c | 25 +++++++++++++++++++------
12  src/rfc1035.c | 19 ++++++++++++++-----
13  4 files changed, 52 insertions(+), 12 deletions(-)
14
15 --- a/src/cache.c
16 +++ b/src/cache.c
17 @@ -1598,6 +1598,19 @@ void log_query(unsigned int flags, char
18      {
19        if (flags & F_KEYTAG)
20         sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
21 +      else if (flags & F_RCODE)
22 +       {
23 +         unsigned int rcode = addr->addr.rcode.rcode;
24 +
25 +          if (rcode == SERVFAIL)
26 +            dest = "SERVFAIL";
27 +          else if (rcode == REFUSED)
28 +            dest = "REFUSED";
29 +          else if (rcode == NOTIMP)
30 +            dest = "not implemented";
31 +          else
32 +            sprintf(daemon->addrbuff, "%u", rcode);
33 +       }
34        else
35         {
36  #ifdef HAVE_IPV6
37 --- a/src/dnsmasq.h
38 +++ b/src/dnsmasq.h
39 @@ -268,7 +268,11 @@ struct all_addr {
40      /* for log_query */
41      struct {
42        unsigned short keytag, algo, digest;
43 -    } log; 
44 +    } log;
45 +    /* for log_query */
46 +    struct {
47 +      unsigned int rcode;
48 +    } rcode;
49      /* for cache_insert of DNSKEY, DS */
50      struct {
51        unsigned short class, type;
52 @@ -459,6 +463,7 @@ struct crec {
53  #define F_IPSET     (1u<<26)
54  #define F_NOEXTRA   (1u<<27)
55  #define F_SERVFAIL  (1u<<28)
56 +#define F_RCODE     (1u<<29)
57  
58  /* Values of uid in crecs with F_CONFIG bit set. */
59  #define SRC_INTERFACE 0
60 --- a/src/forward.c
61 +++ b/src/forward.c
62 @@ -563,6 +563,7 @@ static size_t process_reply(struct dns_h
63    unsigned char *pheader, *sizep;
64    char **sets = 0;
65    int munged = 0, is_sign;
66 +  unsigned int rcode = RCODE(header);
67    size_t plen; 
68    
69    (void)ad_reqd;
70 @@ -593,6 +594,9 @@ static size_t process_reply(struct dns_h
71    
72    if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
73      {
74 +      /* Get extended RCODE. */
75 +      rcode |= sizep[2] << 4;
76 +
77        if (check_subnet && !check_source(header, plen, pheader, query_source))
78         {
79           my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
80 @@ -641,11 +645,20 @@ static size_t process_reply(struct dns_h
81    if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
82       header->hb4 &= ~HB4_AD;
83    
84 -  if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
85 +  if (OPCODE(header) != QUERY)
86      return resize_packet(header, n, pheader, plen);
87 +
88 +  if (rcode != NOERROR && rcode != NXDOMAIN)
89 +    {
90 +      struct all_addr a;
91 +      a.addr.rcode.rcode = rcode;
92 +      log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
93 +      
94 +      return resize_packet(header, n, pheader, plen);
95 +    }
96    
97    /* Complain loudly if the upstream server is non-recursive. */
98 -  if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
99 +  if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
100        server && !(server->flags & SERV_WARNED_RECURSIVE))
101      {
102        prettyprint_addr(&server->addr, daemon->namebuff);
103 @@ -654,7 +667,7 @@ static size_t process_reply(struct dns_h
104         server->flags |= SERV_WARNED_RECURSIVE;
105      }  
106  
107 -  if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
108 +  if (daemon->bogus_addr && rcode != NXDOMAIN &&
109        check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
110      {
111        munged = 1;
112 @@ -666,7 +679,7 @@ static size_t process_reply(struct dns_h
113      {
114        int doctored = 0;
115        
116 -      if (RCODE(header) == NXDOMAIN && 
117 +      if (rcode == NXDOMAIN && 
118           extract_request(header, n, daemon->namebuff, NULL) &&
119           check_for_local_domain(daemon->namebuff, now))
120         {
121 @@ -1090,7 +1103,7 @@ void reply_query(int fd, int family, tim
122               if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
123                 domain = daemon->namebuff;
124               
125 -             log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
126 +             log_query(F_SECSTAT, domain, NULL, result);
127             }
128           
129           if (status == STAT_SECURE)
130 @@ -1948,7 +1961,7 @@ unsigned char *tcp_request(int confd, ti
131                           if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
132                             domain = daemon->namebuff;
133  
134 -                         log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
135 +                         log_query(F_SECSTAT, domain, NULL, result);
136                           
137                           if (status == STAT_BOGUS)
138                             {
139 --- a/src/rfc1035.c
140 +++ b/src/rfc1035.c
141 @@ -926,12 +926,11 @@ unsigned int extract_request(struct dns_
142    return F_QUERY;
143  }
144  
145 -
146  size_t setup_reply(struct dns_header *header, size_t qlen,
147                 struct all_addr *addrp, unsigned int flags, unsigned long ttl)
148  {
149    unsigned char *p;
150 -
151 +  
152    if (!(p = skip_questions(header, qlen)))
153      return 0;
154    
155 @@ -948,7 +947,12 @@ size_t setup_reply(struct dns_header *he
156    else if (flags == F_NXDOMAIN)
157      SET_RCODE(header, NXDOMAIN);
158    else if (flags == F_SERVFAIL)
159 -    SET_RCODE(header, SERVFAIL);
160 +    {
161 +      struct all_addr a;
162 +      a.addr.rcode.rcode = SERVFAIL;
163 +      log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
164 +      SET_RCODE(header, SERVFAIL);
165 +    }
166    else if (flags == F_IPV4)
167      { /* we know the address */
168        SET_RCODE(header, NOERROR);
169 @@ -966,8 +970,13 @@ size_t setup_reply(struct dns_header *he
170      }
171  #endif
172    else /* nowhere to forward to */
173 -    SET_RCODE(header, REFUSED);
174
175 +    {
176 +      struct all_addr a;
177 +      a.addr.rcode.rcode = REFUSED;
178 +      log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
179 +      SET_RCODE(header, REFUSED);
180 +    }
181 +  
182    return p - (unsigned char *)header;
183  }
184