mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Recursion lame is detected and last resort is used to resolve.
git-svn-id: file:///svn/unbound/trunk@1294 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
5b7a514119
commit
dbaa5194a6
13 changed files with 424 additions and 40 deletions
|
|
@ -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
|
10 October 2008: Wouter
|
||||||
- fixup tests - the negative cache contained the correct NSEC3s for
|
- fixup tests - the negative cache contained the correct NSEC3s for
|
||||||
two tests that are supposed to fail to validate.
|
two tests that are supposed to fail to validate.
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ response_type_from_server(int rdset,
|
||||||
/* make sure its not recursive when we don't want it to */
|
/* make sure its not recursive when we don't want it to */
|
||||||
if( (msg->rep->flags&BIT_RA) &&
|
if( (msg->rep->flags&BIT_RA) &&
|
||||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||||
return RESPONSE_TYPE_LAME;
|
return RESPONSE_TYPE_REC_LAME;
|
||||||
return RESPONSE_TYPE_ANSWER;
|
return RESPONSE_TYPE_ANSWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ response_type_from_server(int rdset,
|
||||||
/* we do our own recursion, thank you */
|
/* we do our own recursion, thank you */
|
||||||
if( (msg->rep->flags&BIT_RA) &&
|
if( (msg->rep->flags&BIT_RA) &&
|
||||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||||
return RESPONSE_TYPE_LAME;
|
return RESPONSE_TYPE_REC_LAME;
|
||||||
return RESPONSE_TYPE_ANSWER;
|
return RESPONSE_TYPE_ANSWER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,13 +222,13 @@ response_type_from_server(int rdset,
|
||||||
* deployed and is responding nonAA */
|
* deployed and is responding nonAA */
|
||||||
if( (msg->rep->flags&BIT_RA) &&
|
if( (msg->rep->flags&BIT_RA) &&
|
||||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||||
return RESPONSE_TYPE_LAME;
|
return RESPONSE_TYPE_REC_LAME;
|
||||||
/* Or if a lame server is deployed,
|
/* Or if a lame server is deployed,
|
||||||
* which gives ns==zone delegation from cache
|
* which gives ns==zone delegation from cache
|
||||||
* without AA bit as well, with nodata nosoa*/
|
* without AA bit as well, with nodata nosoa*/
|
||||||
if(msg->rep->an_numrrsets==0 &&
|
if(msg->rep->an_numrrsets==0 &&
|
||||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||||
return RESPONSE_TYPE_LAME;
|
return RESPONSE_TYPE_REC_LAME;
|
||||||
return RESPONSE_TYPE_ANSWER;
|
return RESPONSE_TYPE_ANSWER;
|
||||||
}
|
}
|
||||||
/* If we are getting a referral upwards (or to
|
/* If we are getting a referral upwards (or to
|
||||||
|
|
@ -259,6 +259,6 @@ response_type_from_server(int rdset,
|
||||||
* be an entirely empty message) */
|
* be an entirely empty message) */
|
||||||
/* check if recursive answer; saying it has empty cache */
|
/* check if recursive answer; saying it has empty cache */
|
||||||
if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
|
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;
|
return RESPONSE_TYPE_ANSWER;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,14 @@ enum response_type {
|
||||||
* 'lame' means that this particular response indicates that
|
* 'lame' means that this particular response indicates that
|
||||||
* the nameserver knew nothing about the question.
|
* 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
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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,
|
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
|
||||||
struct delegpt_addr* a)
|
struct delegpt_addr* a)
|
||||||
{
|
{
|
||||||
int rtt;
|
int rtt, lame, reclame, dnsseclame;
|
||||||
int lame;
|
|
||||||
int dnsseclame;
|
|
||||||
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
|
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
|
||||||
return -1; /* server is on the donotquery list */
|
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 */
|
/* check lameness - need zone , class info */
|
||||||
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
|
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)
|
if(lame)
|
||||||
return -1; /* server is lame */
|
return -1; /* server is lame */
|
||||||
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||||
return -1; /* server is unresponsive */
|
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 */
|
return rtt+USEFUL_SERVER_TOP_TIMEOUT; /* nonpref */
|
||||||
else return rtt;
|
else return rtt;
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +241,8 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||||
struct delegpt_addr*
|
struct delegpt_addr*
|
||||||
iter_server_selection(struct iter_env* iter_env,
|
iter_server_selection(struct iter_env* iter_env,
|
||||||
struct module_env* env, struct delegpt* dp,
|
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 sel;
|
||||||
int selrtt;
|
int selrtt;
|
||||||
|
|
@ -250,8 +252,12 @@ iter_server_selection(struct iter_env* iter_env,
|
||||||
|
|
||||||
if(num == 0)
|
if(num == 0)
|
||||||
return NULL;
|
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;
|
*dnssec_expected = 0;
|
||||||
|
}
|
||||||
if(num == 1) {
|
if(num == 1) {
|
||||||
a = dp->result_list;
|
a = dp->result_list;
|
||||||
if(++a->attempts < OUTBOUND_MSG_RETRY)
|
if(++a->attempts < OUTBOUND_MSG_RETRY)
|
||||||
|
|
|
||||||
|
|
@ -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 qtype: query type that we want to send.
|
||||||
* @param dnssec_expected: set to 0, if a known dnssec-lame server is selected
|
* @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.
|
* 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.
|
* @return best target or NULL if no target.
|
||||||
* if not null, that target is removed from the result list in the dp.
|
* 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 delegpt_addr* iter_server_selection(struct iter_env* iter_env,
|
||||||
struct module_env* env, struct delegpt* dp, uint8_t* name,
|
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.
|
* Allocate dns_msg from parsed msg, in regional.
|
||||||
|
|
|
||||||
|
|
@ -1211,7 +1211,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
/* Select the next usable target, filtering out unsuitable targets. */
|
/* Select the next usable target, filtering out unsuitable targets. */
|
||||||
target = iter_server_selection(ie, qstate->env, iq->dp,
|
target = iter_server_selection(ie, qstate->env, iq->dp,
|
||||||
iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
|
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 no usable target was selected... */
|
||||||
if(!target) {
|
if(!target) {
|
||||||
|
|
@ -1276,7 +1276,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
outq = (*qstate->env->send_query)(
|
outq = (*qstate->env->send_query)(
|
||||||
iq->qchase.qname, iq->qchase.qname_len,
|
iq->qchase.qname, iq->qchase.qname_len,
|
||||||
iq->qchase.qtype, iq->qchase.qclass,
|
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);
|
&target->addr, target->addrlen, qstate);
|
||||||
if(!outq) {
|
if(!outq) {
|
||||||
verbose(VERB_OPS, "error sending query to auth server; "
|
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;
|
enum response_type type;
|
||||||
iq->num_current_queries--;
|
iq->num_current_queries--;
|
||||||
if(iq->response == NULL) {
|
if(iq->response == NULL) {
|
||||||
|
iq->chase_to_rd = 0;
|
||||||
verbose(VERB_ALGO, "query response was timeout");
|
verbose(VERB_ALGO, "query response was timeout");
|
||||||
return next_state(iq, QUERYTARGETS_STATE);
|
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->response, &iq->qchase, iq->dp);
|
||||||
|
iq->chase_to_rd = 0;
|
||||||
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
|
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
|
||||||
/* When forwarding (RD bit is set), we handle referrals
|
/* When forwarding (RD bit is set), we handle referrals
|
||||||
* differently. No queries should be sent elsewhere */
|
* 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)
|
if(iq->dnssec_expected && !(iq->chase_flags&BIT_RD)
|
||||||
&& type != RESPONSE_TYPE_LAME
|
&& type != RESPONSE_TYPE_LAME
|
||||||
|
&& type != RESPONSE_TYPE_REC_LAME
|
||||||
&& type != RESPONSE_TYPE_THROWAWAY
|
&& type != RESPONSE_TYPE_THROWAWAY
|
||||||
&& type != RESPONSE_TYPE_UNTYPED) {
|
&& type != RESPONSE_TYPE_UNTYPED) {
|
||||||
/* a possible answer, see if it is missing DNSSEC */
|
/* 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,
|
if(!infra_set_lame(qstate->env->infra_cache,
|
||||||
&qstate->reply->addr, qstate->reply->addrlen,
|
&qstate->reply->addr, qstate->reply->addrlen,
|
||||||
iq->dp->name, iq->dp->namelen,
|
iq->dp->name, iq->dp->namelen,
|
||||||
*qstate->env->now, dnsseclame,
|
*qstate->env->now, dnsseclame, 0,
|
||||||
iq->qchase.qtype))
|
iq->qchase.qtype))
|
||||||
log_err("mark host lame: out of memory");
|
log_err("mark host lame: out of memory");
|
||||||
} else log_err("%slame response from cache",
|
} else log_err("%slame response from cache",
|
||||||
dnsseclame?"DNSSEC ":"");
|
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) {
|
} else if(type == RESPONSE_TYPE_THROWAWAY) {
|
||||||
/* LAME and THROWAWAY responses are handled the same way.
|
/* LAME and THROWAWAY responses are handled the same way.
|
||||||
* In this case, the event is just sent directly back to
|
* In this case, the event is just sent directly back to
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,8 @@ struct iter_qstate {
|
||||||
struct query_info qchase;
|
struct query_info qchase;
|
||||||
/** query flags to use when chasing the answer (i.e. RD flag) */
|
/** query flags to use when chasing the answer (i.e. RD flag) */
|
||||||
uint16_t chase_flags;
|
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
|
* This is the current delegation point for an in-progress query. This
|
||||||
|
|
|
||||||
34
services/cache/infra.c
vendored
34
services/cache/infra.c
vendored
|
|
@ -266,7 +266,7 @@ hash_lameness(uint8_t* name, size_t namelen)
|
||||||
int
|
int
|
||||||
infra_lookup_lame(struct infra_host_data* host,
|
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)
|
int* dlame, int* rlame, int* alame, int* olame)
|
||||||
{
|
{
|
||||||
struct lruhash_entry* e;
|
struct lruhash_entry* e;
|
||||||
struct infra_lame_key k;
|
struct infra_lame_key k;
|
||||||
|
|
@ -287,10 +287,11 @@ infra_lookup_lame(struct infra_host_data* host,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*dlame = d->isdnsseclame;
|
*dlame = d->isdnsseclame;
|
||||||
|
*rlame = d->rec_lame;
|
||||||
*alame = d->lame_type_A;
|
*alame = d->lame_type_A;
|
||||||
*olame = d->lame_other;
|
*olame = d->lame_other;
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
return *dlame || *alame || *olame;
|
return *dlame || *rlame || *alame || *olame;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
@ -337,7 +338,7 @@ int
|
||||||
infra_set_lame(struct infra_cache* infra,
|
infra_set_lame(struct infra_cache* infra,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
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)
|
int reclame, uint16_t qtype)
|
||||||
{
|
{
|
||||||
struct infra_host_data* data;
|
struct infra_host_data* data;
|
||||||
struct lruhash_entry* e;
|
struct lruhash_entry* e;
|
||||||
|
|
@ -369,8 +370,9 @@ infra_set_lame(struct infra_cache* infra,
|
||||||
k->entry.data = (void*)d;
|
k->entry.data = (void*)d;
|
||||||
d->ttl = timenow + infra->lame_ttl;
|
d->ttl = timenow + infra->lame_ttl;
|
||||||
d->isdnsseclame = dnsseclame;
|
d->isdnsseclame = dnsseclame;
|
||||||
d->lame_type_A = (!dnsseclame && qtype == LDNS_RR_TYPE_A);
|
d->rec_lame = reclame;
|
||||||
d->lame_other = (!dnsseclame && qtype != LDNS_RR_TYPE_A);
|
d->lame_type_A = (!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A);
|
||||||
|
d->lame_other = (!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A);
|
||||||
k->namelen = namelen;
|
k->namelen = namelen;
|
||||||
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
|
||||||
if(!e) {
|
if(!e) {
|
||||||
|
|
@ -404,11 +406,12 @@ infra_set_lame(struct infra_cache* infra,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* lookup existing lameness entry (if any) and merge data */
|
/* 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,
|
if(infra_lookup_lame(data, name, namelen, timenow,
|
||||||
&dlame, &alame, &olame)) {
|
&dlame, &rlame, &alame, &olame)) {
|
||||||
/* merge data into new structure */
|
/* merge data into new structure */
|
||||||
if(dlame) d->isdnsseclame = 1;
|
if(dlame) d->isdnsseclame = 1;
|
||||||
|
if(rlame) d->rec_lame = 1;
|
||||||
if(alame) d->lame_type_A = 1;
|
if(alame) d->lame_type_A = 1;
|
||||||
if(olame) d->lame_other = 1;
|
if(olame) d->lame_other = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -500,38 +503,49 @@ int
|
||||||
infra_get_lame_rtt(struct infra_cache* infra,
|
infra_get_lame_rtt(struct infra_cache* infra,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||||
uint8_t* name, size_t namelen, uint16_t qtype,
|
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 infra_host_data* host;
|
||||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||||
addrlen, 0);
|
addrlen, 0);
|
||||||
int dlm, alm, olm;
|
int dlm, rlm, alm, olm;
|
||||||
if(!e)
|
if(!e)
|
||||||
return 0;
|
return 0;
|
||||||
host = (struct infra_host_data*)e->data;
|
host = (struct infra_host_data*)e->data;
|
||||||
*rtt = rtt_unclamped(&host->rtt);
|
*rtt = rtt_unclamped(&host->rtt);
|
||||||
/* check lameness first, if so, ttl on host does not matter anymore */
|
/* 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) {
|
if(alm && qtype == LDNS_RR_TYPE_A) {
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
*lame = 1;
|
*lame = 1;
|
||||||
*dnsseclame = 0;
|
*dnsseclame = 0;
|
||||||
|
*reclame = 0;
|
||||||
return 1;
|
return 1;
|
||||||
} else if(olm && qtype != LDNS_RR_TYPE_A) {
|
} else if(olm && qtype != LDNS_RR_TYPE_A) {
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
*lame = 1;
|
*lame = 1;
|
||||||
*dnsseclame = 0;
|
*dnsseclame = 0;
|
||||||
|
*reclame = 0;
|
||||||
return 1;
|
return 1;
|
||||||
} else if(dlm) {
|
} else if(dlm) {
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
*lame = 0;
|
*lame = 0;
|
||||||
*dnsseclame = 1;
|
*dnsseclame = 1;
|
||||||
|
*reclame = 0;
|
||||||
|
return 1;
|
||||||
|
} else if(rlm) {
|
||||||
|
lock_rw_unlock(&e->lock);
|
||||||
|
*lame = 0;
|
||||||
|
*dnsseclame = 0;
|
||||||
|
*reclame = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* no lameness for this type of query */
|
/* no lameness for this type of query */
|
||||||
}
|
}
|
||||||
*lame = 0;
|
*lame = 0;
|
||||||
*dnsseclame = 0;
|
*dnsseclame = 0;
|
||||||
|
*reclame = 0;
|
||||||
if(timenow > host->ttl) {
|
if(timenow > host->ttl) {
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
12
services/cache/infra.h
vendored
12
services/cache/infra.h
vendored
|
|
@ -98,6 +98,8 @@ struct infra_lame_data {
|
||||||
/** is the host lame (does not serve the zone authoritatively),
|
/** is the host lame (does not serve the zone authoritatively),
|
||||||
* or is the host dnssec lame (does not serve DNSSEC data) */
|
* or is the host dnssec lame (does not serve DNSSEC data) */
|
||||||
int isdnsseclame;
|
int isdnsseclame;
|
||||||
|
/** is the host recursion lame (not AA, but RA) */
|
||||||
|
int rec_lame;
|
||||||
/** the host is lame (not authoritative) for A records */
|
/** the host is lame (not authoritative) for A records */
|
||||||
int lame_type_A;
|
int lame_type_A;
|
||||||
/** the host is lame (not authoritative) for other query types */
|
/** 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 namelen: length of domain name.
|
||||||
* @param timenow: what time it is now.
|
* @param timenow: what time it is now.
|
||||||
* @param dlame: if the function returns true, is set true if dnssec lame.
|
* @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 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.
|
* @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
|
* @return: 0 if not lame or unknown or timed out, 1 if lame
|
||||||
*/
|
*/
|
||||||
int infra_lookup_lame(struct infra_host_data* host,
|
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);
|
int* dlame, int* rlame, int* alame, int* olame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a host to be lame for the given zone.
|
* 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 timenow: what time it is now.
|
||||||
* @param dnsseclame: if true the host is set dnssec lame.
|
* @param dnsseclame: if true the host is set dnssec lame.
|
||||||
* if false, the host is marked lame (not serving the zone).
|
* 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.
|
* @param qtype: the query type for which it is lame.
|
||||||
* @return: 0 on error.
|
* @return: 0 on error.
|
||||||
*/
|
*/
|
||||||
int infra_set_lame(struct infra_cache* infra,
|
int infra_set_lame(struct infra_cache* infra,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
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);
|
int reclame, uint16_t qtype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update rtt information for the host.
|
* 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 lame: if function returns true, this returns lameness of the zone.
|
||||||
* @param dnsseclame: if function returns true, this returns if the zone
|
* @param dnsseclame: if function returns true, this returns if the zone
|
||||||
* is dnssec-lame.
|
* 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.
|
* @param rtt: if function returns true, this returns avg rtt of the server.
|
||||||
* The rtt value is unclamped and reflects recent timeouts.
|
* The rtt value is unclamped and reflects recent timeouts.
|
||||||
* @param timenow: what time it is now.
|
* @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,
|
int infra_get_lame_rtt(struct infra_cache* infra,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||||
uint8_t* name, size_t namelen, uint16_t qtype,
|
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.
|
* Get memory used by the infra cache.
|
||||||
|
|
|
||||||
|
|
@ -1688,3 +1688,4 @@ serviced_get_mem(struct serviced_query* sq)
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ infra_test()
|
||||||
struct infra_host_key* k;
|
struct infra_host_key* k;
|
||||||
struct infra_host_data* d;
|
struct infra_host_data* d;
|
||||||
int init = 376;
|
int init = 376;
|
||||||
int dlame, alame, olame;
|
int dlame, rlame, alame, olame;
|
||||||
|
|
||||||
slab = infra_create(cfg);
|
slab = infra_create(cfg);
|
||||||
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
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( vs == 0 && to == init && edns_lame == 0 );
|
||||||
|
|
||||||
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
|
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) );
|
LDNS_RR_TYPE_A) );
|
||||||
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
|
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), 0, now, &k)) );
|
(socklen_t)sizeof(int), 0, now, &k)) );
|
||||||
unit_assert( d->ttl == now+cfg->host_ttl );
|
unit_assert( d->ttl == now+cfg->host_ttl );
|
||||||
unit_assert( d->edns_version == 0 );
|
unit_assert( d->edns_version == 0 );
|
||||||
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
|
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
|
||||||
&dlame, &alame, &olame) );
|
&dlame, &rlame, &alame, &olame) );
|
||||||
unit_assert(!dlame && alame && !olame);
|
unit_assert(!dlame && !rlame && alame && !olame);
|
||||||
unit_assert( !infra_lookup_lame(d, zone, zonelen,
|
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,
|
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now,
|
||||||
&dlame, &alame, &olame) );
|
&dlame, &rlame, &alame, &olame) );
|
||||||
lock_rw_unlock(&k->entry.lock);
|
lock_rw_unlock(&k->entry.lock);
|
||||||
|
|
||||||
/* test merge of data */
|
/* test merge of data */
|
||||||
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
|
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) );
|
LDNS_RR_TYPE_AAAA) );
|
||||||
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
|
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), 0, now, &k)) );
|
(socklen_t)sizeof(int), 0, now, &k)) );
|
||||||
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
|
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
|
||||||
&dlame, &alame, &olame) );
|
&dlame, &rlame, &alame, &olame) );
|
||||||
unit_assert(!dlame && alame && olame);
|
unit_assert(!dlame && !rlame && alame && olame);
|
||||||
lock_rw_unlock(&k->entry.lock);
|
lock_rw_unlock(&k->entry.lock);
|
||||||
|
|
||||||
infra_delete(slab);
|
infra_delete(slab);
|
||||||
|
|
|
||||||
162
testdata/iter_reclame_one.rpl
vendored
Normal file
162
testdata/iter_reclame_one.rpl
vendored
Normal file
|
|
@ -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
|
||||||
161
testdata/iter_reclame_two.rpl
vendored
Normal file
161
testdata/iter_reclame_two.rpl
vendored
Normal file
|
|
@ -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
|
||||||
Loading…
Reference in a new issue