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.
#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 */
}
}
}
+
+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;
+}
*/
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 */
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,
(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. */
/* 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);
}
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);
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 &&
--- /dev/null
+; 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
--- /dev/null
+; 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