fixup for newegg lameness.

git-svn-id: file:///svn/unbound/trunk@1137 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-06-25 09:39:57 +00:00
parent 4e1eab891b
commit 5eb7ff35ca
7 changed files with 206 additions and 31 deletions

View 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.

View 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)

View 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.

View 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 ":"");

View 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;

View 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.

135
testdata/iter_lame_aaaa.rpl vendored Normal file
View file

@ -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