/src/ntp-dev/lib/isc/random.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") |
3 | | * Copyright (C) 1999-2003 Internet Software Consortium. |
4 | | * |
5 | | * Permission to use, copy, modify, and/or distribute this software for any |
6 | | * purpose with or without fee is hereby granted, provided that the above |
7 | | * copyright notice and this permission notice appear in all copies. |
8 | | * |
9 | | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH |
10 | | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
11 | | * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, |
12 | | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
13 | | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
14 | | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
15 | | * PERFORMANCE OF THIS SOFTWARE. |
16 | | */ |
17 | | |
18 | | /* $Id: random.c,v 1.28 2009/07/16 05:52:46 marka Exp $ */ |
19 | | |
20 | | /*! \file */ |
21 | | |
22 | | #include <config.h> |
23 | | |
24 | | #include <stdlib.h> |
25 | | #include <time.h> /* Required for time(). */ |
26 | | #ifdef HAVE_SYS_TYPES_H |
27 | | #include <sys/types.h> |
28 | | #endif |
29 | | #ifdef HAVE_UNISTD_H |
30 | | #include <unistd.h> |
31 | | #endif |
32 | | |
33 | | #include <isc/mutex.h> |
34 | | #include <isc/once.h> |
35 | | #include <isc/random.h> |
36 | | #include <isc/string.h> |
37 | | #include <isc/util.h> |
38 | | |
39 | | static isc_once_t once = ISC_ONCE_INIT; |
40 | | |
41 | | static void |
42 | | initialize_rand(void) |
43 | 0 | { |
44 | 0 | #ifndef HAVE_ARC4RANDOM |
45 | 0 | unsigned int pid = getpid(); |
46 | | |
47 | | /* |
48 | | * The low bits of pid generally change faster. |
49 | | * Xor them with the high bits of time which change slowly. |
50 | | */ |
51 | 0 | pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff); |
52 | |
|
53 | 0 | srand(time(NULL) ^ pid); |
54 | 0 | #endif |
55 | 0 | } |
56 | | |
57 | | static void |
58 | | initialize(void) |
59 | 0 | { |
60 | 0 | RUNTIME_CHECK(isc_once_do(&once, initialize_rand) == ISC_R_SUCCESS); |
61 | 0 | } |
62 | | |
63 | | void |
64 | | isc_random_seed(isc_uint32_t seed) |
65 | 0 | { |
66 | 0 | initialize(); |
67 | |
|
68 | 0 | #ifndef HAVE_ARC4RANDOM |
69 | 0 | srand(seed); |
70 | | #else |
71 | | arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t)); |
72 | | #endif |
73 | 0 | } |
74 | | |
75 | | void |
76 | | isc_random_get(isc_uint32_t *val) |
77 | 0 | { |
78 | 0 | REQUIRE(val != NULL); |
79 | | |
80 | 0 | initialize(); |
81 | |
|
82 | 0 | #ifndef HAVE_ARC4RANDOM |
83 | | /* |
84 | | * rand()'s lower bits are not random. |
85 | | * rand()'s upper bit is zero. |
86 | | */ |
87 | 0 | #if RAND_MAX >= 0xfffff |
88 | | /* We have at least 20 bits. Use lower 16 excluding lower most 4 */ |
89 | 0 | *val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000); |
90 | | #elif RAND_MAX >= 0x7fff |
91 | | /* We have at least 15 bits. Use lower 10/11 excluding lower most 4 */ |
92 | | *val = ((rand() >> 4) & 0x000007ff) | ((rand() << 7) & 0x003ff800) | |
93 | | ((rand() << 18) & 0xffc00000); |
94 | | #else |
95 | | #error RAND_MAX is too small |
96 | | #endif |
97 | | #else |
98 | | *val = arc4random(); |
99 | | #endif |
100 | 0 | } |
101 | | |
102 | | isc_uint32_t |
103 | 0 | isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) { |
104 | 0 | isc_uint32_t rnd; |
105 | |
|
106 | 0 | REQUIRE(jitter < max || (jitter == 0 && max == 0)); |
107 | | |
108 | 0 | if (jitter == 0) |
109 | 0 | return (max); |
110 | | |
111 | 0 | isc_random_get(&rnd); |
112 | 0 | return (max - rnd % jitter); |
113 | 0 | } |