1 /* Copyright © 2012 Brandon L Black <blblack@gmail.com>
2  *
3  * This file is part of gdnsd.
4  *
5  * gdnsd is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * gdnsd is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with gdnsd.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef GDNSD_MISC_H
21 #define GDNSD_MISC_H
22 
23 #include <gdnsd/compiler.h>
24 #include <gdnsd/dmn.h>
25 
26 #include <inttypes.h>
27 #include <stdbool.h>
28 #include <pthread.h>
29 #include <dirent.h>
30 #include <sys/types.h>
31 
32 typedef struct _gdnsd_rstate32_t {
33     uint32_t x;
34     uint32_t y;
35     uint32_t z;
36     uint32_t w;
37     uint32_t c;
38 } gdnsd_rstate32_t;
39 
40 typedef struct _gdnsd_rstate64_t {
41     uint64_t x;
42     uint64_t y;
43     uint32_t z1;
44     uint32_t c1;
45     uint32_t z2;
46     uint32_t c2;
47 } gdnsd_rstate64_t;
48 
49 #pragma GCC visibility push(default)
50 
51 // Get system/filesystem-specific dirent buffer size for readdir_r() safely
52 //   (dirname is just for error output)
53 // readdir_r() is being deprecated in libc/POSIX in favor of assuming readdir() is
54 //   thread-safe for different streams, and using your own locking for
55 //   multi-thread access to the same stream.  Therefore this function is
56 //   deprecated as well.
57 F_NONNULL F_DEPRECATED
58 size_t gdnsd_dirent_bufsize(DIR* d V_UNUSED, const char* dirname);
59 
60 // Register a child process that exists for the life of the daemon, so that
61 //   the core can SIGTERM and reap it on clean shutdown.
62 void gdnsd_register_child_pid(pid_t child);
63 
64 // allocate a new string, concatenating s1 + s2.
65 // retval is the new string
66 // if s2_offs is not NULL, *s2_offs will be set
67 //   to the offset of the copy of s2 within the retval.
68 F_MALLOC F_NONNULLX(1,2)
69 char* gdnsd_str_combine(const char* s1, const char* s2, const char** s2_offs);
70 
71 // allocate a new string and concatenate all "count" strings
72 //   from the args list into it.
73 F_MALLOC F_NONNULL
74 char* gdnsd_str_combine_n(const unsigned count, ...);
75 
76 // set thread name (via pthread_setname_np or similar)
77 void gdnsd_thread_setname(const char* n);
78 
79 // Returns true if running on Linux with a kernel version >= x.y.z
80 // Returns false for non-Linux systems, or Linux kernels older than specified.
81 bool gdnsd_linux_min_version(const unsigned x, const unsigned y, const unsigned z);
82 
83 // State initializers for gdnsd_randXX_get() below
84 gdnsd_rstate32_t* gdnsd_rand32_init(void);
85 gdnsd_rstate64_t* gdnsd_rand64_init(void);
86 
87 // scale an unsigned by a double in the range [0.0 - 1.0]
88 //   and get the ceiling of the result.  Cannot overflow.
89 F_UNUSED F_CONST
90 unsigned gdnsd_uscale_ceil(unsigned v, double s);
91 
92 #pragma GCC visibility pop
93 
94 // downcase an array of bytes of known length
95 F_NONNULL F_UNUSED
gdnsd_downcase_bytes(char * bytes,unsigned len)96 static void gdnsd_downcase_bytes(char* bytes, unsigned len) {
97     for(unsigned i = 0; i < len; i++)
98         if(unlikely((bytes[i] < 0x5B) && (bytes[i] > 0x40)))
99             bytes[i] |= 0x20;
100 }
101 
102 // downcase an asciiz string
103 F_NONNULL F_UNUSED
gdnsd_downcase_str(char * str)104 static void gdnsd_downcase_str(char* str) {
105     while(*str) {
106         if(unlikely((*str < 0x5B) && (*str > 0x40)))
107             *str |= 0x20;
108         str++;
109     }
110 }
111 
112 /***************
113  * These are Public-Domain JKISS32/JLKISS64 PRNG implementations
114  *   which I initially got from David Jones' RNG paper here:
115  *   http://www.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf
116  *   ... and then incorporated some usage/optimization hints from
117  *   https://github.com/bhickey/librng
118  * The actual algorithms ultimately came from George Marsaglia.
119  * I've made cosmetic modifications (style, C99) and given them a
120  *  state pointer for threading, and renamed them into the gdnsd API
121  *  namespace so they can be swapped out easily later.
122  * I've also wrapped everything up such that there's one
123  *  global PRNG initialized at startup from decent sources,
124  *  which is mutex-protected and used to set seeds for later
125  *  runtime per-thread/plugin PRNG initializations.
126  ***************/
127 
128 /* Note there are separate 64-bit and 32-bit interfaces here.
129  * Both have periods sufficient for this software in general,
130  *   given an analysis of high end per-thread DNS query rates and
131  *   daemon uptimes, etc.  The 32-bit one is faster and should
132  *   be used by default.
133  * The 64-bit one is supplied for cases (such as plugin_weighted)
134  *   where the result is being used in an integer modulo operation
135  *   with unpredictable mod values which could be large enough to
136  *   induce bias with the 32-bit one.
137  * For "gdnsd_rand32_get() % N":
138  *     maxN -> bias
139  *     ----    ----
140  *     2^24 -> 0.39%
141  *     2^28 -> 6.25%
142  *     2^29 -> 12.5%
143  *     2^30 -> 25%
144  * ... whereas rand64_get() will have an almost immeasurably small
145  *   bias for modvals up to 2^32.
146  */
147 
148 // This is JLKISS64
149 F_NONNULL F_UNUSED
gdnsd_rand64_get(gdnsd_rstate64_t * rs)150 static uint64_t gdnsd_rand64_get(gdnsd_rstate64_t* rs) {
151     rs->x = 1490024343005336237ULL * rs->x + 123456789;
152 
153     uint64_t y = rs->y;
154     y ^= y << 21;
155     y ^= y >> 17;
156     y ^= y << 30;
157     rs->y = y;
158 
159     uint64_t t = 4294584393ULL * rs->z1 + rs->c1;
160     rs->c1 = t >> 32;
161     rs->z1 = t;
162 
163     t = 4246477509ULL * rs->z2 + rs->c2;
164     rs->c2 = t >> 32;
165     rs->z2 = t;
166 
167     return rs->x + y + rs->z1 + ((uint64_t)rs->z2 << 32);
168 }
169 
170 // This is JKISS32
171 F_NONNULL F_UNUSED
gdnsd_rand32_get(gdnsd_rstate32_t * rs)172 static uint32_t gdnsd_rand32_get(gdnsd_rstate32_t* rs) {
173     uint32_t y = rs->y;
174     y ^= y << 5;
175     y ^= y >> 7;
176     y ^= y << 22;
177     rs->y = y;
178 
179     // Note local mods to how t is handled (results are the same)
180     uint32_t t = rs->z + rs->w + rs->c;
181     rs->z = rs->w;
182     rs->c = (t & 1U << 31) >> 31;
183     rs->w = t & 2147483647;
184 
185     rs->x += 1411392427;
186 
187     return rs->x + y + rs->w;
188 }
189 
190 /***************
191  * End PRNG Stuff
192  ***************/
193 
194 // gdnsd_lookup2 is lookup2() by Bob Jenkins,
195 //   from http://www.burtleburtle.net/bob/c/lookup2.c,
196 //   which is in the public domain.
197 // It's just been reformatted/styled to match my code.
198 
199 #define mix(a,b,c) { \
200     a -= b; a -= c; a ^= (c>>13); \
201     b -= c; b -= a; b ^= (a<<8);  \
202     c -= a; c -= b; c ^= (b>>13); \
203     a -= b; a -= c; a ^= (c>>12); \
204     b -= c; b -= a; b ^= (a<<16); \
205     c -= a; c -= b; c ^= (b>>5);  \
206     a -= b; a -= c; a ^= (c>>3);  \
207     b -= c; b -= a; b ^= (a<<10); \
208     c -= a; c -= b; c ^= (b>>15); \
209 }
210 
211 F_PURE F_UNUSED F_WUNUSED
gdnsd_lookup2(const uint8_t * k,uint32_t len)212 static uint32_t gdnsd_lookup2(const uint8_t *k, uint32_t len) {
213     dmn_assert(k || !len);
214 
215     const uint32_t orig_len = len;
216 
217     uint32_t a = 0x9e3779b9;
218     uint32_t b = 0x9e3779b9;
219     uint32_t c = 0xdeadbeef;
220 
221     while(len >= 12) {
222         a += (k[0] + ((uint32_t)k[1]  << 8)
223                    + ((uint32_t)k[2]  << 16)
224                    + ((uint32_t)k[3]  << 24));
225         b += (k[4] + ((uint32_t)k[5]  << 8)
226                    + ((uint32_t)k[6]  << 16)
227                    + ((uint32_t)k[7]  << 24));
228         c += (k[8] + ((uint32_t)k[9]  << 8)
229                    + ((uint32_t)k[10] << 16)
230                    + ((uint32_t)k[11] << 24));
231         mix(a,b,c);
232         k += 12; len -= 12;
233     }
234 
235     c += orig_len;
236 
237     switch(len) {
238         case 11: c += ((uint32_t)k[10] << 24);
239         case 10: c += ((uint32_t)k[9]  << 16);
240         case 9 : c += ((uint32_t)k[8]  << 8);
241         case 8 : b += ((uint32_t)k[7]  << 24);
242         case 7 : b += ((uint32_t)k[6]  << 16);
243         case 6 : b += ((uint32_t)k[5]  << 8);
244         case 5 : b += k[4];
245         case 4 : a += ((uint32_t)k[3]  << 24);
246         case 3 : a += ((uint32_t)k[2]  << 16);
247         case 2 : a += ((uint32_t)k[1]  << 8);
248         case 1 : a += k[0];
249         default: break;
250     }
251 
252     mix(a,b,c);
253     return c;
254 }
255 
256 #endif // GDNSD_MISC_H
257