Use random (thread safe version).

git-svn-id: file:///svn/unbound/trunk@145 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-02-26 09:42:05 +00:00
parent 7ccdfe8f7c
commit e679f51ed9
6 changed files with 32 additions and 15 deletions

View file

@ -42,6 +42,7 @@
#include "config.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/random.h"
#include "daemon/worker.h"
#include "util/netevent.h"
#include "util/config_file.h"
@ -103,7 +104,7 @@ worker_process_query(struct worker* worker)
worker->query_reply.c->buffer));
pending_udp_query(worker->back, worker->query_reply.c->buffer,
&worker->fwd_addr, worker->fwd_addrlen, UDP_QUERY_TIMEOUT,
worker_handle_reply, worker);
worker_handle_reply, worker, worker->rndstate);
}
/** check request sanity. Returns error code, 0 OK, or -1 discard.
@ -214,6 +215,7 @@ worker_init(struct config_file *cfg, struct listen_port* ports,
{
struct worker* worker = (struct worker*)calloc(1,
sizeof(struct worker));
unsigned int seed;
if(!worker)
return NULL;
worker->need_to_restart = 0;
@ -249,12 +251,14 @@ worker_init(struct config_file *cfg, struct listen_port* ports,
return NULL;
}
/* init random(), large table size. */
if(!(worker->rndstate = (char*)malloc(RND_STATE_SIZE))) {
if(!(worker->rndstate = (struct ub_randstate*)calloc(1,
sizeof(struct ub_randstate)))) {
log_err("malloc rndtable failed.");
worker_delete(worker);
return NULL;
}
if(!initstate(time(NULL)^getpid(), worker->rndstate, RND_STATE_SIZE)) {
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();
if(!ub_initstate(seed, worker->rndstate, RND_STATE_SIZE)) {
log_err("could not init random numbers.");
worker_delete(worker);
return NULL;

View file

@ -51,6 +51,7 @@ struct outside_network;
struct config_file;
struct daemon;
struct listen_port;
struct ub_randstate;
/** size of table used for random numbers. large to be more secure. */
#define RND_STATE_SIZE 256
@ -86,7 +87,7 @@ struct worker {
socklen_t fwd_addrlen;
/** random() table for this worker. */
char* rndstate;
struct ub_randstate* rndstate;
/** do we need to restart (instead of exit) ? */
int need_to_restart;
};

View file

@ -1,3 +1,6 @@
26 February 2007: Wouter
- ub_random code used to select ID and port.
23 February 2007: Wouter
- Can do reloads on sigHUP. Everything is stopped, and freed,
except the listening ports. Then the config file is reread.

View file

@ -45,6 +45,7 @@
#include "util/netevent.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/random.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@ -391,7 +392,8 @@ pending_delete(struct outside_network* outnet, struct pending* p)
static struct pending*
new_pending(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen,
comm_point_callback_t* callback, void* callback_arg)
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* rnd)
{
/* alloc */
int id_tries = 0;
@ -409,7 +411,7 @@ new_pending(struct outside_network* outnet, ldns_buffer* packet,
}
/* set */
/* id uses lousy random() TODO use better and entropy */
pend->id = (random()>>8) & 0xffff;
pend->id = ((unsigned)ub_random(rnd)>>8) & 0xffff;
LDNS_ID_SET(ldns_buffer_begin(packet), pend->id);
memcpy(&pend->addr, addr, addrlen);
pend->addrlen = addrlen;
@ -421,7 +423,7 @@ new_pending(struct outside_network* outnet, ldns_buffer* packet,
pend->node.key = pend;
while(!rbtree_insert(outnet->pending, &pend->node)) {
/* change ID to avoid collision */
pend->id = (random()>>8) & 0xffff;
pend->id = ((unsigned)ub_random(rnd)>>8) & 0xffff;
LDNS_ID_SET(ldns_buffer_begin(packet), pend->id);
id_tries++;
if(id_tries == MAX_ID_RETRY) {
@ -453,9 +455,11 @@ addr_is_ip6(struct sockaddr_storage* addr)
* Select outgoing comm point for a query. Fills in c.
* @param outnet: network structure that has arrays of ports to choose from.
* @param pend: the message to send. c is filled in, randomly chosen.
* @param rnd: random state for generating ID and port.
*/
static void
select_port(struct outside_network* outnet, struct pending* pend)
select_port(struct outside_network* outnet, struct pending* pend,
struct ub_randstate* rnd)
{
double precho;
int chosen, nummax;
@ -473,8 +477,8 @@ select_port(struct outside_network* outnet, struct pending* pend)
}
/* choose a random outgoing port and interface */
/* uses lousy random() function. TODO: entropy source. */
precho = (double)random() * (double)nummax /
/* TODO: entropy source. */
precho = (double)ub_random(rnd) * (double)nummax /
((double)RAND_MAX + 1.0);
chosen = (int)precho;
@ -494,18 +498,19 @@ select_port(struct outside_network* outnet, struct pending* pend)
void
pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* cb, void* cb_arg)
comm_point_callback_t* cb, void* cb_arg, struct ub_randstate* rnd)
{
struct pending* pend;
struct timeval tv;
/* create pending struct and change ID to be unique */
if(!(pend=new_pending(outnet, packet, addr, addrlen, cb, cb_arg))) {
if(!(pend=new_pending(outnet, packet, addr, addrlen, cb, cb_arg,
rnd))) {
/* callback user for the error */
(void)(*cb)(NULL, cb_arg, NETEVENT_CLOSED, NULL);
return;
}
select_port(outnet, pend);
select_port(outnet, pend, rnd);
/* send it over the commlink */
if(!comm_point_send_udp_msg(pend->c, packet, (struct sockaddr*)addr,

View file

@ -48,6 +48,7 @@
#include "util/netevent.h"
struct pending;
struct pending_timeout;
struct ub_randstate;
/**
* Send queries to outside servers and wait for answers from servers.
@ -140,10 +141,12 @@ void outside_network_delete(struct outside_network* outnet);
* The routine does not return an error, instead it calls the callback,
* with an error code if an error happens.
* @param callback_arg: user argument for callback function.
* @param rnd: random state for generating ID and port.
*/
void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg);
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* rnd);
/**
* Delete pending answer.

View file

@ -644,7 +644,8 @@ outside_network_delete(struct outside_network* outnet)
void
pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg)
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* ATTR_UNUSED(rnd))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,