diff options
Diffstat (limited to 'services/cache/dns.c')
-rw-r--r-- | services/cache/dns.c | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/services/cache/dns.c b/services/cache/dns.c index 7ab63bacf492..351b3568c80b 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -1056,8 +1056,9 @@ dns_cache_lookup(struct module_env* env, int dns_cache_store(struct module_env* env, struct query_info* msgqinf, - struct reply_info* msgrep, int is_referral, time_t leeway, int pside, - struct regional* region, uint32_t flags, time_t qstarttime) + struct reply_info* msgrep, int is_referral, time_t leeway, int pside, + struct regional* region, uint32_t flags, time_t qstarttime, + int is_valrec) { struct reply_info* rep = NULL; if(SERVE_EXPIRED) { @@ -1065,7 +1066,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, * useful expired record exists. */ struct msgreply_entry* e = msg_cache_lookup(env, msgqinf->qname, msgqinf->qname_len, msgqinf->qtype, - msgqinf->qclass, flags, 0, 0); + msgqinf->qclass, flags, 0, 1); if(e) { struct reply_info* cached = e->entry.data; if(cached->ttl < *env->now @@ -1079,7 +1080,43 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, * one and let the validator manage caching. */ && cached->security != sec_status_bogus && (env->need_to_validate && - msgrep->security == sec_status_unchecked)) { + msgrep->security == sec_status_unchecked) + /* Exceptions to that rule are: + * o recursions that don't need validation but + * need to update the cache for coherence + * (delegation information while iterating, + * DNSKEY and DS lookups from validator) + * o explicit RRSIG queries that are not + * validated. */ + && !is_valrec + && msgqinf->qtype != LDNS_RR_TYPE_RRSIG) { + if((int)FLAGS_GET_RCODE(msgrep->flags) != + LDNS_RCODE_NOERROR && + (int)FLAGS_GET_RCODE(msgrep->flags) != + LDNS_RCODE_NXDOMAIN) { + /* The current response has an + * erroneous rcode. Adjust norec time + * so that additional lookups are not + * performed for some time. */ + verbose(VERB_ALGO, "set " + "serve-expired-norec-ttl for " + "response in cache"); + cached->serve_expired_norec_ttl = + NORR_TTL + *env->now; + if(env->cfg->serve_expired_ttl_reset && + cached->serve_expired_ttl + < *env->now + + env->cfg->serve_expired_ttl) { + /* Reset serve-expired-ttl for + * valid response in cache. */ + verbose(VERB_ALGO, "reset " + "serve-expired-ttl " + "for response in cache"); + cached->serve_expired_ttl = + *env->now + + env->cfg->serve_expired_ttl; + } + } verbose(VERB_ALGO, "a validated expired entry " "could be overwritten, skip caching " "the new message at this stage"); |