From 07ed585c38d8f7c0a18470d2e79cf46ea92ea96a Mon Sep 17 00:00:00 2001 From: Simon Kelley 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 --- 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; }