]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix lame server detection, for selfpointed glue records.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 20 May 2026 13:01:42 +0000 (15:01 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 20 May 2026 13:01:42 +0000 (15:01 +0200)
  Thanks to Shuhan Zhang, Dan Li, and Baojun Liu from Tsinghua
  University for the report.

17 files changed:
doc/Changelog
iterator/iter_resptype.c
iterator/iter_resptype.h
iterator/iter_scrub.c
iterator/iter_scrub.h
iterator/iterator.c
iterator/iterator.h
testdata/iter_privaddr.rpl
testdata/iter_resolve_minimised.rpl
testdata/iter_self_glue.rpl [new file with mode: 0644]
testdata/iter_self_glue_promisc.rpl [new file with mode: 0644]
testdata/local_ds.rpl
testdata/val_cnametonsec.rpl
testdata/val_cnametooptin.rpl
testdata/val_ds_cname.rpl
testdata/val_dsnsec.rpl
testdata/val_secds_nosig.rpl

index 58b86543516b68012dfd1c5e48bdb2c699a9593d..10f8e035185fd61943263883f922620cb7a51197 100644 (file)
@@ -38,6 +38,9 @@
        - Fix in depth for serve-expired responses from cachedb, that it
          does not store bogus. Thanks to Qifan Zhang, Palo Alto Networks,
          for the report.
+       - Fix lame server detection, for selfpointed glue records.
+         Thanks to Shuhan Zhang, Dan Li, and Baojun Liu from Tsinghua
+         University for the report.
 
 18 May 2026: Wouter
        - Fix for mixed class referrals, the resolver uses the query
index 38e186e79048eaf7a9214ad8fe0c9b6f168477d0..f16520b3eaade4b376d867dc122fc3fc5187aa1a 100644 (file)
@@ -107,7 +107,7 @@ response_type_from_cache(struct dns_msg* msg,
 enum response_type 
 response_type_from_server(int rdset,
        struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
-       int* empty_nodata_found)
+       int* empty_nodata_found, int msg_lame_empty, int msg_lame_referral)
 {
        uint8_t* origzone = (uint8_t*)"\000"; /* the default */
        struct ub_packed_rrset_key* s;
@@ -122,6 +122,10 @@ response_type_from_server(int rdset,
 
        /* If the message is NXDOMAIN, then it answers the question. */
        if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
+               if(msg->rep->an_numrrsets == 0 &&
+                       msg->rep->ns_numrrsets == 0 &&
+                       msg_lame_empty)
+                       return RESPONSE_TYPE_LAME;
                /* make sure its not recursive when we don't want it to */
                if( (msg->rep->flags&BIT_RA) &&
                        !(msg->rep->flags&BIT_AA) && !rdset)
@@ -143,6 +147,10 @@ response_type_from_server(int rdset,
        if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR)
                return RESPONSE_TYPE_THROWAWAY;
 
+       if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 &&
+               msg_lame_empty)
+               return RESPONSE_TYPE_LAME;
+
        /* Note: TC bit has already been handled */
 
        if(dp) {
@@ -249,13 +257,16 @@ response_type_from_server(int rdset,
                                 * which gives ns==zone delegation from cache 
                                 * without AA bit as well, with nodata nosoa*/
                                /* real answer must be +AA and SOA RFC(2308),
-                                * so this is wrong, and we SERVFAIL it if
-                                * this is the only possible reply, if it
-                                * is misdeployed the THROWAWAY makes us pick
-                                * the next server from the selection */
-                               if(msg->rep->an_numrrsets==0 &&
+                                * this is picked up as lame_referral by the
+                                * sanitize step, so it can spot if there
+                                * was data in the answer section before
+                                * removal. If such data is then removed we
+                                * do not want to turn that answer into lame.
+                                * But if it was not there, it can be lame. */
+                               if(msg_lame_referral &&
+                                       msg->rep->an_numrrsets==0 &&
                                        !(msg->rep->flags&BIT_AA) && !rdset)
-                                       return RESPONSE_TYPE_THROWAWAY;
+                                       return RESPONSE_TYPE_LAME;
                                return RESPONSE_TYPE_ANSWER;
                        }
                        /* If we are getting a referral upwards (or to 
index bfd4b664f62104dcdfd5f651ffbafd686982c7b1..73719abda875f68c1d90d90a0d7b169849c2c137 100644 (file)
@@ -120,10 +120,14 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
  * @param dp: The delegation point that was being queried
  *          when the response was returned.
  * @param empty_nodata_found: flag to keep track of empty nodata detection.
+ * @param msg_lame_empty: The scrubber indicates that this empty message
+ *     is lame, before it became empty.
+ * @param msg_lame_referral: returned true if the reply has a referral before
+ *     scrub.
  * @return the response type (CNAME or ANSWER).
  */
 enum response_type response_type_from_server(int rdset, 
        struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
-       int* empty_nodata_found);
+       int* empty_nodata_found, int msg_lame_empty, int msg_lame_referral);
 
 #endif /* ITERATOR_ITER_RESPTYPE_H */
index f1f9b8f3e0aae15e784c65df0d3fa73e88e7f7f0..823737d8c633b249b73f8beb8189c0ea627a033f 100644 (file)
@@ -316,6 +316,20 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
        return cn;
 }
 
+/** Check if the packet has type NS in answer or authority section */
+static int
+pkt_contains_ns(struct msg_parse* msg)
+{
+       struct rrset_parse* rrset;
+       for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next) {
+               if(rrset->type == LDNS_RR_TYPE_NS &&
+                       (rrset->section == LDNS_SECTION_ANSWER ||
+                       rrset->section == LDNS_SECTION_AUTHORITY))
+                       return 1;
+       }
+       return 0;
+}
+
 /** check if DNAME applies to a name */
 static int
 pkt_strict_sub(sldns_buffer* pkt, uint8_t* sname, uint8_t* dr)
@@ -973,12 +987,20 @@ scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
  * @param env: module environment with config and cache.
  * @param ie: iterator environment with private address data.
  * @param qstate: for setting errinf for EDE error messages.
+ * @param pkt_before_NS: if the packet had type NS before scrub. If that
+ *     is removed now, that indicates this may have been lame.
+ * @param msg_lame_empty: returned true if the empty packet is lame.
+ * @param msg_lame_referral: returned true if the reply has a referral before
+ *     scrub.
+ * @param rdset: if RD bit was sent in query sent by unbound.
  * @return 0 on error.
  */
 static int
 scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg, 
        struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
-       struct iter_env* ie, struct module_qstate* qstate)
+       struct iter_env* ie, struct module_qstate* qstate,
+       int pkt_before_NS, int* msg_lame_empty, int* msg_lame_referral,
+       int rdset)
 {
        int del_addi = 0; /* if additional-holding rrsets are deleted, we
                do not trust the normalized additional-A-AAAA any more */
@@ -1135,6 +1157,21 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
                prev = rrset;
                rrset = rrset->rrset_all_next;
        }
