]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
fixup for newegg lameness.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 25 Jun 2008 09:39:57 +0000 (09:39 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 25 Jun 2008 09:39:57 +0000 (09:39 +0000)
git-svn-id: file:///svn/unbound/trunk@1137 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c
services/cache/infra.c
services/cache/infra.h
testdata/iter_lame_aaaa.rpl [new file with mode: 0644]

index 73a15afd172410dce83cb6839eb10a22f3eff797..93120d731a97ca119fcd8f7f772418868ea0f6b9 100644 (file)
@@ -1,5 +1,6 @@
 25 June 2008: Wouter
        - fixup fwd_ancil test typos.
+       - Fix for newegg lameness : ok for qtype=A, but lame for others.
 
 24 June 2008: Wouter
        - removed testcode/checklocks from production code compilation path.
index 9a0577dc06136d23ddfafc5edd366a9aa6d7ac2a..1ff42a0b4e0e2c1be6d0ef66497d340ad2c74936 100644 (file)
@@ -130,7 +130,8 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
 /** filter out unsuitable targets, return rtt or -1 */
 static int
 iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
-       uint8_t* name, size_t namelen, uint32_t now, struct delegpt_addr* a)
+       uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, 
+       struct delegpt_addr* a)
 {
        int rtt;
        int lame;
@@ -143,7 +144,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
        }
        /* check lameness - need zone , class info */
        if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, 
-               name, namelen, &lame, &dnsseclame, &rtt, now)) {
+               name, namelen, qtype, &lame, &dnsseclame, &rtt, now)) {
                if(lame)
                        return -1; /* server is lame */
                else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
@@ -159,14 +160,14 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
 /** lookup RTT information, and also store fastest rtt (if any) */
 static int
 iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
-       uint8_t* name, size_t namelen, uint32_t now, struct delegpt* dp,
-       int* best_rtt)
+       uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, 
+       struct delegpt* dp, int* best_rtt)
 {
        int got_it = 0;
        struct delegpt_addr* a;
        for(a=dp->result_list; a; a = a->next_result) {
                a->sel_rtt = iter_filter_unsuitable(iter_env, env, 
-                       name, namelen, now, a);
+                       name, namelen, qtype, now, a);
                if(a->sel_rtt != -1) {
                        if(!got_it) {
                                *best_rtt = a->sel_rtt;
@@ -183,14 +184,14 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
  * returns number of best targets (or 0, no suitable targets) */
 static int
 iter_filter_order(struct iter_env* iter_env, struct module_env* env,
-       uint8_t* name, size_t namelen, uint32_t now, struct delegpt* dp,
-       int* selected_rtt)
+       uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, 
+       struct delegpt* dp, int* selected_rtt)
 {
        int got_num = 0, low_rtt = 0, swap_to_front;
        struct delegpt_addr* a, *n, *prev=NULL;
 
        /* fillup sel_rtt and find best rtt in the bunch */
-       got_num = iter_fill_rtt(iter_env, env, name, namelen, now, dp, 
+       got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp, 
                &low_rtt);
        if(got_num == 0) 
                return 0;
@@ -232,12 +233,12 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
 struct delegpt_addr* 
 iter_server_selection(struct iter_env* iter_env, 
        struct module_env* env, struct delegpt* dp, 
-       uint8_t* name, size_t namelen, int* dnssec_expected)
+       uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_expected)
 {
        int sel;
        int selrtt;
        struct delegpt_addr* a, *prev;
-       int num = iter_filter_order(iter_env, env, name, namelen, 
+       int num = iter_filter_order(iter_env, env, name, namelen, qtype,
                *env->now, dp, &selrtt);
 
        if(num == 0)
index e737f2564b66264b2120b28ca5f498e570c27bc4..0edbb8ed4ad924615391a50c88ad570fdf42172a 100644 (file)
@@ -74,6 +74,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
  * @param dp: delegation point with result list.
  * @param name: zone name (for lameness check).
  * @param namelen: length of name.
+ * @param qtype: query type that we want to send.
  * @param dnssec_expected: set to 0, if a known dnssec-lame server is selected
  *     these are not preferred, but are used as a last resort.
  * @return best target or NULL if no target.
@@ -81,7 +82,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
  */
 struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, 
        struct module_env* env, struct delegpt* dp, uint8_t* name, 
-       size_t namelen, int* dnssec_expected);
+       size_t namelen, uint16_t qtype, int* dnssec_expected);
 
 /**
  * Allocate dns_msg from parsed msg, in regional.
index eadc3214a5616384df154724c5d327434b77232b..68d5950ee289e2275f7436fdd61fa6f58205d005 100644 (file)
@@ -1100,7 +1100,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
 
        /* Select the next usable target, filtering out unsuitable targets. */
        target = iter_server_selection(ie, qstate->env, iq->dp, 
-               iq->dp->name, iq->dp->namelen, &iq->dnssec_expected);
+               iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
+               &iq->dnssec_expected);
 
        /* If no usable target was selected... */
        if(!target) {
@@ -1337,7 +1338,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                        if(!infra_set_lame(qstate->env->infra_cache, 
                                &qstate->reply->addr, qstate->reply->addrlen, 
                                iq->dp->name, iq->dp->namelen, 
-                               *qstate->env->now, dnsseclame))
+                               *qstate->env->now, dnsseclame, 
+                               iq->qchase.qtype))
                                log_err("mark host lame: out of memory");
                } else log_err("%slame response from cache",
                        dnsseclame?"DNSSEC ":"");
