Fixed random numbers for port, interface and server selection.

Removed very small bias.
Also some lint fixes.



git-svn-id: file:///svn/unbound/trunk@2049 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2010-03-18 14:42:22 +00:00
parent cd57530efd
commit 75565262f7
9 changed files with 48 additions and 11 deletions

View 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;

View 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.

View 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);
}

View file

@ -57,6 +57,8 @@
#ifdef S_SPLINT_S
typedef struct PyObject PyObject;
typedef struct PyThreadState PyThreadState;
typedef void* PyGILState_STATE;
#endif
/**

View 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];

View 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);
}

View 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)
{

View 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.

View 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);
}