From d96de4c222e7a2b4a8860ee6aaee36ae3f5b2b4e Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Tue, 27 Nov 2018 10:56:45 +0000 Subject: [PATCH] - New and better fix for Fix #4193: Fix that prefetch failure does not overwrite valid cache entry with SERVFAIL. git-svn-id: file:///svn/unbound/trunk@4982 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 2 ++ iterator/iterator.c | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/Changelog b/doc/Changelog index 7adad0590..3b62e6c6e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,8 @@ other threads from picking up the wrong data. The module restores the previous no_cache_store setting when the the module is finished. - Fix #4208: 'stub-no-cache' and 'forward-no-cache' not work. + - New and better fix for Fix #4193: Fix that prefetch failure does + not overwrite valid cache entry with SERVFAIL. 26 November 2018: Wouter - Fix to not set GLOB_NOSORT so the unbound.conf include: files are diff --git a/iterator/iterator.c b/iterator/iterator.c index b21ebb63d..f66381b40 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -292,7 +292,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode) if(!qstate->no_cache_store) { /* store in cache */ struct reply_info err; - if(qstate->prefetch_leeway > 0) { + if(qstate->prefetch_leeway > NORR_TTL) { verbose(VERB_ALGO, "error response for prefetch in cache"); /* attempt to adjust the cache entry prefetch */ if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo, @@ -327,6 +327,29 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode) /* serving expired contents, but nothing is cached * at all, so the servfail cache entry is useful * (stops waste of time on this servfail NORR_TTL) */ + } else { + /* don't overwrite existing (non-expired) data in + * cache with a servfail */ + struct msgreply_entry* msg; + if((msg=msg_cache_lookup(qstate->env, + qstate->qinfo.qname, qstate->qinfo.qname_len, + qstate->qinfo.qtype, qstate->qinfo.qclass, + qstate->query_flags, *qstate->env->now, 0)) + != NULL) { + struct reply_info* rep = (struct reply_info*) + msg->entry.data; + if(FLAGS_GET_RCODE(rep->flags) == + LDNS_RCODE_NOERROR || + FLAGS_GET_RCODE(rep->flags) == + LDNS_RCODE_NXDOMAIN) { + /* we have a good entry, + * don't overwrite */ + lock_rw_unlock(&msg->entry.lock); + return error_response(qstate, id, rcode); + } + lock_rw_unlock(&msg->entry.lock); + } + } memset(&err, 0, sizeof(err)); err.flags = (uint16_t)(BIT_QR | BIT_RA); -- 2.47.3