From: Wouter Wijngaards Date: Tue, 14 Feb 2012 11:06:44 +0000 (+0000) Subject: - Fix sticky NS (ghost domain problem) if prefetch is yes. X-Git-Tag: release-1.4.17rc1~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03a7425eadc1cb12408c97c6a214dd4cdf83797b;p=thirdparty%2Funbound.git - Fix sticky NS (ghost domain problem) if prefetch is yes. git-svn-id: file:///svn/unbound/trunk@2619 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 19c8ac57e..fb3a32282 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +14 February 2012: Wouter + - Fix sticky NS (ghost domain problem) if prefetch is yes. + 13 February 2012: Wouter - RT#2955. Fix for cygwin compilation. - iana portlist updated. diff --git a/services/cache/dns.c b/services/cache/dns.c index 49234ab41..a6778f6ce 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -55,12 +55,17 @@ * @param env: module environment with caches. * @param rep: contains list of rrsets to store. * @param now: current time. + * @param leeway: during prefetch how much leeway to update TTLs. + * This makes rrsets (other than type NS) timeout sooner so they get + * 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 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, - struct reply_info* qrep, struct regional* region) + uint32_t leeway, struct reply_info* qrep, struct regional* region) { size_t i; /* see if rrset already exists in cache, if not insert it. */ @@ -69,7 +74,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now, rep->ref[i].id = rep->rrsets[i]->id; /* update ref if it was in the cache */ switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], - env->alloc, now)) { + env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)== + LDNS_RR_TYPE_NS)?0:leeway))) { case 0: /* ref unchanged, item inserted */ break; case 2: /* ref updated, cache is superior */ @@ -112,7 +118,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, qrep, region); if(ttl == 0) { /* we do not store the message, but we did store the RRs, * which could be useful for delegation information */ @@ -752,8 +758,11 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, ref.key = rep->rrsets[i]; ref.id = rep->rrsets[i]->id; /*ignore ret: it was in the cache, ref updated */ + /* no leeway for typeNS */ (void)rrset_cache_update(env->rrset_cache, &ref, - env->alloc, *env->now + leeway); + env->alloc, *env->now + + ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS)? + 0:leeway)); } free(rep); return 1; diff --git a/testdata/iter_prefetch.rpl b/testdata/iter_prefetch.rpl index f2b63a21d..efd63a59d 100644 --- a/testdata/iter_prefetch.rpl +++ b/testdata/iter_prefetch.rpl @@ -217,7 +217,8 @@ www.example.com. IN A SECTION ANSWER www.example.com. 3600 IN A 10.20.30.40 SECTION AUTHORITY -example.com. 3600 IN NS ns.example.com. +; NS rrset TTL not updated to avoid sticky-NS (ghost domain) problem. +example.com. 360 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 new file mode 100644 index 000000000..777454c98 --- /dev/null +++ b/testdata/iter_prefetch_change2.rpl @@ -0,0 +1,313 @@ +; 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 2. +; for slightly different query pattern. + +; 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. 300 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 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. 300 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 300 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 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. 86400 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. 300 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 300 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 IN A 192.168.0.1 +ENTRY_END + +; after 40 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 40 + +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. 260 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 260 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 260 IN A 192.168.0.1 +ENTRY_END + +; after 230 we are 30 seconds before expiry, prefetch happens. +STEP 50 TIME_PASSES ELAPSE 230 + +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. 30 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 30 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 30 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. 300 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 30 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 IN A 192.168.0.1 +ENTRY_END + +; the NS record times out after 31 seconds. +STEP 160 TIME_PASSES ELAPSE 31 + +; 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. 86400 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. 86400 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 219e48396..0cc528f88 100644 --- a/testdata/iter_prefetch_ns.rpl +++ b/testdata/iter_prefetch_ns.rpl @@ -11,7 +11,7 @@ CONFIG_END SCENARIO_BEGIN Test resolver prefetch of NS record for moved domain ; K.ROOT-SERVERS.NET. -RANGE_BEGIN 0 100 +RANGE_BEGIN 0 200 ADDRESS 193.0.14.129 ENTRY_BEGIN MATCH opcode qtype qname @@ -265,6 +265,30 @@ ENTRY_END STEP 80 TRAFFIC ; let traffic flow for prefetch to happen +; check result of that prefetch +STEP 90 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN NS +ENTRY_END +; recursion happens here. +STEP 91 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +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. +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 @@ -285,9 +309,9 @@ www.example.com. IN A SECTION ANSWER www.example.com. 3600 IN A 88.88.88.88 SECTION AUTHORITY -example.com. 1240 IN NS ns.example.com. +example.com. 3600 IN NS ns.example.com. SECTION ADDITIONAL -ns.example.com. 820 IN A 8.8.8.8 +ns.example.com. 1240 IN A 8.8.8.8 ENTRY_END SCENARIO_END