+
+       /* If the packet is empty now, but it was not before. And there
+        * was type NS in authority, then that indicates the answer is lame. */
+       if(msg->rrset_first == NULL && pkt_before_NS) {
+               *msg_lame_empty = 1;
+               verbose(VERB_ALGO, "sanitize: empty message had referral to NS before, marked as lame");
+       } else if(pkt_before_NS && msg->an_rrsets==0 &&
+               !(msg->flags&BIT_AA) && !rdset) {
+               /* If the packet is now a referral, not really a nodata,
+                * then if it was also with an empty answer section before,
+                * it is also lame. */
+               *msg_lame_referral = 1;
+               verbose(VERB_ALGO, "sanitize: message has referral not answer, marked as lame");
+       }
+
        return 1;
 }
 
@@ -1142,11 +1179,15 @@ int
 scrub_message(sldns_buffer* pkt, struct msg_parse* msg, 
        struct query_info* qinfo, uint8_t* zonename, struct regional* region,
        struct module_env* env, struct module_qstate* qstate,
-       struct iter_env* ie)
+       struct iter_env* ie, int* msg_lame_empty, int* msg_lame_referral,
+       int rdset)
 {
+       int pkt_before_NS;
        /* basic sanity checks */
        log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS, 
                qinfo->qclass);
