diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 4951033073..fff0826d64 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -47,7 +47,7 @@ OBJS = @ISC_EXTRA_OBJS@ \ assertions.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \ bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ heap.@O@ \ lex.@O@ lib.@O@ log.@O@ \ - mem.@O@ mutexblock.@O@ result.@O@ rwlock.@O@ \ + mem.@O@ mutexblock.@O@ random.@O@ result.@O@ rwlock.@O@ \ serial.@O@ sockaddr.@O@ str.@O@ symtab.@O@ task.@O@ timer.@O@ \ version.@O@ \ ${UNIXOBJS} ${NLSOBJS} ${PTHREADOBJS} @@ -57,7 +57,7 @@ SRCS = @ISC_EXTRA_SRCS@ \ assertions.c base64.c bitstring.c buffer.c \ bufferlist.c commandline.c error.c event.c heap.c \ lex.c lib.c log.c \ - mem.c mutexblock.c result.c rwlock.c \ + mem.c mutexblock.c random.c result.c rwlock.c \ serial.c sockaddr.c str.c symtab.c task.c timer.c \ version.c diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h new file mode 100644 index 0000000000..16743b1917 --- /dev/null +++ b/lib/isc/include/isc/random.h @@ -0,0 +1,69 @@ +#ifndef ISC_RANDOM_H +#define ISC_RANDOM_H 1 + +#include +#include +#include +#include + +/* + * Implements a random state pool which will let the caller return a + * series of possibly non-reproducable random values. Note that the + * strength of these numbers is not all that high, and should not be + * used in cryptography functions. + */ + +ISC_LANG_BEGINDECLS + +typedef struct { + unsigned int magic; +#if 0 + isc_mutex_t lock; +#endif +} isc_random_t; +#define ISC_RANDOM_MAGIC 0x52416e64 /* RAnd. */ +#define ISC_RANDOM_VALID(x) ((x) != NULL && (x->magic) == ISC_RANDOM_MAGIC) + +isc_result_t isc_random_init(isc_random_t *r); +/* + * Initialize a random state. + * + * This function must be called before using any of the following functions. + * + * Requires: + * r != NULL. + */ + +isc_result_t isc_random_invalidate(isc_random_t *r); +/* + * Invalidate a random state. This will wipe any information contained in + * the state and make it unusable. + * + * Requires: + * r be a valid pool. + */ + +void isc_random_seed(isc_random_t *r, isc_uint32_t seed); +/* + * Set the initial seed of the random state. Note that on some systems + * the private state isn't all that private, and setting the seed may + * alter numbers returned to other state pools. + * + * Requires: + * r be a valid pool. + */ + +void isc_random_get(isc_random_t *r, isc_uint32_t *val); +/* + * Get a random value. Note that on some systems the private state isn't + * all that private, and getting a value may alter what other state pools + * would have returned. + * + * Requires: + * r be a valid pool. + * val != NULL. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_RANDOM_H */ diff --git a/lib/isc/random.c b/lib/isc/random.c new file mode 100644 index 0000000000..12181fa590 --- /dev/null +++ b/lib/isc/random.c @@ -0,0 +1,97 @@ +/* + * Wrapper around the ANSI rand() function. + */ +#include + +#include +#include + +#include +#include +#include +#include + +#include "util.h" + +static isc_once_t once = ISC_ONCE_INIT; +static isc_mutex_t rand_lock; + +static void +initialize_rand(void) +{ + RUNTIME_CHECK(isc_mutex_init(&rand_lock) == ISC_R_SUCCESS); +} + +static void +initialize(void) +{ + RUNTIME_CHECK(isc_once_do(&once, initialize_rand) == ISC_R_SUCCESS); +} + +isc_result_t +isc_random_init(isc_random_t *r) +{ + REQUIRE(r != NULL); + + r->magic = ISC_RANDOM_MAGIC; +#if 0 + return (isc_mutex_init(&r->lock)); +#else + return (ISC_R_SUCCESS); +#endif +} + +isc_result_t +isc_random_invalidate(isc_random_t *r) +{ + isc_result_t result; + + REQUIRE(ISC_RANDOM_VALID(r)); + +#if 0 + result = isc_mutex_destroy(&r->lock); +#else + result = ISC_R_SUCCESS; +#endif + + memset(r, 0, sizeof(isc_random_t)); + + return (result); +} + +void +isc_random_seed(isc_random_t *r, isc_uint32_t seed) +{ + REQUIRE(ISC_RANDOM_VALID(r)); + + initialize(); + +#if 0 + LOCK(&r->lock); +#endif + LOCK(&rand_lock); + srand(seed); + UNLOCK(&rand_lock); +#if 0 + UNLOCK(&r->lock); +#endif +} + +void +isc_random_get(isc_random_t *r, isc_uint32_t *val) +{ + REQUIRE(ISC_RANDOM_VALID(r)); + REQUIRE(val != NULL); + + initialize(); + +#if 0 + LOCK(&r->lock); +#endif + LOCK(&rand_lock); + *val = rand(); + UNLOCK(&rand_lock); +#if 0 + UNLOCK(&r->lock); +#endif +}