]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
shuffle NS selection randomly for getting addresses.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Jul 2007 09:25:55 +0000 (09:25 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Jul 2007 09:25:55 +0000 (09:25 +0000)
git-svn-id: file:///svn/unbound/trunk@436 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iter_delegpt.c
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c

index 555795af49450d692d69f9530dd1a6f770c15209..7e7fb9433d21c3dc8dedeec47c1fdd6d5488a378 100644 (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.
 
index e27328d4b0e314380fcade428ef31fbc20dc045c..f0038b288aba64d7d12e2be58f9514ece47bb70f 100644 (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;
 }
-
index 300c22e91acf2d3fbda075c92fd17bdef73d137e..53f3c3343326f84321db7f01898c6f604a700a95 100644 (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);
+}
index 89f6f160830b55ae703288194ead9da88ab139c5..dacd954784a4e51e9ae6d003038a70d9c7f6af2a 100644 (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 */
index f4bbee8abb57cd2fb875fbc20a9588c7bf68d873..5f339ed86ce108b9a40f53edfabe02a8036f6c07 100644 (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 */
 }
 
 /**