mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Fix cache update when serve expired is used (#1143)
- Fix cache update when serve expired is used in order to not evict still usable expired records. Modules are forbidden to update the cache if their answer is DNSSEC unchecked or bogus and a valid (expired) entry already exists. Bogus replies from the validator are also discarded in favor of existing (expired) valid replies. - serve-expired-ttl-reset should try to keep expired records in the cache in case they are reset.
This commit is contained in:
+48
-4
@@ -2435,6 +2435,8 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
/* if the result is bogus - set message ttl to bogus ttl to avoid
|
||||
* endless bogus revalidation */
|
||||
if(vq->orig_msg->rep->security == sec_status_bogus) {
|
||||
struct msgreply_entry* e;
|
||||
|
||||
/* see if we can try again to fetch data */
|
||||
if(vq->restart_count < ve->max_restart) {
|
||||
verbose(VERB_ALGO, "validation failed, "
|
||||
@@ -2449,10 +2451,51 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(qstate->env->cfg->serve_expired &&
|
||||
(e=msg_cache_lookup(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
qstate->qinfo.qclass, qstate->query_flags,
|
||||
0 /*now; allow expired*/,
|
||||
1 /*wr; we may update the data*/))) {
|
||||
struct reply_info* rep = (struct reply_info*)e->entry.data;
|
||||
if(rep && rep->security > sec_status_bogus &&
|
||||
(!qstate->env->cfg->serve_expired_ttl ||
|
||||
qstate->env->cfg->serve_expired_ttl_reset ||
|
||||
*qstate->env->now <= rep->serve_expired_ttl)) {
|
||||
verbose(VERB_ALGO, "validation failed but "
|
||||
"previously cached valid response "
|
||||
"exists; set serve-expired-norec-ttl "
|
||||
"for response in cache");
|
||||
rep->serve_expired_norec_ttl = NORR_TTL +
|
||||
*qstate->env->now;
|
||||
if(qstate->env->cfg->serve_expired_ttl_reset &&
|
||||
*qstate->env->now + qstate->env->cfg->serve_expired_ttl
|
||||
> rep->serve_expired_ttl) {
|
||||
verbose(VERB_ALGO, "reset serve-expired-ttl for "
|
||||
"valid response in cache");
|
||||
rep->serve_expired_ttl = *qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
/* Return an error response.
|
||||
* If serve-expired-client-timeout is enabled,
|
||||
* the client-timeout logic will try to find an
|
||||
* (expired) answer in the cache as last
|
||||
* resort. If it is not enabled, expired
|
||||
* answers are already used before the mesh
|
||||
* activation. */
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
}
|
||||
|
||||
vq->orig_msg->rep->ttl = ve->bogus_ttl;
|
||||
vq->orig_msg->rep->prefetch_ttl =
|
||||
PREFETCH_TTL_CALC(vq->orig_msg->rep->ttl);
|
||||
vq->orig_msg->rep->serve_expired_ttl =
|
||||
vq->orig_msg->rep->serve_expired_ttl =
|
||||
vq->orig_msg->rep->ttl + qstate->env->cfg->serve_expired_ttl;
|
||||
if((qstate->env->cfg->val_log_level >= 1 ||
|
||||
qstate->env->cfg->log_servfail) &&
|
||||
@@ -2518,8 +2561,9 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
* to check if from parentNS */
|
||||
if(!qstate->no_cache_store) {
|
||||
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
|
||||
vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime)) {
|
||||
vq->orig_msg->rep, 0, qstate->prefetch_leeway,
|
||||
0, qstate->region, qstate->query_flags,
|
||||
qstate->qstarttime)) {
|
||||
log_err("out of memory caching validator results");
|
||||
}
|
||||
}
|
||||
@@ -2527,7 +2571,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
/* for a referral, store the verified RRsets */
|
||||
/* and this does not get prefetched, so no leeway */
|
||||
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
|
||||
vq->orig_msg->rep, 1, 0, 0, NULL,
|
||||
vq->orig_msg->rep, 1, 0, 0, qstate->region,
|
||||
qstate->query_flags, qstate->qstarttime)) {
|
||||
log_err("out of memory caching validator results");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user