Instead of using `client->query.qname` when caching a SERVFAIL answer,
use `client->query.origqname` when available.
This avoids caching a SERVFAIL against a CNAME target when the failure
occurs while the resolver is following the CNAME chain. This is
problematic, for instance, when the SERVFAIL is triggered by the
`max-query-count` threshold being reached, which would incorrectly
prevent legitimate resolution of the CNAME target while in the SERVFAIL
cache.
Note that if the SERVFAIL genuinely originated from resolving the CNAME
target, that specific failure will no longer be cached, and a direct
query for the CNAME target will trigger a fresh (likely failing)
resolution attempt. However, this is still preferable to the previous
behaviour, which would wrongly prevent resolving the CNAME target if it
was cached for other reasons (like the example above).
isc_time_t expire;
isc_interval_t i;
uint32_t flags = 0;
+ dns_name_t *qname = client->query.origqname != NULL
+ ? client->query.origqname
+ : client->query.qname;
if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) {
flags = NS_FAILCACHE_CD;
isc_interval_set(&i, client->inner.view->fail_ttl, 0);
result = isc_time_nowplusinterval(&expire, &i);
if (result == ISC_R_SUCCESS) {
- dns_badcache_add(client->inner.view->failcache,
- client->query.qname,
+ dns_badcache_add(client->inner.view->failcache, qname,
client->query.qtype, flags,
isc_time_seconds(&expire));
}