mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +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.
This commit is contained in:
@@ -11546,7 +11546,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");
|
||||||
|
|
||||||
@@ -11580,7 +11580,8 @@ 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) {
|
||||||
query_ctx_t *saved_qctx = NULL;
|
query_ctx_t *saved_qctx = NULL;
|
||||||
qctx->client->query.restarts++;
|
qctx->client->query.restarts++;
|
||||||
saved_qctx = isc_mem_get(qctx->client->manager->mctx,
|
saved_qctx = isc_mem_get(qctx->client->manager->mctx,
|
||||||
@@ -11588,13 +11589,35 @@ ns_query_done(query_ctx_t *qctx) {
|
|||||||
qctx_save(qctx, saved_qctx);
|
qctx_save(qctx, saved_qctx);
|
||||||
isc_nmhandle_attach(qctx->client->handle,
|
isc_nmhandle_attach(qctx->client->handle,
|
||||||
&qctx->client->restarthandle);
|
&qctx->client->restarthandle);
|
||||||
isc_async_run(qctx->client->manager->loop, async_restart,
|
isc_async_run(qctx->client->manager->loop,
|
||||||
saved_qctx);
|
async_restart, saved_qctx);
|
||||||
return (DNS_R_CONTINUE);
|
return (DNS_R_CONTINUE);
|
||||||
|
} 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 ||
|
||||||
|
Reference in New Issue
Block a user