Commit b5c9a8ca authored by Witold Krecicki's avatar Witold Krecicki Committed by Michał Kępień

Set result to SERVFAIL if upstream responded with FORMERR

Commit ba912435 causes the resolver to
respond to a client query with FORMERR when all upstream queries sent to
the servers authoritative for QNAME elicit FORMERR responses.  This
happens because resolver code returns DNS_R_FORMERR in such a case and
dns_result_torcode() acts as a pass-through for all arguments which are
already a valid RCODE.

The correct RCODE to set in the response returned to the client in the
case described above is SERVFAIL.  Make sure this happens by overriding
the RCODE in query_gotanswer(), on the grounds that any format errors in
the client query itself should be caught long before execution reaches
that point.  This change should not reduce query error logging accuracy
as the resolver code itself reports the exact reason for returning a
DNS_R_FORMERR result using log_formerr().
parent 9fd3c8a9
Pipeline #5553 passed with stages
in 7 minutes and 57 seconds
......@@ -74,6 +74,9 @@ sub handleUDP {
} elsif ($qname eq "ns.no-questions") {
$packet->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.8"));
return $packet->data;
} elsif ($qname =~ /\.formerr-to-all$/) {
$packet->header->rcode("FORMERR");
return $packet->data;
}
# don't use Net::DNS to construct the header only reply as early
......
......@@ -24,3 +24,5 @@ example.net. NS ns.example.net.
ns.example.net. A 10.53.0.6
no-questions. NS ns.no-questions.
ns.no-questions. A 10.53.0.8
formerr-to-all. NS ns.formerr-to-all.
ns.formerr-to-all. A 10.53.0.8
......@@ -788,5 +788,13 @@ grep "1.2.3.4" dig.ns5.out.${n} > /dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "checking SERVFAIL is returned when all authoritative servers return FORMERR ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.5 ns.formerr-to-all. a > dig.ns5.out.${n} || ret=1
grep "status: SERVFAIL" dig.ns5.out.${n} > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
......@@ -6737,6 +6737,10 @@ query_gotanswer(query_ctx_t *qctx, isc_result_t result) {
case DNS_R_DNAME:
return (query_dname(qctx));
case DNS_R_FORMERR:
QUERY_ERROR(qctx, DNS_R_SERVFAIL);
return (query_done(qctx));
default:
/*
* Something has gone wrong.
......
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