From dbaa5194a6fd583b57afb269bd10f4cad1ae769e Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Mon, 13 Oct 2008 09:11:42 +0000 Subject: [PATCH] Recursion lame is detected and last resort is used to resolve. git-svn-id: file:///svn/unbound/trunk@1294 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 5 ++ iterator/iter_resptype.c | 10 +-- iterator/iter_resptype.h | 9 +- iterator/iter_utils.c | 20 +++-- iterator/iter_utils.h | 5 +- iterator/iterator.c | 25 +++++- iterator/iterator.h | 2 + services/cache/infra.c | 34 ++++--- services/cache/infra.h | 12 ++- services/outside_network.c | 1 + testcode/unitmain.c | 18 ++-- testdata/iter_reclame_one.rpl | 162 ++++++++++++++++++++++++++++++++++ testdata/iter_reclame_two.rpl | 161 +++++++++++++++++++++++++++++++++ 13 files changed, 424 insertions(+), 40 deletions(-) create mode 100644 testdata/iter_reclame_one.rpl create mode 100644 testdata/iter_reclame_two.rpl diff --git a/doc/Changelog b/doc/Changelog index 8d185c3a0..0494dde76 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +13 October 2008: Wouter + - fixed recursion servers deployed as authoritative detection, so + that as a last resort, a +RD query is sent there to get the + correct answer. + 10 October 2008: Wouter - fixup tests - the negative cache contained the correct NSEC3s for two tests that are supposed to fail to validate. diff --git a/iterator/iter_resptype.c b/iterator/iter_resptype.c index 17d546986..40d71358b 100644 --- a/iterator/iter_resptype.c +++ b/iterator/iter_resptype.c @@ -116,7 +116,7 @@ response_type_from_server(int rdset, /* 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_REC_LAME; return RESPONSE_TYPE_ANSWER; } @@ -200,7 +200,7 @@ response_type_from_server(int rdset, /* 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_REC_LAME; return RESPONSE_TYPE_ANSWER; } } @@ -222,13 +222,13 @@ response_type_from_server(int rdset, * deployed and is responding nonAA */ if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_LAME; + return RESPONSE_TYPE_REC_LAME; /* Or if a lame server is deployed, * which gives ns==zone delegation from cache * without AA bit as well, with nodata nosoa*/ if(msg->rep->an_numrrsets==0 && !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_LAME; + return RESPONSE_TYPE_REC_LAME; return RESPONSE_TYPE_ANSWER; } /* If we are getting a referral upwards (or to @@ -259,6 +259,6 @@ response_type_from_server(int rdset, * 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_REC_LAME; return RESPONSE_TYPE_ANSWER; } diff --git a/iterator/iter_resptype.h b/iterator/iter_resptype.h index bfacd6148..3bb3eedb2 100644 --- a/iterator/iter_resptype.h +++ b/iterator/iter_resptype.h @@ -81,7 +81,14 @@ enum response_type { * 'lame' means that this particular response indicates that * the nameserver knew nothing about the question. */ - RESPONSE_TYPE_LAME + RESPONSE_TYPE_LAME, + + /** + * Recursion lame means that the nameserver is some sort of + * open recursor, and not authoritative for the question. + * It may know something, but not authoritatively. + */ + RESPONSE_TYPE_REC_LAME }; /** diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 4c8942199..24251a5c0 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -140,9 +140,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, struct delegpt_addr* a) { - int rtt; - int lame; - int dnsseclame; + int rtt, lame, reclame, dnsseclame; if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) { return -1; /* server is on the donotquery list */ } @@ -151,12 +149,15 @@ 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, qtype, &lame, &dnsseclame, &rtt, now)) { + name, namelen, qtype, &lame, &dnsseclame, &reclame, + &rtt, now)) { if(lame) return -1; /* server is lame */ else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT) return -1; /* server is unresponsive */ - else if(dnsseclame) + else if(reclame) + return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ + else if(dnsseclame ) return rtt+USEFUL_SERVER_TOP_TIMEOUT; /* nonpref */ else return rtt; } @@ -240,7 +241,8 @@ 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, uint16_t qtype, int* dnssec_expected) + uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_expected, + int* chase_to_rd) { int sel; int selrtt; @@ -250,8 +252,12 @@ iter_server_selection(struct iter_env* iter_env, if(num == 0) return NULL; - if(selrtt >= USEFUL_SERVER_TOP_TIMEOUT) + if(selrtt >= USEFUL_SERVER_TOP_TIMEOUT*2) { + *chase_to_rd = 1; + } + if(selrtt >= USEFUL_SERVER_TOP_TIMEOUT) { *dnssec_expected = 0; + } if(num == 1) { a = dp->result_list; if(++a->attempts < OUTBOUND_MSG_RETRY) diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 1d3872294..dfaa367aa 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -77,12 +77,15 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg); * @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. + * @param chase_to_rd: set to 1 if a known recursion lame server is selected + * these are not preferred, but are used as a last resort. * @return best target or NULL if no target. * if not null, that target is removed from the result list in the dp. */ struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, struct module_env* env, struct delegpt* dp, uint8_t* name, - size_t namelen, uint16_t qtype, int* dnssec_expected); + size_t namelen, uint16_t qtype, int* dnssec_expected, + int* chase_to_rd); /** * Allocate dns_msg from parsed msg, in regional. diff --git a/iterator/iterator.c b/iterator/iterator.c index b5eb429c7..40fcbd452 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1211,7 +1211,7 @@ 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->qchase.qtype, - &iq->dnssec_expected); + &iq->dnssec_expected, &iq->chase_to_rd); /* If no usable target was selected... */ if(!target) { @@ -1276,7 +1276,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, outq = (*qstate->env->send_query)( iq->qchase.qname, iq->qchase.qname_len, iq->qchase.qtype, iq->qchase.qclass, - iq->chase_flags, EDNS_DO|BIT_CD, + iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD, &target->addr, target->addrlen, qstate); if(!outq) { verbose(VERB_OPS, "error sending query to auth server; " @@ -1313,11 +1313,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, enum response_type type; iq->num_current_queries--; if(iq->response == NULL) { + iq->chase_to_rd = 0; verbose(VERB_ALGO, "query response was timeout"); return next_state(iq, QUERYTARGETS_STATE); } - type = response_type_from_server((int)(iq->chase_flags&BIT_RD), + type = response_type_from_server( + (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), iq->response, &iq->qchase, iq->dp); + iq->chase_to_rd = 0; 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 */ @@ -1325,6 +1328,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, } if(iq->dnssec_expected && !(iq->chase_flags&BIT_RD) && type != RESPONSE_TYPE_LAME + && type != RESPONSE_TYPE_REC_LAME && type != RESPONSE_TYPE_THROWAWAY && type != RESPONSE_TYPE_UNTYPED) { /* a possible answer, see if it is missing DNSSEC */ @@ -1458,11 +1462,24 @@ 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, 0, iq->qchase.qtype)) log_err("mark host lame: out of memory"); } else log_err("%slame response from cache", dnsseclame?"DNSSEC ":""); + } else if(type == RESPONSE_TYPE_REC_LAME) { + /* Cache the LAMEness. */ + verbose(VERB_DETAIL, "query response REC_LAME: " + "recursive but not authoritative server"); + if(qstate->reply) { + /* need addr for lameness cache, but we may have + * gotten this from cache, so test to be sure */ + if(!infra_set_lame(qstate->env->infra_cache, + &qstate->reply->addr, qstate->reply->addrlen, + iq->dp->name, iq->dp->namelen, + *qstate->env->now, 0, 1, iq->qchase.qtype)) + log_err("mark host lame: out of memory"); + } } else if(type == RESPONSE_TYPE_THROWAWAY) { /* LAME and THROWAWAY responses are handled the same way. * In this case, the event is just sent directly back to diff --git a/iterator/iterator.h b/iterator/iterator.h index f8b1b2ca0..7a0a1e2cd 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -210,6 +210,8 @@ struct iter_qstate { struct query_info qchase; /** query flags to use when chasing the answer (i.e. RD flag) */ uint16_t chase_flags; + /** true if we set RD bit because of last resort recursion lame query*/ + int chase_to_rd; /** * This is the current delegation point for an in-progress query. This diff --git a/services/cache/infra.c b/services/cache/infra.c index dca5080cc..29fca3280 100644 --- a/services/cache/infra.c +++ b/services/cache/infra.c @@ -266,7 +266,7 @@ 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, - int* dlame, int* alame, int* olame) + int* dlame, int* rlame, int* alame, int* olame) { struct lruhash_entry* e; struct infra_lame_key k; @@ -287,10 +287,11 @@ infra_lookup_lame(struct infra_host_data* host, return 0; } *dlame = d->isdnsseclame; + *rlame = d->rec_lame; *alame = d->lame_type_A; *olame = d->lame_other; lock_rw_unlock(&e->lock); - return *dlame || *alame || *olame; + return *dlame || *rlame || *alame || *olame; } size_t @@ -337,7 +338,7 @@ 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, - uint16_t qtype) + int reclame, uint16_t qtype) { struct infra_host_data* data; struct lruhash_entry* e; @@ -369,8 +370,9 @@ 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); + d->rec_lame = reclame; + d->lame_type_A = (!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A); + d->lame_other = (!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A); k->namelen = namelen; e = infra_lookup_host_nottl(infra, addr, addrlen, 1); if(!e) { @@ -404,11 +406,12 @@ infra_set_lame(struct infra_cache* infra, } } else { /* lookup existing lameness entry (if any) and merge data */ - int dlame, alame, olame; + int dlame, rlame, alame, olame; if(infra_lookup_lame(data, name, namelen, timenow, - &dlame, &alame, &olame)) { + &dlame, &rlame, &alame, &olame)) { /* merge data into new structure */ if(dlame) d->isdnsseclame = 1; + if(rlame) d->rec_lame = 1; if(alame) d->lame_type_A = 1; if(olame) d->lame_other = 1; } @@ -500,38 +503,49 @@ int infra_get_lame_rtt(struct infra_cache* infra, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, size_t namelen, uint16_t qtype, - int* lame, int* dnsseclame, int* rtt, uint32_t timenow) + int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow) { struct infra_host_data* host; struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr, addrlen, 0); - int dlm, alm, olm; + int dlm, rlm, 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(infra_lookup_lame(host, name, namelen, timenow, &dlm, &alm, &olm)) { + if(infra_lookup_lame(host, name, namelen, timenow, + &dlm, &rlm, &alm, &olm)) { if(alm && qtype == LDNS_RR_TYPE_A) { lock_rw_unlock(&e->lock); *lame = 1; *dnsseclame = 0; + *reclame = 0; return 1; } else if(olm && qtype != LDNS_RR_TYPE_A) { lock_rw_unlock(&e->lock); *lame = 1; *dnsseclame = 0; + *reclame = 0; return 1; } else if(dlm) { lock_rw_unlock(&e->lock); *lame = 0; *dnsseclame = 1; + *reclame = 0; + return 1; + } else if(rlm) { + lock_rw_unlock(&e->lock); + *lame = 0; + *dnsseclame = 0; + *reclame = 1; return 1; } /* no lameness for this type of query */ } *lame = 0; *dnsseclame = 0; + *reclame = 0; if(timenow > host->ttl) { lock_rw_unlock(&e->lock); return 0; diff --git a/services/cache/infra.h b/services/cache/infra.h index 6417713c1..fa693cf4e 100644 --- a/services/cache/infra.h +++ b/services/cache/infra.h @@ -98,6 +98,8 @@ 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; + /** is the host recursion lame (not AA, but RA) */ + int rec_lame; /** the host is lame (not authoritative) for A records */ int lame_type_A; /** the host is lame (not authoritative) for other query types */ @@ -187,13 +189,14 @@ int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr, * @param namelen: length of domain name. * @param timenow: what time it is now. * @param dlame: if the function returns true, is set true if dnssec lame. + * @param rlame: if the function returns true, is set true if recursion 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, - int* dlame, int* alame, int* olame); + int* dlame, int* rlame, int* alame, int* olame); /** * Set a host to be lame for the given zone. @@ -205,13 +208,15 @@ 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 reclame: if true host is a recursor not AA server. + * if false, dnsseclame or marked lame. * @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, - uint16_t qtype); + int reclame, uint16_t qtype); /** * Update rtt information for the host. @@ -262,6 +267,7 @@ int infra_edns_update(struct infra_cache* infra, * @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. + * @param reclame: if function returns true, this is if it is recursion lame. * @param rtt: if function returns true, this returns avg rtt of the server. * The rtt value is unclamped and reflects recent timeouts. * @param timenow: what time it is now. @@ -270,7 +276,7 @@ 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, uint16_t qtype, - int* lame, int* dnsseclame, int* rtt, uint32_t timenow); + int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow); /** * Get memory used by the infra cache. diff --git a/services/outside_network.c b/services/outside_network.c index 003dfb902..02f6f7402 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1688,3 +1688,4 @@ serviced_get_mem(struct serviced_query* sq) } return s; } + diff --git a/testcode/unitmain.c b/testcode/unitmain.c index b104fbe98..66fc5c73c 100644 --- a/testcode/unitmain.c +++ b/testcode/unitmain.c @@ -320,7 +320,7 @@ infra_test() struct infra_host_key* k; struct infra_host_data* d; int init = 376; - int dlame, alame, olame; + int dlame, rlame, alame, olame; slab = infra_create(cfg); unit_assert( infra_host(slab, (struct sockaddr_storage*)&one, @@ -345,30 +345,30 @@ infra_test() unit_assert( vs == 0 && to == init && edns_lame == 0 ); unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one, - (socklen_t)sizeof(int), zone, zonelen, now, 0, + (socklen_t)sizeof(int), zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) ); unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one, (socklen_t)sizeof(int), 0, now, &k)) ); unit_assert( d->ttl == now+cfg->host_ttl ); unit_assert( d->edns_version == 0 ); unit_assert( infra_lookup_lame(d, zone, zonelen, now, - &dlame, &alame, &olame) ); - unit_assert(!dlame && alame && !olame); + &dlame, &rlame, &alame, &olame) ); + unit_assert(!dlame && !rlame && alame && !olame); unit_assert( !infra_lookup_lame(d, zone, zonelen, - now+cfg->lame_ttl+10, &dlame, &alame, &olame) ); + now+cfg->lame_ttl+10, &dlame, &rlame, &alame, &olame) ); unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now, - &dlame, &alame, &olame) ); + &dlame, &rlame, &alame, &olame) ); lock_rw_unlock(&k->entry.lock); /* test merge of data */ unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one, - (socklen_t)sizeof(int), zone, zonelen, now, 0, + (socklen_t)sizeof(int), zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) ); unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one, (socklen_t)sizeof(int), 0, now, &k)) ); unit_assert( infra_lookup_lame(d, zone, zonelen, now, - &dlame, &alame, &olame) ); - unit_assert(!dlame && alame && olame); + &dlame, &rlame, &alame, &olame) ); + unit_assert(!dlame && !rlame && alame && olame); lock_rw_unlock(&k->entry.lock); infra_delete(slab); diff --git a/testdata/iter_reclame_one.rpl b/testdata/iter_reclame_one.rpl new file mode 100644 index 000000000..5ab5ddb8a --- /dev/null +++ b/testdata/iter_reclame_one.rpl @@ -0,0 +1,162 @@ +; config options +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with a recursion lame server. +; The scenario has a domain with two servers, one is lame the other doesn't +; so depending on the randomly chosen server that goes first, it may +; select the nonlame or the lame server first. + +; 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 +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 +com. IN NS +SECTION ANSWER +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 +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +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 lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; lame.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR 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 lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 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 lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_reclame_two.rpl b/testdata/iter_reclame_two.rpl new file mode 100644 index 000000000..f6acc278b --- /dev/null +++ b/testdata/iter_reclame_two.rpl @@ -0,0 +1,161 @@ +; config options +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with two recursion lame servers. +; both servers are recursion lame. The iterator tries both servers, +; but they are both lame. Then it concludes that it only has reclame. + +; 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 +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 +com. IN NS +SECTION ANSWER +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 +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR 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 lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; lame.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR 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 lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 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 lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +SCENARIO_END