index 149092f0375134421739523dee116b9f1f3d9194..2c366ace5684d64ed60efe1dbe092a2e29bd5d22 100644 (file)
@@ -260,12 +260,12 @@ hash_lameness(uint8_t* name, size_t namelen)
 
 int 
 infra_lookup_lame(struct infra_host_data* host,
-        uint8_t* name, size_t namelen, uint32_t timenow)
+        uint8_t* name, size_t namelen, uint32_t timenow,
+       int* dlame, int* alame, int* olame)
 {
        struct lruhash_entry* e;
        struct infra_lame_key k;
        struct infra_lame_data *d;
-       int dl;
        if(!host->lameness)
                return 0;
        k.entry.hash = hash_lameness(name, namelen);
@@ -281,9 +281,11 @@ infra_lookup_lame(struct infra_host_data* host,
                lock_rw_unlock(&e->lock);
                return 0;
        }
-       dl = d->isdnsseclame;
+       *dlame = d->isdnsseclame;
+       *alame = d->lame_type_A;
+       *olame = d->lame_other;
        lock_rw_unlock(&e->lock);
-       return dl?2:1;
+       return *dlame || *alame || *olame;
 }
 
 size_t 
@@ -329,7 +331,8 @@ infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
 int 
 infra_set_lame(struct infra_cache* infra,
         struct sockaddr_storage* addr, socklen_t addrlen,
-        uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame)
+        uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
+       uint16_t qtype)
 {
        struct infra_host_data* data;
        struct lruhash_entry* e;
@@ -361,6 +364,8 @@ infra_set_lame(struct infra_cache* infra,
        k->entry.data = (void*)d;
        d->ttl = timenow + infra->lame_ttl;
        d->isdnsseclame = dnsseclame;
+       d->lame_type_A = (!dnsseclame && qtype == LDNS_RR_TYPE_A);
+       d->lame_other = (!dnsseclame && qtype != LDNS_RR_TYPE_A);
        k->namelen = namelen;
        e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
        if(!e) {
@@ -392,7 +397,18 @@ infra_set_lame(struct infra_cache* infra,
                        free(d);
                        return 0;
                }
+       } else {
+               /* lookup existing lameness entry (if any) and merge data */
+               int dlame, alame, olame; 
+               if(infra_lookup_lame(data, name, namelen, timenow,
+                       &dlame, &alame, &olame)) { 
+                       /* merge data into new structure */
+                       if(dlame) d->isdnsseclame = 1;
+                       if(alame) d->lame_type_A = 1;
+                       if(olame) d->lame_other = 1;
+               }
        }
+
        /* inserts new entry, or updates TTL of older entry */
        lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
        
@@ -477,28 +493,36 @@ infra_edns_update(struct infra_cache* infra,
 int 
 infra_get_lame_rtt(struct infra_cache* infra,
         struct sockaddr_storage* addr, socklen_t addrlen,
-        uint8_t* name, size_t namelen, int* lame, int* dnsseclame,
-       int* rtt, uint32_t timenow)
+        uint8_t* name, size_t namelen, uint16_t qtype, 
+       int* lame, int* dnsseclame, int* rtt, uint32_t timenow)
 {
        struct infra_host_data* host;
        struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr, 
                addrlen, 0);
-       int lm;
+       int dlm, alm, olm;
        if(!e) 
                return 0;
        host = (struct infra_host_data*)e->data;
        *rtt = rtt_unclamped(&host->rtt);
        /* check lameness first, if so, ttl on host does not matter anymore */
-       if((lm=infra_lookup_lame(host, name, namelen, timenow))) {
-               lock_rw_unlock(&e->lock);
-               if(lm == 1) {
+       if(infra_lookup_lame(host, name, namelen, timenow, &dlm, &alm, &olm)) {
+               if(alm && qtype == LDNS_RR_TYPE_A) {
+                       lock_rw_unlock(&e->lock);
                        *lame = 1;
                        *dnsseclame = 0;
-               } else {
+                       return 1;
+               } else if(olm && qtype != LDNS_RR_TYPE_A) {
+                       lock_rw_unlock(&e->lock);
+                       *lame = 1;
+                       *dnsseclame = 0;
+                       return 1;
+               } else if(dlm) {
+                       lock_rw_unlock(&e->lock);
                        *lame = 0;
                        *dnsseclame = 1;
+                       return 1;
                }
-               return 1;
+               /* no lameness for this type of query */
        }
        *lame = 0;
        *dnsseclame = 0;
index 605396e28274c440cb412d6d8e5bd7370e20bd88..5b441e3e034973b069179d3245ec0ef8a55b2fef 100644 (file)
@@ -94,6 +94,10 @@ struct infra_lame_data {
        /** is the host lame (does not serve the zone authoritatively),
         * or is the host dnssec lame (does not serve DNSSEC data) */
        int isdnsseclame;
+       /** the host is lame (not authoritative) for A records */
+       int lame_type_A;
+       /** the host is lame (not authoritative) for other query types */
+       int lame_other;
 };
 
 /**
@@ -175,10 +179,14 @@ int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
  * @param name: domain name of zone apex.
  * @param namelen: length of domain name.
  * @param timenow: what time it is now.
- * @return: 0 if not lame or unknown or timed out, 1 if lame, 2 if dnsseclame.
+ * @param dlame: if the function returns true, is set true if dnssec lame.
+ * @param alame: if the function returns true, is set true if qtype A lame.
+ * @param olame: if the function returns true, is set true if qtype other lame.
+ * @return: 0 if not lame or unknown or timed out, 1 if lame
  */
 int infra_lookup_lame(struct infra_host_data* host,
-       uint8_t* name, size_t namelen, uint32_t timenow);
+       uint8_t* name, size_t namelen, uint32_t timenow,
+       int* dlame, int* alame, int* olame);
 
 /**
  * Set a host to be lame for the given zone.
@@ -190,11 +198,13 @@ int infra_lookup_lame(struct infra_host_data* host,
  * @param timenow: what time it is now.
  * @param dnsseclame: if true the host is set dnssec lame.
  *     if false, the host is marked lame (not serving the zone).
+ * @param qtype: the query type for which it is lame.
  * @return: 0 on error.
  */
 int infra_set_lame(struct infra_cache* infra,
         struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame);
+       uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
+       uint16_t qtype);
 
 /**
  * Update rtt information for the host.
@@ -239,6 +249,7 @@ int infra_edns_update(struct infra_cache* infra,
  * @param addrlen: length of addr.
  * @param name: zone name.
  * @param namelen: zone name length.
+ * @param qtype: the query to be made.
  * @param lame: if function returns true, this returns lameness of the zone.
  * @param dnsseclame: if function returns true, this returns if the zone
  *     is dnssec-lame.
@@ -249,8 +260,8 @@ int infra_edns_update(struct infra_cache* infra,
  */
 int infra_get_lame_rtt(struct infra_cache* infra,
         struct sockaddr_storage* addr, socklen_t addrlen, 
-       uint8_t* name, size_t namelen, int* lame, int* dnsseclame,
-       int* rtt, uint32_t timenow);
+       uint8_t* name, size_t namelen, uint16_t qtype, 
+       int* lame, int* dnsseclame, int* rtt, uint32_t timenow);
 
 /**
  * Get memory used by the infra cache.
diff --git a/testdata/iter_lame_aaaa.rpl b/testdata/iter_lame_aaaa.rpl
new file mode 100644 (file)
index 0000000..0e39aba
--- /dev/null
@@ -0,0 +1,135 @@
+; config options
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator lameness detection of AAAA-only lameness
+
+; 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
+example.com. IN AAAA
+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.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN AAAA
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.4
+
+; response to AAAA query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+.                      3600000 IN      NS      a.root-servers.net.
+.                      3600000 IN      NS      b.root-servers.net.
+.                      3600000 IN      NS      c.root-servers.net.
+.                      3600000 IN      NS      d.root-servers.net.
+.                      3600000 IN      NS      e.root-servers.net.
+.                      3600000 IN      NS      f.root-servers.net.
+.                      3600000 IN      NS      g.root-servers.net.
+.                      3600000 IN      NS      h.root-servers.net.
+.                      3600000 IN      NS      i.root-servers.net.
+.                      3600000 IN      NS      j.root-servers.net.
+.                      3600000 IN      NS      k.root-servers.net.
+.                      3600000 IN      NS      l.root-servers.net.
+.                      3600000 IN      NS      m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net.    3600000 IN      A       198.41.0.4
+b.root-servers.net.    3600000 IN      A       128.9.0.107
+c.root-servers.net.    3600000 IN      A       192.33.4.12
+ENTRY_END
+
+; response to A query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. 120 IN A 204.14.213.188
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+MATCH TCP
+REPLY RD
+SECTION QUESTION
+example.com. IN AAAA
+ENTRY_END
+
+; this fails; it is LAME
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; Now try the A type, which works, and is not LAME.
+STEP 20 QUERY
+ENTRY_BEGIN
+MATCH TCP
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+; this fails; it is LAME
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. 120 IN A 204.14.213.188
+ENTRY_END
+
+SCENARIO_END