mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Use random (thread safe version).
git-svn-id: file:///svn/unbound/trunk@145 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
7ccdfe8f7c
commit
e679f51ed9
6 changed files with 32 additions and 15 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue