shuffle NS selection randomly for getting addresses.

git-svn-id: file:///svn/unbound/trunk@436 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-07-19 09:25:55 +00:00
parent 59501db3bd
commit 55630293b9
5 changed files with 57 additions and 18 deletions

View file

@ -1,3 +1,6 @@
19 July 2007: Wouter
- shuffle NS selection when getting nameserver target addresses.
18 July 2007: Wouter
- do not query addresses, 127.0.0.1, and ::1 by default.

View file

@ -99,6 +99,17 @@ delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name)
(void)dname_count_size_labels(name, &ns->namelen);
ns->name = region_alloc_init(region, name, ns->namelen);
ns->resolved = 0;
/* Sanity check: if the target name is at or *below* the
* delegation point itself, then this will be (potentially)
* unresolvable. This is the one case where glue *must*
* have been present.
* FIXME: at this point, this *may* be resolvable, so
* perhaps we should issue the query anyway and let it fail.*/
if(dname_subdomain_c(ns->name, dp->name)) {
ns->resolved = 1;
}
return 1;
}
@ -374,4 +385,3 @@ delegpt_add_rrset(struct delegpt* dp, struct region* region,
log_warn("Unknown rrset type added to delegpt");
return 1;
}

View file

@ -341,3 +341,15 @@ iter_dns_store(struct module_env* env, struct dns_msg* msg, int is_referral)
}
return 1;
}
int
iter_ns_probability(struct ub_randstate* rnd, int n, int m)
{
int sel;
if(n == m) /* 100% chance */
return 1;
/* we do not need secure random numbers here, but
* we do need it to be threadsafe, so we use this */
sel = ub_random(rnd) % m;
return (sel < n);
}

View file

@ -49,6 +49,7 @@ struct delegpt_addr;
struct delegpt;
struct region;
struct msg_parse;
struct ub_randstate;
/**
* Process config options and set iterator module state.
@ -105,4 +106,14 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct region* region);
int iter_dns_store(struct module_env* env, struct dns_msg* msg,
int is_referral);
/**
* Select randomly with n/m probability.
* For shuffle NS records for address fetching.
* @param rnd: random table
* @param n: probability.
* @param m: divisor for probability.
* @return true with n/m probability.
*/
int iter_ns_probability(struct ub_randstate* rnd, int n, int m);
#endif /* ITERATOR_ITER_UTILS_H */

View file

@ -803,29 +803,34 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id, int maxtargets, int* num)
{
int query_count = 0;
int target_count = 0;
struct delegpt_ns* ns = iq->dp->nslist;
int missing = (int)delegpt_count_missing_targets(iq->dp);
int toget = 0;
log_assert(maxtargets != 0); /* that would not be useful */
/* Generate target requests. Basically, any missing targets
* are queried for here, regardless if it is necessary to do
* so to continue processing. */
if(maxtargets < 0 || maxtargets > missing)
toget = missing;
else toget = maxtargets;
if(toget == 0) {
*num = 0;
return 1;
}
/* select 'toget' items from the total of 'missing' items */
log_assert(toget <= missing);
/* loop over missing targets */
for(ns = iq->dp->nslist; ns; ns = ns->next) {
if(ns->resolved)
continue;
/* Sanity check: if the target name is at or *below* the
* delegation point itself, then this will be (potentially)
* unresolvable. This is the one case where glue *must*
* have been present.
* FIXME: at this point, this *may* be resolvable, so
* perhaps we should issue the query anyway and let it fail.*/
if(dname_subdomain_c(ns->name, iq->dp->name)) {
log_nametypeclass(VERB_DETAIL, "skipping target name "
"because it should have been glue", ns->name,
LDNS_RR_TYPE_NS, iq->qchase.qclass);
/* randomly select this item with probability toget/missing */
if(!iter_ns_probability(qstate->env->rnd, toget, missing)) {
/* do not select this one, next; select toget number
* of items from a list one less in size */
missing --;
continue;
}
@ -846,10 +851,9 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
/* mark this target as in progress. */
ns->resolved = 1;
/* if maxtargets is negative, there is no maximum,
* otherwise only query for ntarget names. */
if(maxtargets >= 0 && ++target_count >= maxtargets)
missing--;
toget--;
if(toget == 0)
break;
}
*num = query_count;
@ -1286,6 +1290,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
rrset = reply_find_answer_rrset(&iq->qchase, iq->response->rep);
if(rrset) {
/* if CNAMEs have been followed - add new NS to delegpt. */
/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
rrset->rk.dname_len)) {
if(!delegpt_add_ns(foriq->dp, forq->region,
@ -1295,8 +1300,6 @@ processTargetResponse(struct module_qstate* qstate, int id,
if(!delegpt_add_rrset(foriq->dp, forq->region, rrset))
log_err("out of memory adding targets");
} else dpns->resolved = 1; /* fail the target */
log_assert(dpns->resolved); /* one way or another it is now done */
}
/**