2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

Return SERVFAIL for a too long CNAME chain

Due to the maximum query restart limitation a long CNAME chain
it is cut after 16 queries but named still returns NOERROR.

Return SERVFAIL instead and the partial answer.

(cherry picked from commit b621f1d88e)
This commit is contained in:
Aram Sargsyan
2024-06-06 12:06:59 +00:00
parent 9faf355a5c
commit 946931ccb7

View File

@@ -11910,7 +11910,7 @@ isc_result_t
ns_query_done(query_ctx_t *qctx) { ns_query_done(query_ctx_t *qctx) {
isc_result_t result = ISC_R_UNSET; isc_result_t result = ISC_R_UNSET;
const dns_namelist_t *secs = qctx->client->message->sections; const dns_namelist_t *secs = qctx->client->message->sections;
bool nodetach; bool nodetach, partial_result_with_servfail = false;
CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done"); CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done");
@@ -11944,13 +11944,36 @@ ns_query_done(query_ctx_t *qctx) {
/* /*
* Do we need to restart the query (e.g. for CNAME chaining)? * Do we need to restart the query (e.g. for CNAME chaining)?
*/ */
if (qctx->want_restart && qctx->client->query.restarts < MAX_RESTARTS) { if (qctx->want_restart) {
if (qctx->client->query.restarts < MAX_RESTARTS) {
qctx->client->query.restarts++; qctx->client->query.restarts++;
return (ns__query_start(qctx)); return (ns__query_start(qctx));
} else {
/*
* This is e.g. a long CNAME chain which we cut short.
*/
qctx->client->query.attributes |=
NS_QUERYATTR_PARTIALANSWER;
qctx->client->message->rcode = dns_rcode_servfail;
qctx->result = DNS_R_SERVFAIL;
/*
* Send the answer back with a SERVFAIL result even
* if recursion was requested.
*/
partial_result_with_servfail = true;
ns_client_extendederror(qctx->client, 0,
"max. restarts reached");
ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
"query iterations limit reached");
}
} }
if (qctx->result != ISC_R_SUCCESS && if (qctx->result != ISC_R_SUCCESS &&
(!PARTIALANSWER(qctx->client) || WANTRECURSION(qctx->client) || (!PARTIALANSWER(qctx->client) ||
(WANTRECURSION(qctx->client) && !partial_result_with_servfail) ||
qctx->result == DNS_R_DROP)) qctx->result == DNS_R_DROP))
{ {
if (qctx->result == DNS_R_DUPLICATE || if (qctx->result == DNS_R_DUPLICATE ||