]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Fixed random numbers for port, interface and server selection.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Mar 2010 14:42:22 +0000 (14:42 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Mar 2010 14:42:22 +0000 (14:42 +0000)
Removed very small bias.
Also some lint fixes.

git-svn-id: file:///svn/unbound/trunk@2049 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/daemon.c
doc/Changelog
iterator/iter_utils.c
pythonmod/pythonmod.c
services/outside_network.c
testcode/unitmain.c
util/random.c
util/random.h
validator/autotrust.c

index fb293b50664e54e7e970d6fb1a9c0dc4acefe408..5657a8b2ed7a32ee95aaf979166f96d4c65e4337 100644 (file)
@@ -292,7 +292,7 @@ int daemon_get_shufport(struct daemon* daemon, int* shufport)
         /* Knuth shuffle */
        n = avail;
        while(--n > 0) {
-               k = ub_random(daemon->rand) % (n+1); /* 0<= k<= n */
+               k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */
                temp = shufport[k];
                shufport[k] = shufport[n];
                shufport[n] = temp;
index 64033a6983a35a380c3be1f60f13c1fcaf141074..6ada462d7b316d49fce14a9ef5772e5993c87593 100644 (file)
@@ -1,3 +1,7 @@
+18 March 2010: Wouter
+       - Fixed random numbers for port, interface and server selection.
+         Removed very small bias.
+
 16 March 2010: Wouter
        - Fix interface-automatic for OpenBSD: msg.controllen was too small,
          also assertions on ancillary data buffer.
index cd000da37105839943b222655e8f47346188a8d6..a706e6b6489d1c3fb65aabc5f06a72d38e4db0c9 100644 (file)
@@ -350,9 +350,9 @@ iter_server_selection(struct iter_env* iter_env,
 
        /* randomly select a target from the list */
        log_assert(num > 1);
-       /* we do not need secure random numbers here, but
-        * we do need it to be threadsafe, so we use this */
-       sel = ub_random(env->rnd) % num
+       /* grab secure random number, to pick unexpected server.
+        * also we need it to be threadsafe. */
+       sel = ub_random_max(env->rnd, num)
        a = dp->result_list;
        prev = NULL;
        while(sel > 0 && a) {
@@ -418,7 +418,7 @@ iter_ns_probability(struct ub_randstate* rnd, int n, int m)
                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
+       sel = ub_random_max(rnd, m)
        return (sel < n);
 }
 
index 579b82ab3c4eff85b35221e3c30070cd643a4411..1753869e50e23a0f629aad1e7818582fe786a120 100644 (file)
@@ -57,6 +57,8 @@
 
 #ifdef S_SPLINT_S
 typedef struct PyObject PyObject;
+typedef struct PyThreadState PyThreadState;
+typedef void* PyGILState_STATE;
 #endif
 
 /**
index 02eead896b7352bdbf3b3dfae3bb21a378df0dce..e1c5265d7329a1073322a685fb4fc0fbb8ed9ec4 100644 (file)
@@ -809,9 +809,9 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
        log_assert(outnet->unused_fds);
        tries = 0;
        while(1) {
-               my_if = ub_random(outnet->rnd) % num_if;
+               my_if = ub_random_max(outnet->rnd, num_if);
                pif = &ifs[my_if];
-               my_port = ub_random(outnet->rnd) % pif->avail_total;
+               my_port = ub_random_max(outnet->rnd, pif->avail_total);
                if(my_port < pif->inuse) {
                        /* port already open */
                        pend->pc = pif->out[my_port];
index 4f7e8125a36e834a001f301417a7cd8e95bbc209..9105afb881f0569205a8b7ee0a1b28bfaa08d49e 100644 (file)
@@ -447,10 +447,12 @@ static void
 rnd_test()
 {
        struct ub_randstate* r;
-       int num = 100, i;
-       long int a[100];
+       int num = 1000, i;
+       long int a[1000];
+       unsigned int seed = (unsigned)time(NULL);
        unit_show_feature("ub_random");
-       unit_assert( (r = ub_initstate((unsigned)time(NULL), NULL)) );
+       printf("ub_random seed is %u\n", seed);
+       unit_assert( (r = ub_initstate(seed, NULL)) );
        for(i=0; i<num; i++) {
                a[i] = ub_random(r);
                unit_assert(a[i] >= 0);
@@ -460,6 +462,14 @@ rnd_test()
                                a[i] != a[i-3] || a[i] != a[i-4] ||
                                a[i] != a[i-5] || a[i] != a[i-6]);
        }
+       a[0] = ub_random_max(r, 1);
+       unit_assert(a[0] >= 0 && a[0] < 1);
+       a[0] = ub_random_max(r, 10000);
+       unit_assert(a[0] >= 0 && a[0] < 10000);
+       for(i=0; i<num; i++) {
+               a[i] = ub_random_max(r, 10);
+               unit_assert(a[i] >= 0 && a[i] < 10);
+       }
        ub_randfree(r);
 }
 
index 4b387fe49b3e92a9467cdd146280e9beaaebc20c..1458104fe34e0da38d4a0a45cd990334c99b40c1 100644 (file)
@@ -177,6 +177,18 @@ ub_random(struct ub_randstate* s)
        return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
 }
 
+long int
+ub_random_max(struct ub_randstate* state, long int x)
+{
+       /* make sure we fetch in a range that is divisible by x. ignore
+        * values from d .. MAX_VALUE, instead draw a new number */
+       long int d = MAX_VALUE - (MAX_VALUE % x); /* d is divisible by x */
+       long int v = ub_random(state);
+       while(d <= v)
+               v = ub_random(state);
+       return (v % x);
+}
+
 void 
 ub_randfree(struct ub_randstate* s)
 {
index 62e3033a717f5c6f11d98d3d1329dc61ddc1b531..400141a186d19373f9eac4c51d96d2f38828a050 100644 (file)
@@ -75,6 +75,15 @@ struct ub_randstate* ub_initstate(unsigned int seed,
  */
 long int ub_random(struct ub_randstate* state);
 
+/**
+ * Generate random number between 0 and x-1.  No modulo bias.
+ * @param state: must have been initialised with ub_initstate.
+ * @param x: an upper limit. not negative or zero. must be smaller than 2**31.
+ * @return: random value between 0..x-1. Possibly more than one
+ * random number is picked from the random stream to satisfy this.
+ */
+long int ub_random_max(struct ub_randstate* state, long int x);
+
 /**
  * Delete the random state.
  * @param state: to delete.
index 4e90862ce810efbf2458dd85948077d6ee3d5968..578a63f4607fbbfd766006dce2622bf8f2f594bd 100644 (file)
@@ -1685,7 +1685,7 @@ calc_next_probe(struct module_env* env, uint32_t wait)
                wait = 3600;
        rnd = wait/10;
        rest = wait-rnd;
-       rnd = (uint32_t)ub_random(env->rnd) % rnd;
+       rnd = (uint32_t)ub_random_max(env->rnd, (long int)rnd);
        return (time_t)(*env->now + rest + rnd);
 }