This source file includes following definitions.
- uuid_pack
- uuid_unpack
- uuid_clear
- uuid_compare
- uuid_copy
- uuid_is_null
- uuid_parse
- uuid_unparse
- get_random_fd
- get_random_bytes
- get_node_id
- get_clock
- uuid_generate_random
- uuid_generate_time
- uuid_generate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <crm_internal.h>
26 #include <stdio.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #ifdef HAVE_STDLIB_H
31 # include <stdlib.h>
32 #endif
33 #include <string.h>
34 #include <ctype.h>
35
36 #include <replace_uuid.h>
37
38
39
40
41
42 #include <sys/types.h>
43 #include <sys/time.h>
44 #include <time.h>
45
46
47 #define UUID_VARIANT_NCS 0
48 #define UUID_VARIANT_DCE 1
49 #define UUID_VARIANT_MICROSOFT 2
50 #define UUID_VARIANT_OTHER 3
51
52
53 #define UUID_TYPE_DCE_TIME 1
54 #define UUID_TYPE_DCE_RANDOM 4
55
56
57 #define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
58
59
60
61
62
63 #define longlong long long
64
65
66
67
68 #define TIME_OFFSET_HIGH 0x01B21DD2
69 #define TIME_OFFSET_LOW 0x13814000
70
71 #if (SIZEOF_INT == 4)
72 typedef unsigned int __u32;
73 #elif (SIZEOF_LONG == 4)
74 typedef unsigned long __u32;
75 #endif
76
77 #if (SIZEOF_INT == 2)
78 typedef int __s16;
79 typedef unsigned int __u16;
80 #elif (SIZEOF_SHORT == 2)
81 typedef short __s16;
82 typedef unsigned short __u16;
83 #endif
84
85 typedef unsigned char __u8;
86
87 struct uuid {
88 __u32 time_low;
89 __u16 time_mid;
90 __u16 time_hi_and_version;
91 __u16 clock_seq;
92 __u8 node[6];
93 };
94
95
96
97
98 static void
99 uuid_pack(const struct uuid *uu, uuid_t ptr)
100 {
101 __u32 tmp;
102 unsigned char *out = ptr;
103
104 tmp = uu->time_low;
105 out[3] = (unsigned char)tmp;
106 tmp >>= 8;
107 out[2] = (unsigned char)tmp;
108 tmp >>= 8;
109 out[1] = (unsigned char)tmp;
110 tmp >>= 8;
111 out[0] = (unsigned char)tmp;
112
113 tmp = uu->time_mid;
114 out[5] = (unsigned char)tmp;
115 tmp >>= 8;
116 out[4] = (unsigned char)tmp;
117
118 tmp = uu->time_hi_and_version;
119 out[7] = (unsigned char)tmp;
120 tmp >>= 8;
121 out[6] = (unsigned char)tmp;
122
123 tmp = uu->clock_seq;
124 out[9] = (unsigned char)tmp;
125 tmp >>= 8;
126 out[8] = (unsigned char)tmp;
127
128 memcpy(out + 10, uu->node, 6);
129 }
130
131 static void
132 uuid_unpack(const uuid_t in, struct uuid *uu)
133 {
134 const __u8 *ptr = in;
135 __u32 tmp;
136
137 tmp = *ptr++;
138 tmp = (tmp << 8) | *ptr++;
139 tmp = (tmp << 8) | *ptr++;
140 tmp = (tmp << 8) | *ptr++;
141 uu->time_low = tmp;
142
143 tmp = *ptr++;
144 tmp = (tmp << 8) | *ptr++;
145 uu->time_mid = tmp;
146
147 tmp = *ptr++;
148 tmp = (tmp << 8) | *ptr++;
149 uu->time_hi_and_version = tmp;
150
151 tmp = *ptr++;
152 tmp = (tmp << 8) | *ptr++;
153 uu->clock_seq = tmp;
154
155 memcpy(uu->node, ptr, 6);
156 }
157
158
159
160
161 void
162 uuid_clear(uuid_t uu)
163 {
164 memset(uu, 0, 16);
165 }
166
167 int
168 uuid_compare(const uuid_t uu1, const uuid_t uu2)
169 {
170 struct uuid uuid1, uuid2;
171
172 uuid_unpack(uu1, &uuid1);
173 uuid_unpack(uu2, &uuid2);
174
175 UUCMP(uuid1.time_low, uuid2.time_low);
176 UUCMP(uuid1.time_mid, uuid2.time_mid);
177 UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
178 UUCMP(uuid1.clock_seq, uuid2.clock_seq);
179 return memcmp(uuid1.node, uuid2.node, 6);
180 }
181
182 void
183 uuid_copy(uuid_t dst, const uuid_t src)
184 {
185 unsigned char *cp1;
186 const unsigned char *cp2;
187 int i;
188
189 for (i = 0, cp1 = dst, cp2 = src; i < 16; i++)
190 *cp1++ = *cp2++;
191 }
192
193
194 int
195 uuid_is_null(const uuid_t uu)
196 {
197 const unsigned char *cp;
198 int i;
199
200 for (i = 0, cp = uu; i < 16; i++)
201 if (*cp++)
202 return 0;
203 return 1;
204 }
205
206
207 int
208 uuid_parse(const char *in, uuid_t uu)
209 {
210 struct uuid uuid;
211 int i;
212 const char *cp;
213 char buf[3];
214
215 if (strlen(in) != 36)
216 return -1;
217 for (i = 0, cp = in; i <= 36; i++, cp++) {
218 if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
219 if (*cp == '-')
220 continue;
221 else
222 return -1;
223 }
224 if (i == 36)
225 if (*cp == 0)
226 continue;
227 if (!isxdigit((int)*cp))
228 return -1;
229 }
230 uuid.time_low = strtoul(in, NULL, 16);
231 uuid.time_mid = strtoul(in + 9, NULL, 16);
232 uuid.time_hi_and_version = strtoul(in + 14, NULL, 16);
233 uuid.clock_seq = strtoul(in + 19, NULL, 16);
234 cp = in + 24;
235 buf[2] = 0;
236 for (i = 0; i < 6; i++) {
237 buf[0] = *cp++;
238 buf[1] = *cp++;
239 uuid.node[i] = strtoul(buf, NULL, 16);
240 }
241
242 uuid_pack(&uuid, uu);
243 return 0;
244 }
245
246
247 void
248 uuid_unparse(const uuid_t uu, char *out)
249 {
250 struct uuid uuid;
251
252 uuid_unpack(uu, &uuid);
253 sprintf(out,
254 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
255 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
256 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
257 uuid.node[0], uuid.node[1], uuid.node[2], uuid.node[3], uuid.node[4], uuid.node[5]);
258 }
259
260
261
262
263
264 #include <fcntl.h>
265 #include <sys/types.h>
266 #include <sys/stat.h>
267
268 #ifdef HAVE_SYS_IOCTL_H
269 # include <sys/ioctl.h>
270 #endif
271 #ifdef HAVE_SYS_SOCKET_H
272 # include <sys/socket.h>
273 #endif
274 #ifdef HAVE_SYS_SOCKIO_H
275 # include <sys/sockio.h>
276 #endif
277 #ifdef HAVE_NET_IF_H
278 # include <net/if.h>
279 #endif
280 #ifdef HAVE_NETINET_IN_H
281 # include <netinet/in.h>
282 #endif
283
284 #ifdef HAVE_SRANDOM
285 # define srand(x) srandom(x)
286 # define rand() random()
287 #endif
288
289 static int
290 get_random_fd(void)
291 {
292 struct timeval tv;
293 static int fd = -2;
294 int i;
295
296 if (fd == -2) {
297 gettimeofday(&tv, 0);
298 fd = open("/dev/urandom", O_RDONLY);
299 if (fd == -1)
300 fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
301 srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
302 }
303
304 gettimeofday(&tv, 0);
305 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
306 rand();
307 return fd;
308 }
309
310
311
312
313
314 static void
315 get_random_bytes(void *buf, int nbytes)
316 {
317 int i, n = nbytes, fd = get_random_fd();
318 int lose_counter = 0;
319 unsigned char *cp = (unsigned char *)buf;
320
321 if (fd >= 0) {
322 while (n > 0) {
323 i = read(fd, cp, n);
324 if (i <= 0) {
325 if (lose_counter++ > 16)
326 break;
327 continue;
328 }
329 n -= i;
330 cp += i;
331 lose_counter = 0;
332 }
333 }
334
335
336
337
338
339 for (cp = buf, i = 0; i < nbytes; i++)
340 *cp++ ^= (rand() >> 7) & 0xFF;
341 return;
342 }
343
344
345
346
347 static int
348 get_node_id(unsigned char *node_id)
349 {
350 #ifdef HAVE_NET_IF_H
351 int sd;
352 struct ifreq ifr, *ifrp;
353 struct ifconf ifc;
354 char buf[1024];
355 int n, i;
356 unsigned char *a;
357
358
359
360
361
362
363
364 # ifdef HAVE_SA_LEN
365 # ifndef max
366 # define max(a,b) ((a) > (b) ? (a) : (b))
367 # endif
368 # define ifreq_size(i) max(sizeof(struct ifreq),\
369 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
370 # else
371 # define ifreq_size(i) sizeof(struct ifreq)
372 # endif
373
374 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
375 if (sd < 0) {
376 return -1;
377 }
378 memset(buf, 0, sizeof(buf));
379 ifc.ifc_len = sizeof(buf);
380 ifc.ifc_buf = buf;
381 if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0) {
382 close(sd);
383 return -1;
384 }
385 n = ifc.ifc_len;
386 for (i = 0; i < n; i += ifreq_size(*ifr)) {
387 ifrp = (struct ifreq *)((char *)ifc.ifc_buf + i);
388 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
389 # ifdef SIOCGIFHWADDR
390 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
391 continue;
392 a = (unsigned char *)&ifr.ifr_hwaddr.sa_data;
393 # else
394 # ifdef SIOCGENADDR
395 if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
396 continue;
397 a = (unsigned char *)ifr.ifr_enaddr;
398 # else
399
400
401
402
403 close(sd);
404 return 0;
405 # endif
406 # endif
407 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
408 continue;
409 if (node_id) {
410 memcpy(node_id, a, 6);
411 close(sd);
412 return 1;
413 }
414 }
415 close(sd);
416 #endif
417 return 0;
418 }
419
420
421 #define MAX_ADJUSTMENT 10
422
423 static int
424 get_clock(__u32 * clock_high, __u32 * clock_low, __u16 * ret_clock_seq)
425 {
426 static int adjustment = 0;
427 static struct timeval last = { 0, 0 };
428 static __u16 clock_seq;
429 struct timeval tv;
430 unsigned longlong clock_reg;
431
432 try_again:
433 gettimeofday(&tv, 0);
434 if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
435 get_random_bytes(&clock_seq, sizeof(clock_seq));
436 clock_seq &= 0x1FFF;
437 last = tv;
438 last.tv_sec--;
439 }
440 if ((tv.tv_sec < last.tv_sec) || ((tv.tv_sec == last.tv_sec) && (tv.tv_usec < last.tv_usec))) {
441 clock_seq = (clock_seq + 1) & 0x1FFF;
442 adjustment = 0;
443 last = tv;
444 } else if ((tv.tv_sec == last.tv_sec) && (tv.tv_usec == last.tv_usec)) {
445 if (adjustment >= MAX_ADJUSTMENT)
446 goto try_again;
447 adjustment++;
448 } else {
449 adjustment = 0;
450 last = tv;
451 }
452
453 clock_reg = tv.tv_usec * 10 + adjustment;
454 clock_reg += ((unsigned longlong)tv.tv_sec) * 10000000;
455 clock_reg += (((unsigned longlong)0x01B21DD2) << 32) + 0x13814000;
456
457 *clock_high = clock_reg >> 32;
458 *clock_low = clock_reg;
459 *ret_clock_seq = clock_seq;
460 return 0;
461 }
462
463
464 void
465 uuid_generate_random(uuid_t out)
466 {
467 uuid_t buf;
468 struct uuid uu;
469
470 get_random_bytes(buf, sizeof(buf));
471 uuid_unpack(buf, &uu);
472
473 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
474 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
475 uuid_pack(&uu, out);
476 }
477
478
479 static void
480 uuid_generate_time(uuid_t out)
481 {
482 static unsigned char node_id[6];
483 static int has_init = 0;
484 struct uuid uu;
485 __u32 clock_mid;
486
487 if (!has_init) {
488 if (get_node_id(node_id) <= 0) {
489 get_random_bytes(node_id, 6);
490
491
492
493
494
495 node_id[0] |= 0x80;
496 }
497 has_init = 1;
498 }
499 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
500 uu.clock_seq |= 0x8000;
501 uu.time_mid = (__u16) clock_mid;
502 uu.time_hi_and_version = (clock_mid >> 16) | 0x1000;
503 memcpy(uu.node, node_id, 6);
504 uuid_pack(&uu, out);
505 }
506
507 void
508 uuid_generate(uuid_t out)
509 {
510 if (get_random_fd() >= 0) {
511 uuid_generate_random(out);
512 } else {
513 uuid_generate_time(out);
514 }
515 }