]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Detect recursion-lameness.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 22 Oct 2007 12:05:46 +0000 (12:05 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 22 Oct 2007 12:05:46 +0000 (12:05 +0000)
git-svn-id: file:///svn/unbound/trunk@713 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iter_resptype.c
iterator/iter_resptype.h
iterator/iterator.c
testdata/iter_ranoaa_lame.rpl [new file with mode: 0644]

index 88afbfb3b3ccd2c8208af3be0494c604d916cdce..4d1cd736928a3a0ed0587da1cb6cd3233b29e07f 100644 (file)
@@ -2,6 +2,7 @@
        - added donotquerylocalhost config option. Can be turned off for
          out test cases.
        - ISO C compat changes.
+       - detect RA-no-AA lameness, as LAME.
 
 19 October 2007: Wouter
        - added configure (and its files) to svn, so that the trunk is easier
index 94e98a5a3240517512afe15cd13a02914f45ae6d..bad8e393abde59a009d92e0a57b99547d45da7d1 100644 (file)
@@ -100,8 +100,8 @@ response_type_from_cache(struct dns_msg* msg,
 }
 
 enum response_type 
-response_type_from_server(struct dns_msg* msg, struct query_info* request,
-       struct delegpt* dp)
+response_type_from_server(int rdset,
+       struct dns_msg* msg, struct query_info* request, struct delegpt* dp)
 {
        uint8_t* origzone = (uint8_t*)"\000"; /* the default */
        size_t origzonelen = 1;
@@ -111,8 +111,13 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
                return RESPONSE_TYPE_THROWAWAY;
        
        /* If the message is NXDOMAIN, then it answers the question. */
-       if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN)
+       if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
+               /* make sure its not recursive when we don't want it to */
+               if( (msg->rep->flags&BIT_RA) &&
+                       !(msg->rep->flags&BIT_AA) && !rdset)
+                               return RESPONSE_TYPE_LAME;
                return RESPONSE_TYPE_ANSWER;
+       }
        
        /* Other response codes mean (so far) to throw the response away as
         * meaningless and move on to the next nameserver. */
@@ -193,6 +198,10 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
                /* The normal way of detecting NOERROR/NODATA. */
                if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA &&
                        dname_subdomain_c(request->qname, s->rk.dname)) {
+                       /* we do our own recursion, thank you */
+                       if( (msg->rep->flags&BIT_RA) &&
+                               !(msg->rep->flags&BIT_AA) && !rdset)
+                               return RESPONSE_TYPE_LAME;
                        return RESPONSE_TYPE_ANSWER;
                }
 
@@ -203,6 +212,11 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
                         * thought we were contacting, then it is an answer.*/
                        /* FIXME: is this correct? */
                        if(query_dname_compare(s->rk.dname, origzone) == 0) {
+                               /* see if mistakenly a recursive server was
+                                * deployed and is responding nonAA */
+                               if( (msg->rep->flags&BIT_RA) &&
+                                       !(msg->rep->flags&BIT_AA) && !rdset)
+                                       return RESPONSE_TYPE_LAME;
                                return RESPONSE_TYPE_ANSWER;
                        }
                        /* If we are getting a referral upwards (or to 
@@ -231,5 +245,8 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
 
        /* If we've gotten this far, this is NOERROR/NODATA (which could 
         * be an entirely empty message) */
+       /* check if recursive answer; saying it has empty cache */
+       if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
+               return RESPONSE_TYPE_LAME;
        return RESPONSE_TYPE_ANSWER;
 }
index c50f07e1c35bf9dcc509b484b7d35636cc8e9fa3..bfacd6148bf4287bfc1e30cc02f81963b7d16234 100644 (file)
@@ -107,13 +107,14 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
  * relies somewhat on the originating zone to be accurate (for lameness
  * detection, mostly).
  *
+ * @param rdset: if RD bit was sent in query sent by unbound.
  * @param msg: the message from the cache.
  * @param request: the request that generated the response.
  * @param dp: The delegation point that was being queried
  *          when the response was returned.
  * @return the response type (CNAME or ANSWER).
  */
-enum response_type response_type_from_server(struct dns_msg* msg
-       struct query_info* request, struct delegpt* dp);
+enum response_type response_type_from_server(int rdset
+       struct dns_msg* msg, struct query_info* request, struct delegpt* dp);
 
 #endif /* ITERATOR_ITER_RESPTYPE_H */
index eb0e9269e85a811c817b717c877957530690f232..c6f2d2f140d491c26a85b255946b67d63042f6c6 100644 (file)
@@ -1179,7 +1179,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                verbose(VERB_ALGO, "query response was timeout");
                return next_state(iq, QUERYTARGETS_STATE);
        }
-       type = response_type_from_server(iq->response, &iq->qchase, iq->dp);
+       type = response_type_from_server((int)(iq->chase_flags&BIT_RD),
+               iq->response, &iq->qchase, iq->dp);
        if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
                /* When forwarding (RD bit is set), we handle referrals 
                 * differently. No queries should be sent elsewhere */
@@ -1373,7 +1374,7 @@ static int
 processPrimeResponse(struct module_qstate* qstate, int id)
 {
        struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
-       enum response_type type = response_type_from_server(iq->response, 
+       enum response_type type = response_type_from_server(0, iq->response, 
                &iq->qchase, iq->dp);
        if(type == RESPONSE_TYPE_ANSWER) {
                qstate->return_rcode = LDNS_RCODE_NOERROR;
diff --git a/testdata/iter_ranoaa_lame.rpl b/testdata/iter_ranoaa_lame.rpl
new file mode 100644 (file)
index 0000000..48a0e7b
--- /dev/null
@@ -0,0 +1,218 @@
+; config options
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test detection of RA but no AA lameness
+; in this scenario mistakenly, a recursive server is deployed, instead
+; of an authoritative server. It gives answers from cache.
+; However, unbound is doing recursion on behalf of its client, and does
+; not trust the server to do so.
+
+; 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
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.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
+www.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+; this entry; glue will make unbound take this reference first.
+; it is however, the lame server.
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A  1.2.3.44
+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. IN A  10.20.30.40
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net         IN A    1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+; the lame response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; the wrong answer.
+www.example.com. IN A  10.20.30.50
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA 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.
+example.com.   IN NS   ns.example.net.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.example.net        IN A    1.2.3.44
+ENTRY_END
+
+SCENARIO_END