+       *msg_lame_empty = 0;
+       *msg_lame_referral = 0;
        if(msg->qdcount > 1)
                return 0;
        if( !(msg->flags&BIT_QR) )
@@ -1171,11 +1212,21 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
                        return 0;
        }
 
+       /* If the packet contains type NS in authority before scrub,
+        * like a self referral. With the answer section empty, it
+        * was not AA, the query was not sent with RD, with NS in auth,
+        * and no SOA in auth. For a negative answer, type SOA is present.
+        * This detects certain lameness if after has removed that. */
+       pkt_before_NS = msg->an_rrsets == 0 &&
+               !(msg->flags&BIT_AA) && !rdset &&
+               pkt_contains_ns(msg) && !soa_in_auth(msg);
+
        /* normalize the response, this cleans up the additional.  */
        if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename))
                return 0;
        /* delete all out-of-zone information */
-       if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
+       if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate,
+               pkt_before_NS, msg_lame_empty, msg_lame_referral, rdset))
                return 0;
        return 1;
 }
index 4d6ce7166516d2168e08bb918bffa7c773ed9598..6b40e6c574c98f6e4f6b7493da7ebd427060800a 100644 (file)
@@ -62,11 +62,16 @@ struct module_qstate;
  * @param env: module environment with config settings and cache. 
  * @param qstate: for setting errinf for EDE error messages.
  * @param ie: iterator module environment data.
+ * @param msg_lame_empty: returned true if the empty packet is lame.
+ * @param msg_lame_referral: returned true if the reply has a referral before
+ *     scrub.
+ * @param rdset: if RD bit was sent in query sent by unbound.
  * @return: false if the message is total waste. true if scrubbed with success.
  */
 int scrub_message(struct sldns_buffer* pkt, struct msg_parse* msg, 
        struct query_info* qinfo, uint8_t* zonename, struct regional* regional,
        struct module_env* env, struct module_qstate* qstate,
-       struct iter_env* ie);
+       struct iter_env* ie, int* msg_lame_empty, int* msg_lame_referral,
+       int rdset);
 
 #endif /* ITERATOR_ITER_SCRUB_H */
index cc38348b39dad95a2175cd1a41c915ece21f3029..642536d9522b98b28df6fa2f5ee2622f03c7f42e 100644 (file)
@@ -3154,7 +3154,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
        orig_empty_nodata_found = iq->empty_nodata_found;
        type = response_type_from_server(
                (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
-               iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found);
+               iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found,
+               iq->msg_lame_empty, iq->msg_lame_referral);
        iq->chase_to_rd = 0;
        /* remove TC flag, if this is erroneously set by TCP upstream */
        iq->response->rep->flags &= ~BIT_TC;
