From e679f51ed92941f21d4bcf22d98eb7d06ce42d1f Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Mon, 26 Feb 2007 09:42:05 +0000 Subject: [PATCH] Use random (thread safe version). git-svn-id: file:///svn/unbound/trunk@145 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/worker.c | 10 +++++++--- daemon/worker.h | 3 ++- doc/Changelog | 3 +++ services/outside_network.c | 23 ++++++++++++++--------- services/outside_network.h | 5 ++++- testcode/fake_event.c | 3 ++- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 620c39118..210af5dad 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -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; diff --git a/daemon/worker.h b/daemon/worker.h index 7458e0a2a..666cd3e08 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -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; }; diff --git a/doc/Changelog b/doc/Changelog index d566e5026..3456b983d 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/services/outside_network.c b/services/outside_network.c index 57063212a..132b7c88b 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -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 @@ -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, diff --git a/services/outside_network.h b/services/outside_network.h index d1fe8da5d..5aaecec58 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -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. diff --git a/testcode/fake_event.c b/testcode/fake_event.c index cec9c7c46..c62d33430 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -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, -- 2.47.2