From: Wouter Wijngaards Date: Wed, 19 Sep 2007 12:17:42 +0000 (+0000) Subject: fixup glue timeout problems, and priming with safety belt. X-Git-Tag: release-0.5~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c968fc7581c4f860efe9eed223da2e86de7227b7;p=thirdparty%2Funbound.git fixup glue timeout problems, and priming with safety belt. git-svn-id: file:///svn/unbound/trunk@622 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 9ffc9c40d..bdd30189e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,10 @@ 19 September 2007: Wouter - comments about non-packed usage. - plan for overload support in 0.6. + - added testbound tests for a failed resolution from the logs + and for failed prime when missing glue. + - fixup so useless delegation points are not returned from the + cache. Also the safety belt is used if priming fails to complete. 18 September 2007: Wouter - wildcard nsec3 testcases, and fixup to get correct wildcard name. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index ac1d7c42e..ca64e7ddd 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -55,6 +55,7 @@ #include "util/config_file.h" #include "util/region-allocator.h" #include "util/data/msgparse.h" +#include "util/data/dname.h" #include "util/random.h" /** fillup fetch policy array */ @@ -320,3 +321,27 @@ iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) } } } + +int +iter_dp_is_useless(uint16_t flags, struct delegpt* dp) +{ + struct delegpt_ns* ns; + /* check: + * o all NS items are required glue. + * o no addresses are provided. + * o RD qflag is on. + */ + if(!(flags&BIT_RD)) + return 0; + /* either available or unused targets */ + if(dp->usable_list || dp->result_list) + return 0; + + for(ns = dp->nslist; ns; ns = ns->next) { + if(ns->resolved) /* skip failed targets */ + continue; + if(!dname_subdomain_c(ns->name, dp->name)) + return 0; /* one address is not required glue */ + } + return 1; +} diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 7e3a5ccab..f18adf614 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -128,4 +128,12 @@ int iter_ns_probability(struct ub_randstate* rnd, int n, int m); */ void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp); +/** + * See if delegation is useful or offers immediately no targets for + * further recursion. + * @param flags: query flags. + * @param dp: delegpt to check. + */ +int iter_dp_is_useless(uint16_t flags, struct delegpt* dp); + #endif /* ITERATOR_ITER_UTILS_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c index 091b4165c..462edcc63 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -484,6 +484,12 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_ALGO, "Cannot prime due to lack of hints"); return 0; } + /* copy dp; to avoid messing up available list for other thr/queries */ + dp = delegpt_copy(dp, qstate->region); + if(!dp) { + log_err("out of memory priming root, copydp"); + return 0; + } /* Priming requests start at the QUERYTARGETS state, skipping * the normal INIT state logic (which would cause an infloop). */ if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, @@ -550,7 +556,14 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, (struct iter_qstate*)subq->minfo[id]; /* Set the initial delegation point to the hint. */ - subiq->dp = stub_dp; + /* make copy to avoid use of stub dp by different qs/threads */ + subiq->dp = delegpt_copy(stub_dp, subq->region); + if(!subiq->dp) { + log_err("out of memory priming stub, copydp"); + (*qstate->env->kill_sub)(subq); + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); + return 1; /* return 1 to make module stop, with error */ + } /* there should not be any target queries -- although there * wouldn't be anyway, since stub hints never have * missing targets. */ @@ -704,29 +717,75 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, /* do not adjust root label, remove first label from delname */ dname_remove_label(&delname, &delnamelen); } - - /* Lookup the delegation in the cache. If null, then the cache needs - * to be primed for the qclass. */ - iq->dp = dns_cache_find_delegation(qstate->env, delname, delnamelen, - iq->qchase.qtype, iq->qchase.qclass, qstate->region, - &iq->deleg_msg, (uint32_t)time(NULL)); - - /* If the cache has returned nothing, then we have a root priming - * situation. */ - if(iq->dp == NULL) { - /* Note that the result of this will set a new - * DelegationPoint based on the result of priming. */ - if(!prime_root(qstate, iq, ie, id, iq->qchase.qclass)) - return error_response(qstate, id, LDNS_RCODE_REFUSED); - - /* priming creates and sends a subordinate query, with - * this query as the parent. So further processing for - * this event will stop until reactivated by the results - * of priming. */ - return 0; + while(1) { + + /* Lookup the delegation in the cache. If null, then the cache needs + * to be primed for the qclass. */ + iq->dp = dns_cache_find_delegation(qstate->env, delname, + delnamelen, iq->qchase.qtype, iq->qchase.qclass, + qstate->region, &iq->deleg_msg, (uint32_t)time(NULL)); + + /* If the cache has returned nothing, then we have a + * root priming situation. */ + if(iq->dp == NULL) { + /* Note that the result of this will set a new + * DelegationPoint based on the result of priming. */ + if(!prime_root(qstate, iq, ie, id, iq->qchase.qclass)) + return error_response(qstate, id, + LDNS_RCODE_REFUSED); + + /* priming creates and sends a subordinate query, with + * this query as the parent. So further processing for + * this event will stop until reactivated by the + * results of priming. */ + return 0; + } + + /* see if this dp not useless. + * It is useless if: + * o all NS items are required glue. + * o no addresses are provided. + * o RD qflag is on. + * Instead, go up one level, and try to get even further + * If the root was useless, use safety belt information. + * Only check cache returns, because replies for servers + * could be useless but lead to loops (bumping into the + * same server reply) if useless-checked. + */ + if(iter_dp_is_useless(qstate->query_flags, iq->dp)) { + if(dname_is_root(iq->dp->name)) { + /* use safety belt */ + verbose(VERB_OPS, "Priming problem: NS but " + "no addresses. Fallback to the safety belt."); + iq->dp = hints_lookup_root(ie->hints, + iq->qchase.qclass); + /* note deleg_msg is from previous lookup, + * but RD is on, so it is not used */ + if(!iq->dp) { + log_err("internal error: no hints dp"); + return error_response(qstate, id, + LDNS_RCODE_REFUSED); + } + iq->dp = delegpt_copy(iq->dp, qstate->region); + if(!iq->dp) { + log_err("out of memory in safety belt"); + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + break; + } else { + log_info("cache delegation was useless:"); + delegpt_log(iq->dp); + /* go up */ + delname = iq->dp->name; + delnamelen = iq->dp->namelen; + dname_remove_label(&delname, &delnamelen); + } + } else break; } + if(verbosity >= VERB_ALGO) { - log_info("dns_cache_find_delegation returns delegpt"); + log_info("cache delegation returns delegpt"); delegpt_log(iq->dp); } diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 2a7913e40..b1f86d285 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -815,6 +815,11 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, ldns_status status; (void)arg_compare; log_assert(pend); + log_nametypeclass(VERB_OPS, "pending serviced query", + qname, qtype, qclass); + verbose(VERB_OPS, "pending serviced query flags%s%s%s%s", + (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"", + (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":""); /* create packet with EDNS */ pend->buffer = ldns_buffer_new(512); @@ -856,7 +861,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, ldns_get_errorstr_by_id(status)); fatal_exit("internal error"); } - log_pkt("pending serviced query: ", pend->pkt); + /*log_pkt("pending serviced query: ", pend->pkt);*/ /* see if it matches the current moment */ if(runtime->now && runtime->now->evt_type == repevt_back_query && diff --git a/testdata/iter_emptydp.rpl b/testdata/iter_emptydp.rpl new file mode 100644 index 000000000..40c9e9c09 --- /dev/null +++ b/testdata/iter_emptydp.rpl @@ -0,0 +1,190 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with empty delegation from cache. + +; 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. + +; sneak in some data into the cache to simulate partial data after timeouts +example.net. NS ns.example.net. + +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. 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 +; com zone +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.net. +SECTION ADDITIONAL +ENTRY_END + +; net zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +; example.net. zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.com. zone +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +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 +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; make sure glue fetch is done. +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_primenoglue.rpl b/testdata/iter_primenoglue.rpl new file mode 100644 index 000000000..74227f2e8 --- /dev/null +++ b/testdata/iter_primenoglue.rpl @@ -0,0 +1,257 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with root prime answer without glue. + +; 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 +; glue ommitted! +;K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION AUTHORITY +net. 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 +com. IN NS a.gtld-servers.net. + +; sneak in some data into the cache to simulate partial data after timeouts +example.net. NS ns.example.net. + +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. 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 +; com zone +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.net. +SECTION ADDITIONAL +ENTRY_END + +; net zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION AUTHORITY +ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET. +SECTION ADDITIONAL +A.ROOT-SERVERS.NET. IN A 198.41.0.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; A.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 198.41.0.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +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 +K.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +; no ip6 address: we want to use only one address for K. to avoid having +; to duplicate the entries in this file for both addresses. +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +; example.net. zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.com. zone +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +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 +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; make sure glue fetch is done. +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 13 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +ENTRY_END + +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END