You need to sign in or sign up before continuing.
Commit 07ed585c authored by Simon Kelley's avatar Simon Kelley

Add logging for DNS error returns from upstream and local configuration.

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