From: Wouter Wijngaards Date: Tue, 10 Jan 2012 09:42:32 +0000 (+0000) Subject: - Fix bug #425: unbound reports wrong TTL in reply, it reports a TTL X-Git-Tag: release-1.4.15rc1~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6dd2c0467e6dea554489e448c2108f969ba7a036;p=thirdparty%2Funbound.git - Fix bug #425: unbound reports wrong TTL in reply, it reports a TTL that would be permissible by the RFCs but it is not the TTL in the cache. git-svn-id: file:///svn/unbound/trunk@2581 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/cachedump.c b/daemon/cachedump.c index 41a15e266..e5be8564e 100644 --- a/daemon/cachedump.c +++ b/daemon/cachedump.c @@ -765,7 +765,7 @@ load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker) if(!go_on) return 1; /* skip this one, not all references satisfied */ - if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0)) { + if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, NULL)) { log_warn("error out of memory"); return 0; } diff --git a/doc/Changelog b/doc/Changelog index 307d2ccbd..ea9d05443 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +10 January 2012: Wouter + - Fix bug #425: unbound reports wrong TTL in reply, it reports a TTL + that would be permissible by the RFCs but it is not the TTL in the + cache. + 2 January 2012: Wouter - Fix to randomize hash function, based on 28c3 congress, reported by Peter van Dijk. diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c index aa6d6450d..6147c96a9 100644 --- a/iterator/iter_scrub.c +++ b/iterator/iter_scrub.c @@ -535,8 +535,7 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env, ref.key = k; ref.id = k->id; /*ignore ret: it was in the cache, ref updated */ - (void)rrset_cache_update(env->rrset_cache, &ref, - env->alloc, now); + (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now); } /** Check if there are SOA records in the authority section (negative) */ diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index ee04339ee..25fda5eb3 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -425,9 +425,11 @@ dns_copy_msg(struct dns_msg* from, struct regional* region) int iter_dns_store(struct module_env* env, struct query_info* msgqinf, - struct reply_info* msgrep, int is_referral, uint32_t leeway) + struct reply_info* msgrep, int is_referral, uint32_t leeway, + struct regional* region) { - return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway); + return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, + region); } int diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index d048ad8a2..6d2f862ac 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -121,10 +121,12 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional); * @param is_referral: If true, then the given message to be stored is a * referral. The cache implementation may use this as a hint. * @param leeway: prefetch TTL leeway to expire old rrsets quicker. + * @param region: to copy modified (cache is better) rrs back to. * @return 0 on alloc error (out of memory). */ int iter_dns_store(struct module_env* env, struct query_info* qinf, - struct reply_info* rep, int is_referral, uint32_t leeway); + struct reply_info* rep, int is_referral, uint32_t leeway, + struct regional* region); /** * Select randomly with n/m probability. diff --git a/iterator/iterator.c b/iterator/iterator.c index efe1bcec6..432fdc477 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -260,7 +260,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode) /* do not waste time trying to validate this servfail */ err.security = sec_status_indeterminate; verbose(VERB_ALGO, "store error response in message cache"); - if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0)) { + if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, NULL)) { log_err("error_response_cache: could not store error (nomem)"); } return error_response(qstate, id, rcode); @@ -1832,7 +1832,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, "nodata ANSWER")); } if(!iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 0, qstate->prefetch_leeway)) + iq->response->rep, 0, qstate->prefetch_leeway, + qstate->region)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* close down outstanding requests to be discarded */ outbound_list_clear(&iq->outlist); @@ -1871,7 +1872,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* Store the referral under the current query */ /* no prefetch-leeway, since its not the answer */ if(!iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 1, 0)) + iq->response->rep, 1, 0, NULL)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); if(iq->store_parent_NS) @@ -1957,7 +1958,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, * the partial query answer (CNAME only). */ /* prefetchleeway applied because this updates answer parts */ if(!iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 1, qstate->prefetch_leeway)) + iq->response->rep, 1, qstate->prefetch_leeway, NULL)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* set the current request's qname to the new value. */ iq->qchase.qname = sname; @@ -2433,7 +2434,8 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, * from cache does not need to be stored in the msg cache. */ if(qstate->query_flags&BIT_RD) { if(!iter_dns_store(qstate->env, &qstate->qinfo, - iq->response->rep, 0, qstate->prefetch_leeway)) + iq->response->rep, 0, qstate->prefetch_leeway, + qstate->region)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } diff --git a/pythonmod/pythonmod_utils.c b/pythonmod/pythonmod_utils.c index bd0ef3708..52cfad0a6 100644 --- a/pythonmod/pythonmod_utils.c +++ b/pythonmod/pythonmod_utils.c @@ -66,7 +66,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, st } return dns_cache_store(qstate->env, qinfo, msgrep, is_referral, - qstate->prefetch_leeway); + qstate->prefetch_leeway, NULL); } /* Invalidate the message associated with query_info stored in message cache */ diff --git a/services/cache/dns.c b/services/cache/dns.c index 2fb8a6436..49234ab41 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -55,24 +55,49 @@ * @param env: module environment with caches. * @param rep: contains list of rrsets to store. * @param now: current time. + * @param qrep: update rrsets here if cache is better + * @param region: for qrep allocs. */ static void -store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now) +store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now, + struct reply_info* qrep, struct regional* region) { size_t i; /* see if rrset already exists in cache, if not insert it. */ for(i=0; irrset_count; i++) { rep->ref[i].key = rep->rrsets[i]; rep->ref[i].id = rep->rrsets[i]->id; - if(rrset_cache_update(env->rrset_cache, &rep->ref[i], - env->alloc, now)) /* it was in the cache */ + /* update ref if it was in the cache */ + switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], + env->alloc, now)) { + case 0: /* ref unchanged, item inserted */ + break; + case 2: /* ref updated, cache is superior */ + if(region) { + struct ub_packed_rrset_key* ck; + lock_rw_rdlock(&rep->ref[i].key->entry.lock); + /* if deleted rrset, do not copy it */ + if(rep->ref[i].key->id == 0) + ck = NULL; + else ck = packed_rrset_copy_region( + rep->ref[i].key, region, now); + lock_rw_unlock(&rep->ref[i].key->entry.lock); + if(ck) { + /* use cached copy if memory allows */ + qrep->rrsets[i] = ck; + } + } + /* no break: also copy key item */ + case 1: /* ref updated, item inserted */ rep->rrsets[i] = rep->ref[i].key; + } } } void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, - hashvalue_t hash, struct reply_info* rep, uint32_t leeway) + hashvalue_t hash, struct reply_info* rep, uint32_t leeway, + struct reply_info* qrep, struct regional* region) { struct msgreply_entry* e; uint32_t ttl = rep->ttl; @@ -83,9 +108,11 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, rep->ref[i].key = rep->rrsets[i]; rep->ref[i].id = rep->rrsets[i]->id; } - reply_info_sortref(rep); + + /* there was a reply_info_sortref(rep) here but it seems to be + * unnecessary, because the cache gets locked per rrset. */ reply_info_set_ttls(rep, *env->now); - store_rrsets(env, rep, *env->now+leeway); + store_rrsets(env, rep, *env->now+leeway, qrep, region); if(ttl == 0) { /* we do not store the message, but we did store the RRs, * which could be useful for delegation information */ @@ -703,7 +730,8 @@ 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, uint32_t leeway) + struct reply_info* msgrep, int is_referral, uint32_t leeway, + struct regional* region) { struct reply_info* rep = NULL; /* alloc, malloc properly (not in region, like msg is) */ @@ -746,7 +774,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, rep->flags |= (BIT_RA | BIT_QR); rep->flags &= ~(BIT_AA | BIT_CD); h = query_info_hash(&qinf); - dns_cache_store_msg(env, &qinf, h, rep, leeway); + dns_cache_store_msg(env, &qinf, h, rep, leeway, msgrep, region); /* qname is used inside query_info_entrysetup, and set to * NULL. If it has not been used, free it. free(0) is safe. */ free(qinf.qname); diff --git a/services/cache/dns.h b/services/cache/dns.h index 561e13d64..76705ab7f 100644 --- a/services/cache/dns.h +++ b/services/cache/dns.h @@ -74,10 +74,13 @@ struct dns_msg { * It will store only the RRsets, not the message. * @param leeway: TTL value, if not 0, other rrsets are considered expired * that many seconds before actual TTL expiry. + * @param region: region to allocate better entries from cache into. + * (used when is_referral is false). * @return 0 on alloc error (out of memory). */ int dns_cache_store(struct module_env* env, struct query_info* qinf, - struct reply_info* rep, int is_referral, uint32_t leeway); + struct reply_info* rep, int is_referral, uint32_t leeway, + struct regional* region); /** * Store message in the cache. Stores in message cache and rrset cache. @@ -92,9 +95,12 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf, * Adjusts the reply info TTLs to absolute time. * @param leeway: TTL value, if not 0, other rrsets are considered expired * that many seconds before actual TTL expiry. + * @param qrep: message that can be altered with better rrs from cache. + * @param region: to allocate into for qmsg. */ void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, - hashvalue_t hash, struct reply_info* rep, uint32_t leeway); + hashvalue_t hash, struct reply_info* rep, uint32_t leeway, + struct reply_info* qrep, struct regional* region); /** * Find a delegation from the cache. diff --git a/services/cache/rrset.c b/services/cache/rrset.c index 33660f89f..92447317d 100644 --- a/services/cache/rrset.c +++ b/services/cache/rrset.c @@ -207,7 +207,7 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, /* cache is superior, return that value */ lock_rw_unlock(&e->lock); ub_packed_rrset_parsedelete(k, alloc); - return 1; + return 2; } lock_rw_unlock(&e->lock); /* Go on and insert the passed item. diff --git a/services/cache/rrset.h b/services/cache/rrset.h index e414107d2..f1c34d67a 100644 --- a/services/cache/rrset.h +++ b/services/cache/rrset.h @@ -125,6 +125,9 @@ void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key, * @param alloc: how to allocate (and deallocate) the special rrset key. * @param timenow: current time (to see if ttl in cache is expired). * @return: true if the passed reference is updated, false if it is unchanged. + * 0: reference unchanged, inserted in cache. + * 1: reference updated, item is inserted in cache. + * 2: reference updated, item in cache is considered superior. */ int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, struct alloc_cache* alloc, uint32_t timenow); diff --git a/testdata/iter_domain_sale.rpl b/testdata/iter_domain_sale.rpl index cc46bce99..724b51dad 100644 --- a/testdata/iter_domain_sale.rpl +++ b/testdata/iter_domain_sale.rpl @@ -239,9 +239,9 @@ nx1.example.com. IN A SECTION ANSWER SECTION AUTHORITY example.com. 3600 IN SOA a. b. 1 2 3 4 5 -example.com. 3600 IN NS ns.example.com. +example.com. 1800 IN NS ns.example.com. SECTION ADDITIONAL -ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 1800 IN A 1.2.3.4 ENTRY_END ; after another 1900 seconds the domain must have timed out. diff --git a/testdata/iter_prefetch_change.rpl b/testdata/iter_prefetch_change.rpl new file mode 100644 index 000000000..2ed70cdad --- /dev/null +++ b/testdata/iter_prefetch_change.rpl @@ -0,0 +1,364 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: "yes" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver prefetch and a moved domain +; for bug #425. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 500 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (before sale of domain) +RANGE_BEGIN 0 30 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (after sale of domain) +RANGE_BEGIN 40 500 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END +RANGE_END + +; ns.example.com. first owner +RANGE_BEGIN 0 500 + ADDRESS 192.168.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END +RANGE_END + +; ns.example.com. new owner +RANGE_BEGIN 0 500 + ADDRESS 172.16.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +old-ns.example.com. IN A +SECTION ANSWER +old-ns.example.com. 86400 IN A 172.16.0.1 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END + +; after 1800 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 1800 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 84600 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 84600 IN A 192.168.0.1 +ENTRY_END + +; after 1440 we are 360 seconds before the expiry +; but it still contacts the old-ns +STEP 50 TIME_PASSES ELAPSE 1440 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 360 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 83160 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 83160 IN A 192.168.0.1 +ENTRY_END + +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; we updated from the old-ns. +STEP 90 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 100 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 83160 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 83160 IN A 192.168.0.1 +ENTRY_END + +; the NS record is now 10% from expiry (8640 TTL left). +; and the A record has expired completely, retry. +STEP 110 TIME_PASSES ELAPSE 74520 + +; the NS record should have timed out. +; but you see the full TTL here, this is only for *this query* +; in the cache itself its 8640, not 86400. +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 8640 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 8640 IN A 192.168.0.1 +ENTRY_END + +; get it from cache +STEP 140 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 150 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 8640 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 8640 IN A 192.168.0.1 +ENTRY_END + +; the NS record times out after 8640 seconds. +STEP 160 TIME_PASSES ELAPSE 8641 + +; fetch it +STEP 170 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 180 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +; a reply from cache +STEP 190 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 200 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch_ns.rpl b/testdata/iter_prefetch_ns.rpl index c0ffdb86c..219e48396 100644 --- a/testdata/iter_prefetch_ns.rpl +++ b/testdata/iter_prefetch_ns.rpl @@ -285,9 +285,9 @@ www.example.com. IN A SECTION ANSWER www.example.com. 3600 IN A 88.88.88.88 SECTION AUTHORITY -example.com. 3600 IN NS ns.example.com. +example.com. 1240 IN NS ns.example.com. SECTION ADDITIONAL -ns.example.com. 3600 IN A 8.8.8.8 +ns.example.com. 820 IN A 8.8.8.8 ENTRY_END SCENARIO_END diff --git a/testdata/rrset_rettl.rpl b/testdata/rrset_rettl.rpl index b7e05eb85..2ae64e947 100644 --- a/testdata/rrset_rettl.rpl +++ b/testdata/rrset_rettl.rpl @@ -85,7 +85,7 @@ ENTRY_BEGIN SECTION ANSWER bla.example.com. IN A 10.20.30.140 SECTION AUTHORITY - example.com. 200 IN NS ns.example.com. + example.com. 100 IN NS ns.example.com. SECTION ADDITIONAL ns.example.com. IN A 10.20.30.50 ENTRY_END diff --git a/validator/validator.c b/validator/validator.c index 0ac593d82..c05a8cf97 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -1978,14 +1978,14 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, /* store results in cache */ if(qstate->query_flags&BIT_RD) { if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, - vq->orig_msg->rep, 0, qstate->prefetch_leeway)) { + vq->orig_msg->rep, 0, qstate->prefetch_leeway, NULL)) { log_err("out of memory caching validator results"); } } else { /* 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)) { + vq->orig_msg->rep, 1, 0, NULL)) { log_err("out of memory caching validator results"); } }