From: Wouter Wijngaards Date: Wed, 25 Jun 2008 09:39:57 +0000 (+0000) Subject: fixup for newegg lameness. X-Git-Tag: release-1.0.1~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5eb7ff35ca781d2006668557dbb156b7773b40d7;p=thirdparty%2Funbound.git fixup for newegg lameness. git-svn-id: file:///svn/unbound/trunk@1137 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 73a15afd1..93120d731 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 9a0577dc0..1ff42a0b4 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -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) diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index e737f2564..0edbb8ed4 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -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. diff --git a/iterator/iterator.c b/iterator/iterator.c index eadc3214a..68d5950ee 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -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 ":""); diff --git a/services/cache/infra.c b/services/cache/infra.c index 149092f03..2c366ace5 100644 --- a/services/cache/infra.c +++ b/services/cache/infra.c @@ -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; diff --git a/services/cache/infra.h b/services/cache/infra.h index 605396e28..5b441e3e0 100644 --- a/services/cache/infra.h +++ b/services/cache/infra.h @@ -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 index 000000000..0e39aba64 --- /dev/null +++ b/testdata/iter_lame_aaaa.rpl @@ -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