mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Improve handling of non-QUERY DNS requests.
We can't answer and shouldn't forward non-QUERY DNS requests. This patch fixes handling such requests from TCP connections; before the connection would be closed without reply. It also changes the RCODE in the answer from REFUSED to NOTIMP and provides clearer logging.
This commit is contained in:
@@ -2256,12 +2256,12 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||||||
}
|
}
|
||||||
else if (flags & F_AUTH)
|
else if (flags & F_AUTH)
|
||||||
source = "auth";
|
source = "auth";
|
||||||
else if (flags & F_DNSSEC)
|
else if (flags & F_DNSSEC)
|
||||||
{
|
{
|
||||||
source = arg;
|
source = arg;
|
||||||
verb = "to";
|
verb = "to";
|
||||||
}
|
}
|
||||||
else if (flags & F_SERVER)
|
else if (flags & F_SERVER)
|
||||||
{
|
{
|
||||||
source = "forwarded";
|
source = "forwarded";
|
||||||
verb = "to";
|
verb = "to";
|
||||||
|
|||||||
@@ -405,10 +405,18 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
|||||||
int start;
|
int start;
|
||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
|
|
||||||
|
setup_reply(header, flags, ede);
|
||||||
|
|
||||||
if (flags & (F_NXDOMAIN | F_NOERR))
|
if (flags & (F_NXDOMAIN | F_NOERR))
|
||||||
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL, 0);
|
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL, 0);
|
||||||
|
|
||||||
setup_reply(header, flags, ede);
|
if (flags & F_RCODE)
|
||||||
|
{
|
||||||
|
union all_addr a;
|
||||||
|
a.log.rcode = RCODE(header);
|
||||||
|
a.log.ede = ede;
|
||||||
|
log_query(F_UPSTREAM | F_RCODE, "opcode", &a, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(p = skip_questions(header, size)))
|
if (!(p = skip_questions(header, size)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
395
src/forward.c
395
src/forward.c
@@ -278,10 +278,15 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
/* new query */
|
/* new query */
|
||||||
if (!forward)
|
if (!forward)
|
||||||
{
|
{
|
||||||
/* If the query is malformed, we can't forward it because
|
if (OPCODE(header) != QUERY)
|
||||||
we can't recognise the answer. */
|
|
||||||
if (!gotname)
|
|
||||||
{
|
{
|
||||||
|
flags = F_RCODE;
|
||||||
|
goto reply;
|
||||||
|
}
|
||||||
|
else if (!gotname)
|
||||||
|
{
|
||||||
|
/* If the query is malformed, we can't forward it because
|
||||||
|
we can't recognise the answer. */
|
||||||
flags = 0;
|
flags = 0;
|
||||||
ede = EDE_INVALID_DATA;
|
ede = EDE_INVALID_DATA;
|
||||||
goto reply;
|
goto reply;
|
||||||
@@ -1686,7 +1691,9 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
have_mark = get_incoming_mark(&source_addr, &dst_addr, /* istcp: */ 0, &mark);
|
have_mark = get_incoming_mark(&source_addr, &dst_addr, /* istcp: */ 0, &mark);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
|
if (OPCODE(header) != QUERY)
|
||||||
|
log_query_mysockaddr(F_QUERY | F_FORWARD, "opcode", &source_addr, "non-query", 0);
|
||||||
|
else if (extract_request(header, (size_t)n, daemon->namebuff, &type))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
struct auth_zone *zone;
|
struct auth_zone *zone;
|
||||||
@@ -2292,6 +2299,8 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
{
|
{
|
||||||
int ede = EDE_UNSET;
|
int ede = EDE_UNSET;
|
||||||
|
|
||||||
|
stale = 0;
|
||||||
|
|
||||||
if (!do_stale)
|
if (!do_stale)
|
||||||
{
|
{
|
||||||
if (query_count >= TCP_MAX_QUERIES)
|
if (query_count >= TCP_MAX_QUERIES)
|
||||||
@@ -2322,8 +2331,15 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
if ((checking_disabled = header->hb4 & HB4_CD))
|
if ((checking_disabled = header->hb4 & HB4_CD))
|
||||||
no_cache_dnssec = 1;
|
no_cache_dnssec = 1;
|
||||||
|
|
||||||
if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
if (OPCODE(header) != QUERY)
|
||||||
{
|
{
|
||||||
|
log_query_mysockaddr(F_QUERY | F_FORWARD, "opcode", &peer_addr, "non-query", 0);
|
||||||
|
gotname = 0;
|
||||||
|
m = 0;
|
||||||
|
flags = F_RCODE;
|
||||||
|
}
|
||||||
|
else if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
||||||
|
{
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
struct auth_zone *zone;
|
struct auth_zone *zone;
|
||||||
#endif
|
#endif
|
||||||
@@ -2349,219 +2365,220 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
norebind = domain_no_rebind(daemon->namebuff);
|
norebind = domain_no_rebind(daemon->namebuff);
|
||||||
|
|
||||||
if (local_addr->sa.sa_family == AF_INET)
|
if (local_addr->sa.sa_family == AF_INET)
|
||||||
dst_addr_4 = local_addr->in.sin_addr;
|
dst_addr_4 = local_addr->in.sin_addr;
|
||||||
else
|
else
|
||||||
dst_addr_4.s_addr = 0;
|
dst_addr_4.s_addr = 0;
|
||||||
|
|
||||||
do_bit = 0;
|
do_bit = 0;
|
||||||
|
|
||||||
if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
|
if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
|
||||||
{
|
|
||||||
unsigned short flags;
|
|
||||||
|
|
||||||
have_pseudoheader = 1;
|
|
||||||
pheader += 4; /* udp_size, ext_rcode */
|
|
||||||
GETSHORT(flags, pheader);
|
|
||||||
|
|
||||||
if (flags & 0x8000)
|
|
||||||
do_bit = 1; /* do bit */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
|
||||||
#ifdef HAVE_AUTH
|
|
||||||
if (!auth_dns || local_auth)
|
|
||||||
#endif
|
|
||||||
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
|
||||||
allowed = is_query_allowed_for_mark((u32)mark, is_single_query ? daemon->namebuff : NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (0);
|
|
||||||
#ifdef HAVE_CONNTRACK
|
|
||||||
else if (!allowed)
|
|
||||||
{
|
|
||||||
u16 swap = htons(EDE_BLOCKED);
|
|
||||||
|
|
||||||
m = answer_disallowed(header, size, (u32)mark, is_single_query ? daemon->namebuff : NULL);
|
|
||||||
|
|
||||||
if (have_pseudoheader && m != 0)
|
|
||||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
|
|
||||||
EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_AUTH
|
|
||||||
else if (auth_dns)
|
|
||||||
{
|
|
||||||
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
|
|
||||||
if (m >= 1 && have_pseudoheader)
|
|
||||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
|
|
||||||
0, NULL, 0, do_bit, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int ad_reqd = do_bit;
|
|
||||||
/* RFC 6840 5.7 */
|
|
||||||
if (header->hb4 & HB4_AD)
|
|
||||||
ad_reqd = 1;
|
|
||||||
|
|
||||||
if (do_stale)
|
|
||||||
m = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (saved_question)
|
|
||||||
blockdata_free(saved_question);
|
|
||||||
|
|
||||||
saved_question = blockdata_alloc((char *)header, (size_t)size);
|
|
||||||
saved_size = size;
|
|
||||||
|
|
||||||
/* m > 0 if answered from cache */
|
|
||||||
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
|
||||||
dst_addr_4, netmask, now, ad_reqd, do_bit, &stale, &filtered);
|
|
||||||
|
|
||||||
if (m >= 1 && have_pseudoheader)
|
|
||||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
|
|
||||||
0, NULL, 0, do_bit, 0);
|
|
||||||
}
|
|
||||||
/* Do this by steam now we're not in the select() loop */
|
|
||||||
check_log_writer(1);
|
|
||||||
|
|
||||||
if (m == 0 && saved_question)
|
|
||||||
{
|
{
|
||||||
struct server *master;
|
unsigned short flags;
|
||||||
int start;
|
|
||||||
|
|
||||||
blockdata_retrieve(saved_question, (size_t)saved_size, header);
|
have_pseudoheader = 1;
|
||||||
size = saved_size;
|
pheader += 4; /* udp_size, ext_rcode */
|
||||||
|
GETSHORT(flags, pheader);
|
||||||
|
|
||||||
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
if (flags & 0x8000)
|
||||||
flags = is_local_answer(now, first, daemon->namebuff);
|
do_bit = 1; /* do bit */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CONNTRACK
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
if (!auth_dns || local_auth)
|
||||||
|
#endif
|
||||||
|
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
||||||
|
allowed = is_query_allowed_for_mark((u32)mark, is_single_query ? daemon->namebuff : NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (0);
|
||||||
|
#ifdef HAVE_CONNTRACK
|
||||||
|
else if (!allowed)
|
||||||
|
{
|
||||||
|
u16 swap = htons(EDE_BLOCKED);
|
||||||
|
|
||||||
|
m = answer_disallowed(header, size, (u32)mark, is_single_query ? daemon->namebuff : NULL);
|
||||||
|
|
||||||
|
if (have_pseudoheader && m != 0)
|
||||||
|
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
|
||||||
|
EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
else if (auth_dns)
|
||||||
|
{
|
||||||
|
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
|
||||||
|
if (m >= 1 && have_pseudoheader)
|
||||||
|
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
|
||||||
|
0, NULL, 0, do_bit, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ad_reqd = do_bit;
|
||||||
|
/* RFC 6840 5.7 */
|
||||||
|
if (header->hb4 & HB4_AD)
|
||||||
|
ad_reqd = 1;
|
||||||
|
|
||||||
|
if (do_stale)
|
||||||
|
m = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No configured servers */
|
if (saved_question)
|
||||||
ede = EDE_NOT_READY;
|
blockdata_free(saved_question);
|
||||||
flags = 0;
|
|
||||||
|
saved_question = blockdata_alloc((char *)header, (size_t)size);
|
||||||
|
saved_size = size;
|
||||||
|
|
||||||
|
/* m > 0 if answered from cache */
|
||||||
|
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||||
|
dst_addr_4, netmask, now, ad_reqd, do_bit, &stale, &filtered);
|
||||||
|
|
||||||
|
if (m >= 1 && have_pseudoheader)
|
||||||
|
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
|
||||||
|
0, NULL, 0, do_bit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't forward A or AAAA queries for simple names, except the empty name */
|
/* Do this by steam now we're not in the select() loop */
|
||||||
if (!flags &&
|
check_log_writer(1);
|
||||||
option_bool(OPT_NODOTS_LOCAL) &&
|
|
||||||
(gotname & (F_IPV4 | F_IPV6)) &&
|
|
||||||
!strchr(daemon->namebuff, '.') &&
|
|
||||||
strlen(daemon->namebuff) != 0)
|
|
||||||
flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
|
|
||||||
|
|
||||||
if (!flags && ede != EDE_NOT_READY)
|
if (m == 0 && saved_question)
|
||||||
{
|
{
|
||||||
master = daemon->serverarray[first];
|
struct server *master;
|
||||||
|
int start;
|
||||||
|
|
||||||
if (option_bool(OPT_ORDER) || master->last_server == -1)
|
blockdata_retrieve(saved_question, (size_t)saved_size, header);
|
||||||
start = first;
|
size = saved_size;
|
||||||
|
|
||||||
|
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
||||||
|
flags = is_local_answer(now, first, daemon->namebuff);
|
||||||
else
|
else
|
||||||
start = master->last_server;
|
|
||||||
|
|
||||||
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &cacheable);
|
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && (master->flags & SERV_DO_DNSSEC))
|
|
||||||
{
|
{
|
||||||
size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
|
/* No configured servers */
|
||||||
|
ede = EDE_NOT_READY;
|
||||||
/* For debugging, set Checking Disabled, otherwise, have the upstream check too,
|
flags = 0;
|
||||||
this allows it to select auth servers when one is returning bad data. */
|
|
||||||
if (option_bool(OPT_DNSSEC_DEBUG))
|
|
||||||
header->hb4 |= HB4_CD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check if we added a pheader on forwarding - may need to
|
|
||||||
strip it from the reply. */
|
|
||||||
if (!have_pseudoheader && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
|
|
||||||
added_pheader = 1;
|
|
||||||
|
|
||||||
/* Loop round available servers until we succeed in connecting to one. */
|
|
||||||
if ((m = tcp_talk(first, last, start, packet, size, have_mark, mark, &serv)) == 0)
|
|
||||||
{
|
|
||||||
ede = EDE_NETERR;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get query name again for logging - may have been overwritten */
|
/* don't forward A or AAAA queries for simple names, except the empty name */
|
||||||
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
if (!flags &&
|
||||||
strcpy(daemon->namebuff, "query");
|
option_bool(OPT_NODOTS_LOCAL) &&
|
||||||
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff, &serv->addr, NULL, 0);
|
(gotname & (F_IPV4 | F_IPV6)) &&
|
||||||
|
!strchr(daemon->namebuff, '.') &&
|
||||||
|
strlen(daemon->namebuff) != 0)
|
||||||
|
flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
|
||||||
|
|
||||||
|
if (!flags && ede != EDE_NOT_READY)
|
||||||
|
{
|
||||||
|
master = daemon->serverarray[first];
|
||||||
|
|
||||||
|
if (option_bool(OPT_ORDER) || master->last_server == -1)
|
||||||
|
start = first;
|
||||||
|
else
|
||||||
|
start = master->last_server;
|
||||||
|
|
||||||
|
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &cacheable);
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID) && (master->flags & SERV_DO_DNSSEC))
|
||||||
{
|
|
||||||
/* Clear this in case we don't call tcp_key_recurse() below */
|
|
||||||
memset(daemon->rr_status, 0, sizeof(*daemon->rr_status) * daemon->rr_status_sz);
|
|
||||||
|
|
||||||
if (!checking_disabled && (master->flags & SERV_DO_DNSSEC))
|
|
||||||
{
|
{
|
||||||
int keycount = daemon->limit[LIMIT_WORK]; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
|
size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
|
||||||
int validatecount = daemon->limit[LIMIT_CRYPTO];
|
|
||||||
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
|
|
||||||
serv, have_mark, mark, &keycount, &validatecount);
|
|
||||||
char *result, *domain = "result";
|
|
||||||
|
|
||||||
union all_addr a;
|
/* For debugging, set Checking Disabled, otherwise, have the upstream check too,
|
||||||
a.log.ede = ede = errflags_to_ede(status);
|
this allows it to select auth servers when one is returning bad data. */
|
||||||
|
if (option_bool(OPT_DNSSEC_DEBUG))
|
||||||
if (STAT_ISEQUAL(status, STAT_ABANDONED))
|
header->hb4 |= HB4_CD;
|
||||||
{
|
|
||||||
result = "ABANDONED";
|
|
||||||
status = STAT_BOGUS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = (STAT_ISEQUAL(status, STAT_SECURE) ? "SECURE" : (STAT_ISEQUAL(status, STAT_INSECURE) ? "INSECURE" : "BOGUS"));
|
|
||||||
|
|
||||||
if (STAT_ISEQUAL(status, STAT_SECURE))
|
|
||||||
cache_secure = 1;
|
|
||||||
else if (STAT_ISEQUAL(status, STAT_BOGUS))
|
|
||||||
{
|
|
||||||
no_cache_dnssec = 1;
|
|
||||||
bogusanswer = 1;
|
|
||||||
|
|
||||||
if (extract_request(header, m, daemon->namebuff, NULL))
|
|
||||||
domain = daemon->namebuff;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_query(F_SECSTAT, domain, &a, result, 0);
|
|
||||||
|
|
||||||
if ((daemon->limit[LIMIT_CRYPTO] - validatecount) > (int)daemon->metrics[METRIC_CRYPTO_HWM])
|
|
||||||
daemon->metrics[METRIC_CRYPTO_HWM] = daemon->limit[LIMIT_CRYPTO] - validatecount;
|
|
||||||
|
|
||||||
if ((daemon->limit[LIMIT_WORK] - keycount) > (int)daemon->metrics[METRIC_WORK_HWM])
|
|
||||||
daemon->metrics[METRIC_WORK_HWM] = daemon->limit[LIMIT_WORK] - keycount;
|
|
||||||
|
|
||||||
/* include DNSSEC queries in the limit for a connection. */
|
|
||||||
query_count += daemon->limit[LIMIT_WORK] - keycount;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* restore CD bit to the value in the query */
|
/* Check if we added a pheader on forwarding - may need to
|
||||||
if (checking_disabled)
|
strip it from the reply. */
|
||||||
header->hb4 |= HB4_CD;
|
if (!have_pseudoheader && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
|
||||||
else
|
added_pheader = 1;
|
||||||
header->hb4 &= ~HB4_CD;
|
|
||||||
|
|
||||||
/* Never cache answers which are contingent on the source or MAC address EDSN0 option,
|
/* Loop round available servers until we succeed in connecting to one. */
|
||||||
since the cache is ignorant of such things. */
|
if ((m = tcp_talk(first, last, start, packet, size, have_mark, mark, &serv)) == 0)
|
||||||
if (!cacheable)
|
{
|
||||||
no_cache_dnssec = 1;
|
ede = EDE_NETERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m = process_reply(header, now, serv, (unsigned int)m,
|
/* get query name again for logging - may have been overwritten */
|
||||||
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
|
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
||||||
ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede);
|
strcpy(daemon->namebuff, "query");
|
||||||
|
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff, &serv->addr, NULL, 0);
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
|
{
|
||||||
|
/* Clear this in case we don't call tcp_key_recurse() below */
|
||||||
|
memset(daemon->rr_status, 0, sizeof(*daemon->rr_status) * daemon->rr_status_sz);
|
||||||
|
|
||||||
|
if (!checking_disabled && (master->flags & SERV_DO_DNSSEC))
|
||||||
|
{
|
||||||
|
int keycount = daemon->limit[LIMIT_WORK]; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
|
||||||
|
int validatecount = daemon->limit[LIMIT_CRYPTO];
|
||||||
|
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
|
||||||
|
serv, have_mark, mark, &keycount, &validatecount);
|
||||||
|
char *result, *domain = "result";
|
||||||
|
|
||||||
|
union all_addr a;
|
||||||
|
a.log.ede = ede = errflags_to_ede(status);
|
||||||
|
|
||||||
|
if (STAT_ISEQUAL(status, STAT_ABANDONED))
|
||||||
|
{
|
||||||
|
result = "ABANDONED";
|
||||||
|
status = STAT_BOGUS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = (STAT_ISEQUAL(status, STAT_SECURE) ? "SECURE" : (STAT_ISEQUAL(status, STAT_INSECURE) ? "INSECURE" : "BOGUS"));
|
||||||
|
|
||||||
|
if (STAT_ISEQUAL(status, STAT_SECURE))
|
||||||
|
cache_secure = 1;
|
||||||
|
else if (STAT_ISEQUAL(status, STAT_BOGUS))
|
||||||
|
{
|
||||||
|
no_cache_dnssec = 1;
|
||||||
|
bogusanswer = 1;
|
||||||
|
|
||||||
|
if (extract_request(header, m, daemon->namebuff, NULL))
|
||||||
|
domain = daemon->namebuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_query(F_SECSTAT, domain, &a, result, 0);
|
||||||
|
|
||||||
|
if ((daemon->limit[LIMIT_CRYPTO] - validatecount) > (int)daemon->metrics[METRIC_CRYPTO_HWM])
|
||||||
|
daemon->metrics[METRIC_CRYPTO_HWM] = daemon->limit[LIMIT_CRYPTO] - validatecount;
|
||||||
|
|
||||||
|
if ((daemon->limit[LIMIT_WORK] - keycount) > (int)daemon->metrics[METRIC_WORK_HWM])
|
||||||
|
daemon->metrics[METRIC_WORK_HWM] = daemon->limit[LIMIT_WORK] - keycount;
|
||||||
|
|
||||||
|
/* include DNSSEC queries in the limit for a connection. */
|
||||||
|
query_count += daemon->limit[LIMIT_WORK] - keycount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* restore CD bit to the value in the query */
|
||||||
|
if (checking_disabled)
|
||||||
|
header->hb4 |= HB4_CD;
|
||||||
|
else
|
||||||
|
header->hb4 &= ~HB4_CD;
|
||||||
|
|
||||||
|
/* Never cache answers which are contingent on the source or MAC address EDSN0 option,
|
||||||
|
since the cache is ignorant of such things. */
|
||||||
|
if (!cacheable)
|
||||||
|
no_cache_dnssec = 1;
|
||||||
|
|
||||||
|
m = process_reply(header, now, serv, (unsigned int)m,
|
||||||
|
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
|
||||||
|
ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_stale)
|
if (do_stale)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1240,6 +1240,8 @@ void setup_reply(struct dns_header *header, unsigned int flags, int ede)
|
|||||||
SET_RCODE(header, NOERROR); /* empty domain */
|
SET_RCODE(header, NOERROR); /* empty domain */
|
||||||
else if (flags == F_NXDOMAIN)
|
else if (flags == F_NXDOMAIN)
|
||||||
SET_RCODE(header, NXDOMAIN);
|
SET_RCODE(header, NXDOMAIN);
|
||||||
|
else if (flags == F_RCODE)
|
||||||
|
SET_RCODE(header, NOTIMP);
|
||||||
else if (flags & ( F_IPV4 | F_IPV6))
|
else if (flags & ( F_IPV4 | F_IPV6))
|
||||||
{
|
{
|
||||||
SET_RCODE(header, NOERROR);
|
SET_RCODE(header, NOERROR);
|
||||||
@@ -2182,7 +2184,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (flags & F_NXDOMAIN)
|
if (flags & F_NXDOMAIN)
|
||||||
nxdomain = 1;
|
nxdomain = 1;
|
||||||
else if (qtype != T_ANY && rr_on_list(daemon->filter_rr, qtype))
|
else if (qtype != T_ANY && rr_on_list(daemon->filter_rr, qtype))
|
||||||
flags |= F_NEG | F_CONFIG;
|
flags |= F_NEG | F_CONFIG;
|
||||||
|
|
||||||
auth = 0;
|
auth = 0;
|
||||||
ans = 1;
|
ans = 1;
|
||||||
@@ -2210,8 +2212,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
anscount++;
|
anscount++;
|
||||||
|
|
||||||
/* log after cache insertion as log_txt mangles rrdata */
|
/* log after cache insertion as log_txt mangles rrdata */
|
||||||
if (qtype == T_TXT && !(crecp->flags & F_NEG))
|
if (qtype == T_TXT && !(flags & F_NEG))
|
||||||
log_txt(name, (unsigned char *)rrdata, rrlen, crecp->flags & F_DNSSECOK);
|
log_txt(name, (unsigned char *)rrdata, rrlen, flags & (F_DNSSECOK | F_STALE));
|
||||||
else
|
else
|
||||||
log_query(flags, name, &crecp->addr, NULL, 0);
|
log_query(flags, name, &crecp->addr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user