From: Wouter Wijngaards Date: Thu, 16 Feb 2012 11:04:53 +0000 (+0000) Subject: Fix prefetch and stickyness. X-Git-Tag: release-1.4.17rc1~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=773d8e3b84062fd4deb22e175e9d9b304aff8e75;p=thirdparty%2Funbound.git Fix prefetch and stickyness. git-svn-id: file:///svn/unbound/trunk@2632 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/cachedump.c b/daemon/cachedump.c index 2c5bb5c26..988e24735 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, NULL)) { + if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL)) { log_warn("error out of memory"); return 0; } diff --git a/doc/Changelog b/doc/Changelog index 841cb9ac1..fcd1168e9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,10 @@ 16 February 2012: Wouter - iter_hints is now thread-owned in module env, and thus threadsafe. + - Fix prefetch and sticky NS, now the prefetch works. It picks + nameservers that 'would be valid in the future', and if this makes + the NS timeout, it updates that NS by asking delegation from the + parent again. If child NS has longer TTL, that TTL does not get + refreshed from the lookup to the child nameserver. 15 February 2012: Wouter - Fix forward-zone memory, uses malloc and frees original root dp. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 3a4939f68..ac0aa318f 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -419,11 +419,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, int pside, struct regional* region) { return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, - region); + pside, region); } int diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 6d2f862ac..f77240751 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -121,11 +121,13 @@ 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 pside: true if dp is parentside, thus message is 'fresh' and NS + * can be prefetch-updates. * @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, int pside, struct regional* region); /** diff --git a/iterator/iterator.c b/iterator/iterator.c index c8c358a9a..a9dd03016 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -259,7 +259,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, NULL)) { + if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL)) { log_err("error_response_cache: could not store error (nomem)"); } return error_response(qstate, id, rcode); @@ -1040,7 +1040,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, if(delname) iq->dp = dns_cache_find_delegation(qstate->env, delname, delnamelen, iq->qchase.qtype, iq->qchase.qclass, - qstate->region, &iq->deleg_msg, *qstate->env->now); + qstate->region, &iq->deleg_msg, + *qstate->env->now+qstate->prefetch_leeway); else iq->dp = NULL; /* If the cache has returned nothing, then we have a @@ -1258,7 +1259,8 @@ generate_parentside_target_query(struct module_qstate* qstate, } else { subiq->dp = dns_cache_find_delegation(qstate->env, name, namelen, qtype, qclass, subq->region, - &subiq->deleg_msg, *qstate->env->now); + &subiq->deleg_msg, + *qstate->env->now+subq->prefetch_leeway); /* if no dp, then it's from root, refetch unneeded */ if(subiq->dp) { subiq->dnssec_expected = iter_indicates_dnssec( @@ -1830,6 +1832,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, } if(!iter_dns_store(qstate->env, &iq->response->qinfo, iq->response->rep, 0, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, qstate->region)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* close down outstanding requests to be discarded */ @@ -1869,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, NULL)) + iq->response->rep, 1, 0, 0, NULL)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); if(iq->store_parent_NS) @@ -1955,7 +1958,9 @@ 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, NULL)) + iq->response->rep, 1, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, + NULL)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); /* set the current request's qname to the new value. */ iq->qchase.qname = sname; @@ -2432,6 +2437,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, if(qstate->query_flags&BIT_RD) { if(!iter_dns_store(qstate->env, &qstate->qinfo, iq->response->rep, 0, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, qstate->region)) return error_response(qstate, id, LDNS_RCODE_SERVFAIL); diff --git a/services/cache/dns.c b/services/cache/dns.c index a6778f6ce..6e99b7fa4 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -60,12 +60,15 @@ * updated with a new full TTL. * Type NS does not get this, because it must not be refreshed from the * child domain, but keep counting down properly. + * @param pside: if from parentside discovered NS, so that its NS is okay + * in a prefetch situation to be updated (without becoming sticky). * @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, - uint32_t leeway, struct reply_info* qrep, struct regional* region) + uint32_t leeway, int pside, struct reply_info* qrep, + struct regional* region) { size_t i; /* see if rrset already exists in cache, if not insert it. */ @@ -75,7 +78,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now, /* update ref if it was in the cache */ switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)== - LDNS_RR_TYPE_NS)?0:leeway))) { + LDNS_RR_TYPE_NS && !pside)?0:leeway))) { case 0: /* ref unchanged, item inserted */ break; case 2: /* ref updated, cache is superior */ @@ -102,7 +105,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now, 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, int pside, struct reply_info* qrep, struct regional* region) { struct msgreply_entry* e; @@ -118,7 +121,7 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, /* 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, qrep, region); + store_rrsets(env, rep, *env->now, leeway, pside, qrep, region); if(ttl == 0) { /* we do not store the message, but we did store the RRs, * which could be useful for delegation information */ @@ -736,7 +739,7 @@ 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, int pside, struct regional* region) { struct reply_info* rep = NULL; @@ -761,8 +764,8 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, /* no leeway for typeNS */ (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, *env->now + - ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS)? - 0:leeway)); + ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS + && !pside) ? 0:leeway)); } free(rep); return 1; @@ -783,7 +786,8 @@ 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, msgrep, region); + dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, 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 76705ab7f..bc9f57c9c 100644 --- a/services/cache/dns.h +++ b/services/cache/dns.h @@ -74,12 +74,15 @@ 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 pside: if true, information came from a server which was fetched + * from the parentside of the zonecut. This means that the type NS + * can be updated to full TTL even in prefetch situations. * @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, int pside, struct regional* region); /** @@ -95,11 +98,14 @@ 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 pside: if true, information came from a server which was fetched + * from the parentside of the zonecut. This means that the type NS + * can be updated to full TTL even in prefetch situations. * @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, int pside, struct reply_info* qrep, struct regional* region); /** diff --git a/testdata/iter_prefetch.rpl b/testdata/iter_prefetch.rpl index efd63a59d..678bdd79d 100644 --- a/testdata/iter_prefetch.rpl +++ b/testdata/iter_prefetch.rpl @@ -217,8 +217,8 @@ www.example.com. IN A SECTION ANSWER www.example.com. 3600 IN A 10.20.30.40 SECTION AUTHORITY -; NS rrset TTL not updated to avoid sticky-NS (ghost domain) problem. -example.com. 360 IN NS ns.example.com. +; NS rrset picked up from parent-NS (the child-NS timed out at now+prefetch) +example.com. 3600 IN NS ns.example.com. SECTION ADDITIONAL ns.example.com. 3600 IN A 1.2.3.4 ENTRY_END diff --git a/testdata/iter_prefetch_change2.rpl b/testdata/iter_prefetch_change2.rpl index 777454c98..93196d555 100644 --- a/testdata/iter_prefetch_change2.rpl +++ b/testdata/iter_prefetch_change2.rpl @@ -256,11 +256,11 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 300 IN A 10.1.1.1 +www.example.com. 86400 IN A 10.2.2.2 SECTION AUTHORITY -example.com. 30 IN NS old-ns.example.com. +example.com. 86400 IN NS new-ns.example.com. SECTION ADDITIONAL -old-ns.example.com. 300 IN A 192.168.0.1 +new-ns.example.com. 86400 IN A 172.16.0.1 ENTRY_END ; the NS record times out after 31 seconds. @@ -281,11 +281,11 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 86400 IN A 10.2.2.2 +www.example.com. 86369 IN A 10.2.2.2 SECTION AUTHORITY -example.com. 86400 IN NS new-ns.example.com. +example.com. 86369 IN NS new-ns.example.com. SECTION ADDITIONAL -new-ns.example.com. 86400 IN A 172.16.0.1 +new-ns.example.com. 86369 IN A 172.16.0.1 ENTRY_END ; a reply from cache @@ -303,11 +303,11 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 86400 IN A 10.2.2.2 +www.example.com. 86369 IN A 10.2.2.2 SECTION AUTHORITY -example.com. 86400 IN NS new-ns.example.com. +example.com. 86369 IN NS new-ns.example.com. SECTION ADDITIONAL -new-ns.example.com. 86400 IN A 172.16.0.1 +new-ns.example.com. 86369 IN A 172.16.0.1 ENTRY_END SCENARIO_END diff --git a/testdata/iter_prefetch_childns.rpl b/testdata/iter_prefetch_childns.rpl new file mode 100644 index 000000000..c2b72d62a --- /dev/null +++ b/testdata/iter_prefetch_childns.rpl @@ -0,0 +1,227 @@ +; 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 from child nameserver +; child NS record has longer TTL than A record and is thus valid for prefetch. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + 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 qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.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. +RANGE_BEGIN 0 100 + 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 qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +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. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; after 900 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 900 + +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. 900 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 2700 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 2700 IN A 1.2.3.4 +ENTRY_END + +; after 720 we are 180 seconds before the expiry +; (the authority changes behind the scenes to detect new lookup) +STEP 50 TIME_PASSES ELAPSE 720 + +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. 180 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 1980 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1980 IN A 1.2.3.4 +ENTRY_END +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; above a cache reply with 10% of the original TTL +; but the actual cache is changed, try to get that +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. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +; The NS rrset (from the child-side NS) is not updated but keeps counting down +example.com. 1980 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1980 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch_ns.rpl b/testdata/iter_prefetch_ns.rpl index 0cc528f88..3dcda608c 100644 --- a/testdata/iter_prefetch_ns.rpl +++ b/testdata/iter_prefetch_ns.rpl @@ -26,11 +26,11 @@ K.ROOT-SERVERS.NET. IN A 193.0.14.129 ENTRY_END ENTRY_BEGIN -MATCH opcode qtype qname -ADJUST copy_id +MATCH opcode subdomain +ADJUST copy_id copy_query REPLY QR NOERROR SECTION QUESTION -www.example.com. IN A +example.com. IN A SECTION AUTHORITY com. IN NS a.gtld-servers.net. SECTION ADDITIONAL @@ -273,6 +273,8 @@ SECTION QUESTION example.com. IN NS ENTRY_END ; recursion happens here. + +; because the prefetch+current makes old-NS expired, new delegation is picked up STEP 91 CHECK_ANSWER ENTRY_BEGIN MATCH all ttl @@ -280,19 +282,14 @@ REPLY QR RD RA NOERROR SECTION QUESTION example.com. IN NS SECTION ANSWER -; this record is unchanged even though it now points to the -; new registrant. Thus it keeps counting down. -example.com. 360 IN NS ns.example.com. +example.com. 3600 IN NS ns.example.com. SECTION AUTHORITY SECTION ADDITIONAL ns.example.com. 3600 IN A 8.8.8.8 ENTRY_END - -; after 360 + 2000 we are after the change to new owner. STEP 100 TIME_PASSES ELAPSE 2360 -; the NS record should have timed out. STEP 120 QUERY ENTRY_BEGIN REPLY RD @@ -309,7 +306,7 @@ 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. 1240 IN A 8.8.8.8 ENTRY_END diff --git a/validator/validator.c b/validator/validator.c index 19e1f9006..af1d344a6 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -1977,15 +1977,17 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, /* store results in cache */ if(qstate->query_flags&BIT_RD) { + /* if secure, this will override cache anyway, no need + * to check if from parentNS */ if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, - vq->orig_msg->rep, 0, qstate->prefetch_leeway, NULL)) { + vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, 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, NULL)) { + vq->orig_msg->rep, 1, 0, 0, NULL)) { log_err("out of memory caching validator results"); } }