Merge pull request #665 from pi-hole/fix/REFUSED_SERVFAIL

Correctly handle REFUSED and SERVFAIL responses
This commit is contained in:
DL6ER 2020-03-29 22:19:11 +02:00 committed by GitHub
commit 6c240d3888
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 9 deletions

View File

@ -479,12 +479,12 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
{
log_query(flags | F_UPSTREAM, name, addr, NULL);
FTL_reply(flags, name, addr, daemon->log_display_id);
/* Don't mess with TTL for DNSSEC records. */
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
ttl = daemon->min_cache_ttl;
FTL_reply(flags, name, addr, daemon->log_display_id);
}
/* if previous insertion failed give up now. */

View File

@ -964,6 +964,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
struct all_addr a;
a.addr.rcode.rcode = SERVFAIL;
log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
FTL_reply(flags, "error", &a, daemon->log_display_id);
SET_RCODE(header, SERVFAIL);
}
else if (flags & ( F_IPV4 | F_IPV6))
@ -991,6 +992,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
struct all_addr a;
a.addr.rcode.rcode = REFUSED;
log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
FTL_reply(flags, "error", &a, daemon->log_display_id);
SET_RCODE(header, REFUSED);
}

View File

@ -37,7 +37,8 @@
#include "args.h"
static void print_flags(const unsigned int flags);
static void save_reply_type(const unsigned int flags, queriesData* query, const struct timeval response);
static void save_reply_type(const unsigned int flags, const struct all_addr *addr,
queriesData* query, const struct timeval response);
static unsigned long converttimeval(const struct timeval time) __attribute__((const));
static void detect_blocked_IP(const unsigned short flags, const char* answer, const int queryID);
static void query_externally_blocked(const int queryID, const unsigned char status);
@ -763,6 +764,20 @@ void _FTL_reply(const unsigned short flags, const char *name, const struct all_a
answer = "(NXDOMAIN)";
else if(flags & F_NEG)
answer = "(NODATA)";
else if(flags & F_RCODE && addr != NULL)
{
unsigned int rcode = addr->addr.rcode.rcode;
if(rcode == REFUSED)
{
// This happens, e.g., in a "nowhere to forward to" situation
answer = "REFUSED";
}
else if(rcode == SERVFAIL)
{
// This happens on upstream destionation errors
answer = "SERVFAIL";
}
}
// Possible debugging output
if(config.debug & DEBUG_QUERIES)
@ -858,7 +873,7 @@ void _FTL_reply(const unsigned short flags, const char *name, const struct all_a
}
// Save reply type and update individual reply counters
save_reply_type(flags, query, response);
save_reply_type(flags, addr, query, response);
// Hereby, this query is now fully determined
query->complete = true;
@ -872,7 +887,7 @@ void _FTL_reply(const unsigned short flags, const char *name, const struct all_a
query->reply != QUERY_EXTERNAL_BLOCKED_NXRA)
{
// Save reply type and update individual reply counters
save_reply_type(flags, query, response);
save_reply_type(flags, addr, query, response);
// Detect if returned IP indicates that this query was blocked
detect_blocked_IP(flags, answer, i);
@ -890,7 +905,7 @@ void _FTL_reply(const unsigned short flags, const char *name, const struct all_a
// Hence, isExactMatch is always false
// Save reply type and update individual reply counters
save_reply_type(flags, query, response);
save_reply_type(flags, addr, query, response);
}
else if(isExactMatch && !query->complete)
{
@ -1195,7 +1210,7 @@ void _FTL_cache(const unsigned int flags, const char *name, const struct all_add
}
// Save reply type and update individual reply counters
save_reply_type(flags, query, response);
save_reply_type(flags, addr, query, response);
// Hereby, this query is now fully determined
query->complete = true;
@ -1213,7 +1228,7 @@ static void query_blocked(queriesData* query, domainsData* domain, clientsData*
// Get response time
struct timeval response;
gettimeofday(&response, 0);
save_reply_type(blocking_flags, query, response);
save_reply_type(blocking_flags, NULL, query, response);
// Adjust counters
if(query->status == QUERY_UNKNOWN)
@ -1422,7 +1437,7 @@ void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode,
query_externally_blocked(queryID, QUERY_EXTERNAL_BLOCKED_NXRA);
// Store reply type as replied with NXDOMAIN
save_reply_type(F_NEG | F_NXDOMAIN, query, response);
save_reply_type(F_NEG | F_NXDOMAIN, NULL, query, response);
// Unlock shared memory
unlock_shm();
@ -1445,7 +1460,8 @@ void print_flags(const unsigned int flags)
free(flagstr);
}
static void save_reply_type(const unsigned int flags, queriesData* query, const struct timeval response)
static void save_reply_type(const unsigned int flags, const struct all_addr *addr,
queriesData* query, const struct timeval response)
{
// Iterate through possible values
if(flags & F_NEG)
@ -1480,6 +1496,20 @@ static void save_reply_type(const unsigned int flags, queriesData* query, const
// TXT query
query->reply = REPLY_RRNAME;
}
else if(flags & F_RCODE && addr != NULL)
{
const unsigned int rcode = addr->addr.rcode.rcode;
if(rcode == REFUSED)
{
// REFUSED query
query->reply = REPLY_REFUSED;
}
else if(rcode == SERVFAIL)
{
// SERVFAIL query
query->reply = REPLY_SERVFAIL;
}
}
else
{
// Valid IP