Fix prefetch and stickyness.

git-svn-id: file:///svn/unbound/trunk@2632 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2012-02-16 11:04:53 +00:00
parent 682ff957ed
commit 773d8e3b84
12 changed files with 291 additions and 42 deletions

View file

@ -765,7 +765,7 @@ load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker)
if(!go_on) if(!go_on)
return 1; /* skip this one, not all references satisfied */ 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"); log_warn("error out of memory");
return 0; return 0;
} }

View file

@ -1,5 +1,10 @@
16 February 2012: Wouter 16 February 2012: Wouter
- iter_hints is now thread-owned in module env, and thus threadsafe. - 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 15 February 2012: Wouter
- Fix forward-zone memory, uses malloc and frees original root dp. - Fix forward-zone memory, uses malloc and frees original root dp.

View file

@ -419,11 +419,11 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
int int
iter_dns_store(struct module_env* env, struct query_info* msgqinf, 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) struct regional* region)
{ {
return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
region); pside, region);
} }
int int

View file

@ -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 * @param is_referral: If true, then the given message to be stored is a
* referral. The cache implementation may use this as a hint. * referral. The cache implementation may use this as a hint.
* @param leeway: prefetch TTL leeway to expire old rrsets quicker. * @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. * @param region: to copy modified (cache is better) rrs back to.
* @return 0 on alloc error (out of memory). * @return 0 on alloc error (out of memory).
*/ */
int iter_dns_store(struct module_env* env, struct query_info* qinf, 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); struct regional* region);
/** /**

View file

@ -259,7 +259,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
/* do not waste time trying to validate this servfail */ /* do not waste time trying to validate this servfail */
err.security = sec_status_indeterminate; err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache"); 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)"); log_err("error_response_cache: could not store error (nomem)");
} }
return error_response(qstate, id, rcode); return error_response(qstate, id, rcode);
@ -1040,7 +1040,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
if(delname) if(delname)
iq->dp = dns_cache_find_delegation(qstate->env, delname, iq->dp = dns_cache_find_delegation(qstate->env, delname,
delnamelen, iq->qchase.qtype, iq->qchase.qclass, 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; else iq->dp = NULL;
/* If the cache has returned nothing, then we have a /* If the cache has returned nothing, then we have a
@ -1258,7 +1259,8 @@ generate_parentside_target_query(struct module_qstate* qstate,
} else { } else {
subiq->dp = dns_cache_find_delegation(qstate->env, subiq->dp = dns_cache_find_delegation(qstate->env,
name, namelen, qtype, qclass, subq->region, 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 no dp, then it's from root, refetch unneeded */
if(subiq->dp) { if(subiq->dp) {
subiq->dnssec_expected = iter_indicates_dnssec( 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, if(!iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway, iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region)) qstate->region))
return error_response(qstate, id, LDNS_RCODE_SERVFAIL); return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
/* close down outstanding requests to be discarded */ /* 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 */ /* Store the referral under the current query */
/* no prefetch-leeway, since its not the answer */ /* no prefetch-leeway, since its not the answer */
if(!iter_dns_store(qstate->env, &iq->response->qinfo, 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, return error_response(qstate, id,
LDNS_RCODE_SERVFAIL); LDNS_RCODE_SERVFAIL);
if(iq->store_parent_NS) if(iq->store_parent_NS)
@ -1955,7 +1958,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* the partial query answer (CNAME only). */ * the partial query answer (CNAME only). */
/* prefetchleeway applied because this updates answer parts */ /* prefetchleeway applied because this updates answer parts */
if(!iter_dns_store(qstate->env, &iq->response->qinfo, 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); return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
/* set the current request's qname to the new value. */ /* set the current request's qname to the new value. */
iq->qchase.qname = sname; iq->qchase.qname = sname;
@ -2432,6 +2437,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
if(qstate->query_flags&BIT_RD) { if(qstate->query_flags&BIT_RD) {
if(!iter_dns_store(qstate->env, &qstate->qinfo, if(!iter_dns_store(qstate->env, &qstate->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway, iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region)) qstate->region))
return error_response(qstate, id, return error_response(qstate, id,
LDNS_RCODE_SERVFAIL); LDNS_RCODE_SERVFAIL);

20
services/cache/dns.c vendored
View file

@ -60,12 +60,15 @@
* updated with a new full TTL. * updated with a new full TTL.
* Type NS does not get this, because it must not be refreshed from the * Type NS does not get this, because it must not be refreshed from the
* child domain, but keep counting down properly. * 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 qrep: update rrsets here if cache is better
* @param region: for qrep allocs. * @param region: for qrep allocs.
*/ */
static void 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,
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; size_t i;
/* see if rrset already exists in cache, if not insert it. */ /* 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 */ /* update ref if it was in the cache */
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)== 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 */ case 0: /* ref unchanged, item inserted */
break; break;
case 2: /* ref updated, cache is superior */ 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 void
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, 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 reply_info* qrep, struct regional* region)
{ {
struct msgreply_entry* e; 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 /* there was a reply_info_sortref(rep) here but it seems to be
* unnecessary, because the cache gets locked per rrset. */ * unnecessary, because the cache gets locked per rrset. */
reply_info_set_ttls(rep, *env->now); 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) { if(ttl == 0) {
/* we do not store the message, but we did store the RRs, /* we do not store the message, but we did store the RRs,
* which could be useful for delegation information */ * which could be useful for delegation information */
@ -736,7 +739,7 @@ dns_cache_lookup(struct module_env* env,
int int
dns_cache_store(struct module_env* env, struct query_info* msgqinf, 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 regional* region)
{ {
struct reply_info* rep = NULL; struct reply_info* rep = NULL;
@ -761,8 +764,8 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
/* no leeway for typeNS */ /* no leeway for typeNS */
(void)rrset_cache_update(env->rrset_cache, &ref, (void)rrset_cache_update(env->rrset_cache, &ref,
env->alloc, *env->now + env->alloc, *env->now +
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS)? ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
0:leeway)); && !pside) ? 0:leeway));
} }
free(rep); free(rep);
return 1; 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_RA | BIT_QR);
rep->flags &= ~(BIT_AA | BIT_CD); rep->flags &= ~(BIT_AA | BIT_CD);
h = query_info_hash(&qinf); 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 /* qname is used inside query_info_entrysetup, and set to
* NULL. If it has not been used, free it. free(0) is safe. */ * NULL. If it has not been used, free it. free(0) is safe. */
free(qinf.qname); free(qinf.qname);

10
services/cache/dns.h vendored
View file

@ -74,12 +74,15 @@ struct dns_msg {
* It will store only the RRsets, not the message. * It will store only the RRsets, not the message.
* @param leeway: TTL value, if not 0, other rrsets are considered expired * @param leeway: TTL value, if not 0, other rrsets are considered expired
* that many seconds before actual TTL expiry. * 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. * @param region: region to allocate better entries from cache into.
* (used when is_referral is false). * (used when is_referral is false).
* @return 0 on alloc error (out of memory). * @return 0 on alloc error (out of memory).
*/ */
int dns_cache_store(struct module_env* env, struct query_info* qinf, 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); 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. * Adjusts the reply info TTLs to absolute time.
* @param leeway: TTL value, if not 0, other rrsets are considered expired * @param leeway: TTL value, if not 0, other rrsets are considered expired
* that many seconds before actual TTL expiry. * 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 qrep: message that can be altered with better rrs from cache.
* @param region: to allocate into for qmsg. * @param region: to allocate into for qmsg.
*/ */
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, 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 reply_info* qrep, struct regional* region);
/** /**

View file

@ -217,8 +217,8 @@ www.example.com. IN A
SECTION ANSWER SECTION ANSWER
www.example.com. 3600 IN A 10.20.30.40 www.example.com. 3600 IN A 10.20.30.40
SECTION AUTHORITY SECTION AUTHORITY
; NS rrset TTL not updated to avoid sticky-NS (ghost domain) problem. ; NS rrset picked up from parent-NS (the child-NS timed out at now+prefetch)
example.com. 360 IN NS ns.example.com. example.com. 3600 IN NS ns.example.com.
SECTION ADDITIONAL SECTION ADDITIONAL
ns.example.com. 3600 IN A 1.2.3.4 ns.example.com. 3600 IN A 1.2.3.4
ENTRY_END ENTRY_END

View file

@ -256,11 +256,11 @@ REPLY QR RD RA NOERROR
SECTION QUESTION SECTION QUESTION
www.example.com. IN A www.example.com. IN A
SECTION ANSWER SECTION ANSWER
www.example.com. 300 IN A 10.1.1.1 www.example.com. 86400 IN A 10.2.2.2
SECTION AUTHORITY SECTION AUTHORITY
example.com. 30 IN NS old-ns.example.com. example.com. 86400 IN NS new-ns.example.com.
SECTION ADDITIONAL 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 ENTRY_END
; the NS record times out after 31 seconds. ; the NS record times out after 31 seconds.
@ -281,11 +281,11 @@ REPLY QR RD RA NOERROR
SECTION QUESTION SECTION QUESTION
www.example.com. IN A www.example.com. IN A
SECTION ANSWER SECTION ANSWER
www.example.com. 86400 IN A 10.2.2.2 www.example.com. 86369 IN A 10.2.2.2
SECTION AUTHORITY SECTION AUTHORITY
example.com. 86400 IN NS new-ns.example.com. example.com. 86369 IN NS new-ns.example.com.
SECTION ADDITIONAL 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 ENTRY_END
; a reply from cache ; a reply from cache
@ -303,11 +303,11 @@ REPLY QR RD RA NOERROR
SECTION QUESTION SECTION QUESTION
www.example.com. IN A www.example.com. IN A
SECTION ANSWER SECTION ANSWER
www.example.com. 86400 IN A 10.2.2.2 www.example.com. 86369 IN A 10.2.2.2
SECTION AUTHORITY SECTION AUTHORITY
example.com. 86400 IN NS new-ns.example.com. example.com. 86369 IN NS new-ns.example.com.
SECTION ADDITIONAL 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 ENTRY_END
SCENARIO_END SCENARIO_END

227
testdata/iter_prefetch_childns.rpl vendored Normal file
View file

@ -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

View file

@ -26,11 +26,11 @@ K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END ENTRY_END
ENTRY_BEGIN ENTRY_BEGIN
MATCH opcode qtype qname MATCH opcode subdomain
ADJUST copy_id ADJUST copy_id copy_query
REPLY QR NOERROR REPLY QR NOERROR
SECTION QUESTION SECTION QUESTION
www.example.com. IN A example.com. IN A
SECTION AUTHORITY SECTION AUTHORITY
com. IN NS a.gtld-servers.net. com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL SECTION ADDITIONAL
@ -273,6 +273,8 @@ SECTION QUESTION
example.com. IN NS example.com. IN NS
ENTRY_END ENTRY_END
; recursion happens here. ; recursion happens here.
; because the prefetch+current makes old-NS expired, new delegation is picked up
STEP 91 CHECK_ANSWER STEP 91 CHECK_ANSWER
ENTRY_BEGIN ENTRY_BEGIN
MATCH all ttl MATCH all ttl
@ -280,19 +282,14 @@ REPLY QR RD RA NOERROR
SECTION QUESTION SECTION QUESTION
example.com. IN NS example.com. IN NS
SECTION ANSWER SECTION ANSWER
; this record is unchanged even though it now points to the example.com. 3600 IN NS ns.example.com.
; new registrant. Thus it keeps counting down.
example.com. 360 IN NS ns.example.com.
SECTION AUTHORITY SECTION AUTHORITY
SECTION ADDITIONAL SECTION ADDITIONAL
ns.example.com. 3600 IN A 8.8.8.8 ns.example.com. 3600 IN A 8.8.8.8
ENTRY_END ENTRY_END
; after 360 + 2000 we are after the change to new owner.
STEP 100 TIME_PASSES ELAPSE 2360 STEP 100 TIME_PASSES ELAPSE 2360
; the NS record should have timed out.
STEP 120 QUERY STEP 120 QUERY
ENTRY_BEGIN ENTRY_BEGIN
REPLY RD REPLY RD
@ -309,7 +306,7 @@ www.example.com. IN A
SECTION ANSWER SECTION ANSWER
www.example.com. 3600 IN A 88.88.88.88 www.example.com. 3600 IN A 88.88.88.88
SECTION AUTHORITY SECTION AUTHORITY
example.com. 3600 IN NS ns.example.com. example.com. 1240 IN NS ns.example.com.
SECTION ADDITIONAL SECTION ADDITIONAL
ns.example.com. 1240 IN A 8.8.8.8 ns.example.com. 1240 IN A 8.8.8.8
ENTRY_END ENTRY_END

View file

@ -1977,15 +1977,17 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
/* store results in cache */ /* store results in cache */
if(qstate->query_flags&BIT_RD) { 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, 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"); log_err("out of memory caching validator results");
} }
} else { } else {
/* for a referral, store the verified RRsets */ /* for a referral, store the verified RRsets */
/* and this does not get prefetched, so no leeway */ /* and this does not get prefetched, so no leeway */
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, 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"); log_err("out of memory caching validator results");
} }
} }