@@ -3760,7 +3761,8 @@ processPrimeResponse(struct module_qstate* qstate, int id)
        iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */
        type = response_type_from_server(
                (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), 
-               iq->response, &iq->qchase, iq->dp, NULL);
+               iq->response, &iq->qchase, iq->dp, NULL, iq->msg_lame_empty,
+               iq->msg_lame_referral);
        if(type == RESPONSE_TYPE_ANSWER) {
                qstate->return_rcode = LDNS_RCODE_NOERROR;
                qstate->return_msg = iq->response;
@@ -4369,7 +4371,10 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
 
        /* normalize and sanitize: easy to delete items from linked lists */
        if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name, 
-               qstate->env->scratch, qstate->env, qstate, ie)) {
+               qstate->env->scratch, qstate->env, qstate, ie,
+               &iq->msg_lame_empty, &iq->msg_lame_referral,
+               (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd)
+               )) {
                /* if 0x20 enabled, start fallback, but we have no message */
                if(event == module_event_capsfail && !iq->caps_fallback) {
                        iq->caps_fallback = 1;
index ae4b4e45170a615ce9f3bf9d7c09bdd489ec6978..5c3acda3bd4720fc4dbcec06afb2b5421e4525f5 100644 (file)
@@ -434,6 +434,13 @@ struct iter_qstate {
         * already so that it is accepted later. */
        int empty_nodata_found;
 
+       /** Store if the answer was empty, but lame, before it became empty.*/
+       int msg_lame_empty;
+
+       /** Store if the answer was a referral, to self, before scrub. So the
+        * it is not some sort of answer. */
+       int msg_lame_referral;
+
        /** list of pending queries to authoritative servers. */
        struct outbound_list outlist;
 
index b7a6fde29b6c121ae94d8d79dbce0999d2288f7d..15511996fc0b2ebaf1a4c40ca84c76c5f53fe8cd 100644 (file)
@@ -95,7 +95,7 @@ RANGE_BEGIN 0 100
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 example.com. IN NS
 SECTION ANSWER
@@ -107,7 +107,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.example.com. IN A
 SECTION ANSWER
@@ -119,7 +119,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.example.com. IN AAAA
 SECTION ANSWER
@@ -130,7 +130,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 www.example.com. IN A
 SECTION ANSWER
@@ -144,7 +144,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 mail.example.com. IN AAAA
 SECTION ANSWER
@@ -158,7 +158,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 foo.example.com. IN A
 SECTION ANSWER
@@ -172,7 +172,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 toss.example.com. IN A
 SECTION ANSWER
@@ -221,12 +221,16 @@ ENTRY_END
 STEP 10 CHECK_ANSWER
 ENTRY_BEGIN
 MATCH all
-REPLY QR RD RA SERVFAIL
+REPLY QR RD RA NOERROR
 SECTION QUESTION
 foo.example.com. IN A
 SECTION ANSWER
 ; scrubbed away
 ;foo.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
 
 ; IPv6 address is scrubbed
@@ -240,10 +244,14 @@ ENTRY_END
 STEP 30 CHECK_ANSWER
 ENTRY_BEGIN
 MATCH all
-REPLY QR RD RA SERVFAIL
+REPLY QR RD RA NOERROR
 SECTION QUESTION
 mail.example.com. IN AAAA
 SECTION ANSWER
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
 ENTRY_END
 
 ; allowed domain is not scrubbed.
index 13f04d4817f60cbd8ffc1b1c97f27be78f73eac5..fbcdf35eef0789f3dc402e133622714275e805d7 100644 (file)
@@ -73,7 +73,7 @@ RANGE_BEGIN 0 100
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 example.com. IN A
 SECTION AUTHORITY
@@ -85,7 +85,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 www.example.com. IN A
 SECTION AUTHORITY
@@ -97,7 +97,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 www.example.com. IN AAAA
 SECTION ANSWER
diff --git a/testdata/iter_self_glue.rpl b/testdata/iter_self_glue.rpl
new file mode 100644 (file)
index 0000000..003b294
--- /dev/null
@@ -0,0 +1,109 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+       qname-minimisation: no
+       iter-scrub-promiscuous: yes
+
+stub-zone:
+       name: "."
+       stub-addr: 1.2.3.0 # ns.root
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with self glue response that becomes empty.
+
+; ns.root
+RANGE_BEGIN 0 400
+       ADDRESS 1.2.3.0
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS NS.ROOT.
+SECTION ADDITIONAL
+NS.ROOT. IN A 1.2.3.0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+mesa. IN NS
+SECTION AUTHORITY
+mesa. IN NS ns.mesa.
+SECTION ADDITIONAL
+ns.mesa. IN A 1.2.7.7
+ENTRY_END
+RANGE_END
+
+; ns.mesa
+RANGE_BEGIN 0 400
+       ADDRESS 1.2.7.7
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.mesa. IN NS
+SECTION AUTHORITY
+example.mesa. IN NS ns.example.mesa.
+SECTION ADDITIONAL
+ns.example.mesa. IN A 1.2.4.3
+ENTRY_END
+RANGE_END
+
+; ns.example.mesa
+RANGE_BEGIN 0 400
+       ADDRESS 1.2.4.3
+
+; This answer contains an NS record that points to itself.
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.mesa. IN NS
+SECTION AUTHORITY
+sub.example.mesa. IN NS ns.nonce1.sub.example.mesa.
+SECTION ADDITIONAL
+ns.nonce1.sub.example.mesa. IN A 1.2.4.3
+ENTRY_END
+RANGE_END
+
+; Test query with authority section MX glue.
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+test1.sub.example.mesa. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+test1.sub.example.mesa. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+test2.sub.example.mesa. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+test2.sub.example.mesa. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_self_glue_promisc.rpl b/testdata/iter_self_glue_promisc.rpl
new file mode 100644 (file)
index 0000000..36b2a26
--- /dev/null
@@ -0,0 +1,94 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+       qname-minimisation: no
+       iter-scrub-promiscuous: no
+
+stub-zone:
+       name: "."
+       stub-addr: 1.2.3.0 # ns.root
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with self glue response that becomes empty.
+; It allows promiscuous NS records.
+
+; ns.root
+RANGE_BEGIN 0 400
+       ADDRESS 1.2.3.0
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS NS.ROOT.
+SECTION ADDITIONAL
+NS.ROOT. IN A 1.2.3.0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+mesa. IN NS
+SECTION AUTHORITY
+mesa. IN NS ns.mesa.
+SECTION ADDITIONAL
+ns.mesa. IN A 1.2.7.7
+ENTRY_END
+RANGE_END
+
+; ns.mesa
+RANGE_BEGIN 0 400
+       ADDRESS 1.2.7.7
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.mesa. IN NS
+SECTION AUTHORITY
+example.mesa. IN NS ns.example.mesa.
+SECTION ADDITIONAL
+ns.example.mesa. IN A 1.2.4.3
+ENTRY_END
+RANGE_END
+
+; ns.example.mesa
+RANGE_BEGIN 0 400
+       ADDRESS 1.2.4.3
+
+; This answer contains an NS record that points to itself.
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.mesa. IN NS
+SECTION AUTHORITY
+sub.example.mesa. IN NS ns.sub.example.mesa.
+SECTION ADDITIONAL
+ns.sub.example.mesa. IN A 1.2.4.3
+ENTRY_END
+RANGE_END
+
+; Test query with authority section MX glue.
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+test1.sub.example.mesa. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+test1.sub.example.mesa. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
index d76d34601417575b907d3b42ca19404693979925..51ffb4121a37e29a8b1df254987e4c95e1550aff 100644 (file)
@@ -32,6 +32,7 @@ SECTION QUESTION
 arpa. IN NS
 SECTION ANSWER
 SECTION AUTHORITY
+. IN SOA invalid. invalid. 1 2 3 4 5
 . IN NS        K.ROOT-SERVERS.NET.
 SECTION ADDITIONAL
 K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
@@ -45,6 +46,7 @@ SECTION QUESTION
 in-addr.arpa. IN NS
 SECTION ANSWER
 SECTION AUTHORITY
+. IN SOA invalid. invalid. 1 2 3 4 5
 . IN NS        K.ROOT-SERVERS.NET.
 SECTION ADDITIONAL
 K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
index 27a562f3a6457fb519f54ef23f6fa13ec983e5e1..9e758a56fb6e4f40fc120e0e52d356ce381d95ed 100644 (file)
@@ -91,7 +91,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.example.com. IN AAAA
 SECTION ANSWER
index 77a3c06bdef7439b035c4496e529c459a616e911..8441760ce86b06b660811f9f86fb9025e09a0bb1 100644 (file)
@@ -91,7 +91,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.example.com. IN AAAA
 SECTION ANSWER
index 9a8919fb0005e42206fbc366fee24cf9edc7f968..c14d31edaee13c2b2b1fddfce67fb7de711e9cb3 100644 (file)
@@ -90,7 +90,7 @@ RANGE_BEGIN 0 100
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.example.com. IN AAAA
 SECTION ANSWER
index 07dd40340c4d544ed3facf78618fd79e948f71e4..3e47c5ae0aba0050fcdef7a761e2d02893b833b3 100644 (file)
@@ -92,7 +92,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.example.com. IN AAAA
 SECTION ANSWER
index ec768799d7f9b821fdcc6eeea14b78c0c75a62d6..6a892772d5ec7732ea7db80990e2b8145e2863f9 100644 (file)
@@ -159,7 +159,7 @@ ENTRY_END
 ENTRY_BEGIN
 MATCH opcode qtype qname
 ADJUST copy_id
-REPLY QR NOERROR
+REPLY QR AA NOERROR
 SECTION QUESTION
 ns.sub.example.com. IN AAAA
 SECTION AUTHORITY