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 "config.h"
#include "util/log.h" #include "util/log.h"
#include "util/net_help.h" #include "util/net_help.h"
#include "util/random.h"
#include "daemon/worker.h" #include "daemon/worker.h"
#include "util/netevent.h" #include "util/netevent.h"
#include "util/config_file.h" #include "util/config_file.h"
@ -103,7 +104,7 @@ worker_process_query(struct worker* worker)
worker->query_reply.c->buffer)); worker->query_reply.c->buffer));
pending_udp_query(worker->back, 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->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. /** 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, struct worker* worker = (struct worker*)calloc(1,
sizeof(struct worker)); sizeof(struct worker));
unsigned int seed;
if(!worker) if(!worker)
return NULL; return NULL;
worker->need_to_restart = 0; worker->need_to_restart = 0;
@ -249,12 +251,14 @@ worker_init(struct config_file *cfg, struct listen_port* ports,
return NULL; return NULL;
} }
/* init random(), large table size. */ /* 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."); log_err("malloc rndtable failed.");
worker_delete(worker); worker_delete(worker);
return NULL; 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."); log_err("could not init random numbers.");
worker_delete(worker); worker_delete(worker);
return NULL; return NULL;

View file

@ -51,6 +51,7 @@ struct outside_network;
struct config_file; struct config_file;
struct daemon; struct daemon;
struct listen_port; struct listen_port;
struct ub_randstate;
/** size of table used for random numbers. large to be more secure. */ /** size of table used for random numbers. large to be more secure. */
#define RND_STATE_SIZE 256 #define RND_STATE_SIZE 256
@ -86,7 +87,7 @@ struct worker {
socklen_t fwd_addrlen; socklen_t fwd_addrlen;
/** random() table for this worker. */ /** random() table for this worker. */
char* rndstate; struct ub_randstate* rndstate;
/** do we need to restart (instead of exit) ? */ /** do we need to restart (instead of exit) ? */
int need_to_restart; 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 23 February 2007: Wouter
- Can do reloads on sigHUP. Everything is stopped, and freed, - Can do reloads on sigHUP. Everything is stopped, and freed,
except the listening ports. Then the config file is reread. except the listening ports. Then the config file is reread.

View file

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

View file

@ -48,6 +48,7 @@
#include "util/netevent.h" #include "util/netevent.h"
struct pending; struct pending;
struct pending_timeout; struct pending_timeout;
struct ub_randstate;
/** /**
* Send queries to outside servers and wait for answers from servers. * 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, * The routine does not return an error, instead it calls the callback,
* with an error code if an error happens. * with an error code if an error happens.
* @param callback_arg: user argument for callback function. * @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, void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout, 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. * Delete pending answer.

View file

@ -644,7 +644,8 @@ outside_network_delete(struct outside_network* outnet)
void void
pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout, 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 replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1, struct fake_pending* pend = (struct fake_pending*)calloc(1,