1 /* 2 * gen_uuid.c --- generate a DCE-compatible uuid 3 * 4 * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, and the entire permission notice in its entirety, 12 * including the disclaimer of warranties. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 23 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 30 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 31 * DAMAGE. 32 * %End-Header% 33 */ 34 35 /* 36 * Force inclusion of SVID stuff since we need it if we're compiling in 37 * gcc-wall wall mode 38 */ 39 #define _SVID_SOURCE 40 #define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */ 41 42 #include "config.h" 43 44 #ifdef _WIN32 45 #define _WIN32_WINNT 0x0500 46 #include <windows.h> 47 #define UUID MYUUID 48 #endif 49 #include <stdio.h> 50 #ifdef HAVE_UNISTD_H 51 #include <unistd.h> 52 #endif 53 #ifdef HAVE_STDLIB_H 54 #include <stdlib.h> 55 #endif 56 #include <string.h> 57 #include <fcntl.h> 58 #include <errno.h> 59 #include <sys/types.h> 60 #ifdef HAVE_SYS_TIME_H 61 #include <sys/time.h> 62 #endif 63 #include <sys/wait.h> 64 #include <sys/stat.h> 65 #ifdef HAVE_SYS_FILE_H 66 #include <sys/file.h> 67 #endif 68 #ifdef HAVE_SYS_IOCTL_H 69 #include <sys/ioctl.h> 70 #endif 71 #ifdef HAVE_SYS_SOCKET_H 72 #include <sys/socket.h> 73 #endif 74 #ifdef HAVE_SYS_UN_H 75 #include <sys/un.h> 76 #endif 77 #ifdef HAVE_SYS_SOCKIO_H 78 #include <sys/sockio.h> 79 #endif 80 #ifdef HAVE_NET_IF_H 81 #include <net/if.h> 82 #endif 83 #ifdef HAVE_NETINET_IN_H 84 #include <netinet/in.h> 85 #endif 86 #ifdef HAVE_NET_IF_DL_H 87 #include <net/if_dl.h> 88 #endif 89 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) 90 #include <sys/syscall.h> 91 #endif 92 #ifdef HAVE_SYS_RESOURCE_H 93 #include <sys/resource.h> 94 #endif 95 96 #include "uuidP.h" 97 #include "uuidd.h" 98 99 #ifdef HAVE_SRANDOM 100 #define srand(x) srandom(x) 101 #define rand() random() 102 #endif 103 104 #ifdef TLS 105 #define THREAD_LOCAL static TLS 106 #else 107 #define THREAD_LOCAL static 108 #endif 109 110 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48) 111 #define DO_JRAND_MIX 112 THREAD_LOCAL unsigned short jrand_seed[3]; 113 #endif 114 115 #ifdef _WIN32 116 static void gettimeofday (struct timeval *tv, void *dummy) 117 { 118 FILETIME ftime; 119 uint64_t n; 120 121 GetSystemTimeAsFileTime (&ftime); 122 n = (((uint64_t) ftime.dwHighDateTime << 32) 123 + (uint64_t) ftime.dwLowDateTime); 124 if (n) { 125 n /= 10; 126 n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000; 127 } 128 129 tv->tv_sec = n / 1000000; 130 tv->tv_usec = n % 1000000; 131 } 132 133 static int getuid (void) 134 { 135 return 1; 136 } 137 #endif 138 139 static int get_random_fd(void) 140 { 141 struct timeval tv; 142 static int fd = -2; 143 int i; 144 145 if (fd == -2) { 146 gettimeofday(&tv, 0); 147 #ifndef _WIN32 148 fd = open("/dev/urandom", O_RDONLY); 149 if (fd == -1) 150 fd = open("/dev/random", O_RDONLY | O_NONBLOCK); 151 if (fd >= 0) { 152 i = fcntl(fd, F_GETFD); 153 if (i >= 0) 154 fcntl(fd, F_SETFD, i | FD_CLOEXEC); 155 } 156 #endif 157 srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); 158 #ifdef DO_JRAND_MIX 159 jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); 160 jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF); 161 jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16; 162 #endif 163 } 164 /* Crank the random number generator a few times */ 165 gettimeofday(&tv, 0); 166 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) 167 rand(); 168 return fd; 169 } 170 171 172 /* 173 * Generate a series of random bytes. Use /dev/urandom if possible, 174 * and if not, use srandom/random. 175 */ 176 static void get_random_bytes(void *buf, int nbytes) 177 { 178 int i, n = nbytes, fd = get_random_fd(); 179 int lose_counter = 0; 180 unsigned char *cp = buf; 181 182 if (fd >= 0) { 183 while (n > 0) { 184 i = read(fd, cp, n); 185 if (i <= 0) { 186 if (lose_counter++ > 16) 187 break; 188 continue; 189 } 190 n -= i; 191 cp += i; 192 lose_counter = 0; 193 } 194 } 195 196 /* 197 * We do this all the time, but this is the only source of 198 * randomness if /dev/random/urandom is out to lunch. 199 */ 200 for (cp = buf, i = 0; i < nbytes; i++) 201 *cp++ ^= (rand() >> 7) & 0xFF; 202 #ifdef DO_JRAND_MIX 203 { 204 unsigned short tmp_seed[3]; 205 206 memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed)); 207 jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid); 208 for (cp = buf, i = 0; i < nbytes; i++) 209 *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF; 210 memcpy(jrand_seed, tmp_seed, 211 sizeof(jrand_seed) - sizeof(unsigned short)); 212 } 213 #endif 214 215 return; 216 } 217 218 /* 219 * Get the ethernet hardware address, if we can find it... 220 * 221 * XXX for a windows version, probably should use GetAdaptersInfo: 222 * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 223 * commenting out get_node_id just to get gen_uuid to compile under windows 224 * is not the right way to go! 225 */ 226 static int get_node_id(unsigned char *node_id) 227 { 228 #ifdef HAVE_NET_IF_H 229 int sd; 230 struct ifreq ifr, *ifrp; 231 struct ifconf ifc; 232 char buf[1024]; 233 int n, i; 234 unsigned char *a; 235 #ifdef HAVE_NET_IF_DL_H 236 struct sockaddr_dl *sdlp; 237 #endif 238 239 /* 240 * BSD 4.4 defines the size of an ifreq to be 241 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len 242 * However, under earlier systems, sa_len isn't present, so the size is 243 * just sizeof(struct ifreq) 244 */ 245 #ifdef HAVE_SA_LEN 246 #ifndef max 247 #define max(a,b) ((a) > (b) ? (a) : (b)) 248 #endif 249 #define ifreq_size(i) max(sizeof(struct ifreq),\ 250 sizeof((i).ifr_name)+(i).ifr_addr.sa_len) 251 #else 252 #define ifreq_size(i) sizeof(struct ifreq) 253 #endif /* HAVE_SA_LEN*/ 254 255 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 256 if (sd < 0) { 257 return -1; 258 } 259 memset(buf, 0, sizeof(buf)); 260 ifc.ifc_len = sizeof(buf); 261 ifc.ifc_buf = buf; 262 if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { 263 close(sd); 264 return -1; 265 } 266 n = ifc.ifc_len; 267 for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { 268 ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); 269 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); 270 #ifdef SIOCGIFHWADDR 271 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) 272 continue; 273 a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 274 #else 275 #ifdef SIOCGENADDR 276 if (ioctl(sd, SIOCGENADDR, &ifr) < 0) 277 continue; 278 a = (unsigned char *) ifr.ifr_enaddr; 279 #else 280 #ifdef HAVE_NET_IF_DL_H 281 sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; 282 if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) 283 continue; 284 a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; 285 #else 286 /* 287 * XXX we don't have a way of getting the hardware 288 * address 289 */ 290 close(sd); 291 return 0; 292 #endif /* HAVE_NET_IF_DL_H */ 293 #endif /* SIOCGENADDR */ 294 #endif /* SIOCGIFHWADDR */ 295 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) 296 continue; 297 if (node_id) { 298 memcpy(node_id, a, 6); 299 close(sd); 300 return 1; 301 } 302 } 303 close(sd); 304 #endif 305 return 0; 306 } 307 308 /* Assume that the gettimeofday() has microsecond granularity */ 309 #define MAX_ADJUSTMENT 10 310 311 static int get_clock(uint32_t *clock_high, uint32_t *clock_low, 312 uint16_t *ret_clock_seq, int *num) 313 { 314 THREAD_LOCAL int adjustment = 0; 315 THREAD_LOCAL struct timeval last = {0, 0}; 316 THREAD_LOCAL int state_fd = -2; 317 THREAD_LOCAL FILE *state_f; 318 THREAD_LOCAL uint16_t clock_seq; 319 struct timeval tv; 320 struct flock fl; 321 uint64_t clock_reg; 322 mode_t save_umask; 323 int len; 324 325 if (state_fd == -2) { 326 save_umask = umask(0); 327 state_fd = open("/var/lib/libuuid/clock.txt", 328 O_RDWR|O_CREAT, 0660); 329 (void) umask(save_umask); 330 if (state_fd >= 0) { 331 state_f = fdopen(state_fd, "r+"); 332 if (!state_f) { 333 close(state_fd); 334 state_fd = -1; 335 } 336 } 337 } 338 fl.l_type = F_WRLCK; 339 fl.l_whence = SEEK_SET; 340 fl.l_start = 0; 341 fl.l_len = 0; 342 fl.l_pid = 0; 343 if (state_fd >= 0) { 344 rewind(state_f); 345 while (fcntl(state_fd, F_SETLKW, &fl) < 0) { 346 if ((errno == EAGAIN) || (errno == EINTR)) 347 continue; 348 fclose(state_f); 349 state_fd = -1; 350 break; 351 } 352 } 353 if (state_fd >= 0) { 354 unsigned int cl; 355 unsigned long tv1, tv2; 356 int a; 357 358 if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", 359 &cl, &tv1, &tv2, &a) == 4) { 360 clock_seq = cl & 0x3FFF; 361 last.tv_sec = tv1; 362 last.tv_usec = tv2; 363 adjustment = a; 364 } 365 } 366 367 if ((last.tv_sec == 0) && (last.tv_usec == 0)) { 368 get_random_bytes(&clock_seq, sizeof(clock_seq)); 369 clock_seq &= 0x3FFF; 370 gettimeofday(&last, 0); 371 last.tv_sec--; 372 } 373 374 try_again: 375 gettimeofday(&tv, 0); 376 if ((tv.tv_sec < last.tv_sec) || 377 ((tv.tv_sec == last.tv_sec) && 378 (tv.tv_usec < last.tv_usec))) { 379 clock_seq = (clock_seq+1) & 0x3FFF; 380 adjustment = 0; 381 last = tv; 382 } else if ((tv.tv_sec == last.tv_sec) && 383 (tv.tv_usec == last.tv_usec)) { 384 if (adjustment >= MAX_ADJUSTMENT) 385 goto try_again; 386 adjustment++; 387 } else { 388 adjustment = 0; 389 last = tv; 390 } 391 392 clock_reg = tv.tv_usec*10 + adjustment; 393 clock_reg += ((uint64_t) tv.tv_sec)*10000000; 394 clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; 395 396 if (num && (*num > 1)) { 397 adjustment += *num - 1; 398 last.tv_usec += adjustment / 10; 399 adjustment = adjustment % 10; 400 last.tv_sec += last.tv_usec / 1000000; 401 last.tv_usec = last.tv_usec % 1000000; 402 } 403 404 if (state_fd > 0) { 405 rewind(state_f); 406 len = fprintf(state_f, 407 "clock: %04x tv: %016lu %08lu adj: %08d\n", 408 clock_seq, last.tv_sec, (long)last.tv_usec, 409 adjustment); 410 fflush(state_f); 411 if (ftruncate(state_fd, len) < 0) { 412 fprintf(state_f, " \n"); 413 fflush(state_f); 414 } 415 rewind(state_f); 416 fl.l_type = F_UNLCK; 417 if (fcntl(state_fd, F_SETLK, &fl) < 0) { 418 fclose(state_f); 419 state_fd = -1; 420 } 421 } 422 423 *clock_high = clock_reg >> 32; 424 *clock_low = clock_reg; 425 *ret_clock_seq = clock_seq; 426 return 0; 427 } 428 429 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) 430 static ssize_t read_all(int fd, char *buf, size_t count) 431 { 432 ssize_t ret; 433 ssize_t c = 0; 434 int tries = 0; 435 436 memset(buf, 0, count); 437 while (count > 0) { 438 ret = read(fd, buf, count); 439 if (ret <= 0) { 440 if ((errno == EAGAIN || errno == EINTR || ret == 0) && 441 (tries++ < 5)) 442 continue; 443 return c ? c : -1; 444 } 445 if (ret > 0) 446 tries = 0; 447 count -= ret; 448 buf += ret; 449 c += ret; 450 } 451 return c; 452 } 453 454 /* 455 * Close all file descriptors 456 */ 457 static void close_all_fds(void) 458 { 459 int i, max; 460 461 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 462 max = sysconf(_SC_OPEN_MAX); 463 #elif defined(HAVE_GETDTABLESIZE) 464 max = getdtablesize(); 465 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) 466 struct rlimit rl; 467 468 getrlimit(RLIMIT_NOFILE, &rl); 469 max = rl.rlim_cur; 470 #else 471 max = OPEN_MAX; 472 #endif 473 474 for (i=0; i < max; i++) { 475 close(i); 476 if (i <= 2) 477 open("/dev/null", O_RDWR); 478 } 479 } 480 #endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */ 481 482 #pragma GCC diagnostic push 483 #if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H) 484 #pragma GCC diagnostic ignored "-Wunused-parameter" 485 #endif 486 /* 487 * Try using the uuidd daemon to generate the UUID 488 * 489 * Returns 0 on success, non-zero on failure. 490 */ 491 static int get_uuid_via_daemon(int op, uuid_t out, int *num) 492 { 493 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) 494 char op_buf[64]; 495 int op_len; 496 int s; 497 ssize_t ret; 498 int32_t reply_len = 0, expected = 16; 499 struct sockaddr_un srv_addr; 500 struct stat st; 501 pid_t pid; 502 static const char *uuidd_path = UUIDD_PATH; 503 static int access_ret = -2; 504 static int start_attempts = 0; 505 506 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 507 return -1; 508 509 srv_addr.sun_family = AF_UNIX; 510 strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH); 511 512 if (connect(s, (const struct sockaddr *) &srv_addr, 513 sizeof(struct sockaddr_un)) < 0) { 514 if (access_ret == -2) 515 access_ret = access(uuidd_path, X_OK); 516 if (access_ret == 0) 517 access_ret = stat(uuidd_path, &st); 518 if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0) 519 access_ret = access(UUIDD_DIR, W_OK); 520 if (access_ret == 0 && start_attempts++ < 5) { 521 if ((pid = fork()) == 0) { 522 close_all_fds(); 523 execl(uuidd_path, "uuidd", "-qT", "300", 524 (char *) NULL); 525 exit(1); 526 } 527 (void) waitpid(pid, 0, 0); 528 if (connect(s, (const struct sockaddr *) &srv_addr, 529 sizeof(struct sockaddr_un)) < 0) 530 goto fail; 531 } else 532 goto fail; 533 } 534 op_buf[0] = op; 535 op_len = 1; 536 if (op == UUIDD_OP_BULK_TIME_UUID) { 537 memcpy(op_buf+1, num, sizeof(*num)); 538 op_len += sizeof(*num); 539 expected += sizeof(*num); 540 } 541 542 ret = write(s, op_buf, op_len); 543 if (ret < 1) 544 goto fail; 545 546 ret = read_all(s, (char *) &reply_len, sizeof(reply_len)); 547 if (ret < 0) 548 goto fail; 549 550 if (reply_len != expected) 551 goto fail; 552 553 ret = read_all(s, op_buf, reply_len); 554 555 if (op == UUIDD_OP_BULK_TIME_UUID) 556 memcpy(op_buf+16, num, sizeof(int)); 557 558 memcpy(out, op_buf, 16); 559 560 close(s); 561 return ((ret == expected) ? 0 : -1); 562 563 fail: 564 close(s); 565 #endif 566 return -1; 567 } 568 #pragma GCC diagnostic pop 569 570 void uuid__generate_time(uuid_t out, int *num) 571 { 572 static unsigned char node_id[6]; 573 static int has_init = 0; 574 struct uuid uu; 575 uint32_t clock_mid; 576 577 if (!has_init) { 578 if (get_node_id(node_id) <= 0) { 579 get_random_bytes(node_id, 6); 580 /* 581 * Set multicast bit, to prevent conflicts 582 * with IEEE 802 addresses obtained from 583 * network cards 584 */ 585 node_id[0] |= 0x01; 586 } 587 has_init = 1; 588 } 589 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); 590 uu.clock_seq |= 0x8000; 591 uu.time_mid = (uint16_t) clock_mid; 592 uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; 593 memcpy(uu.node, node_id, 6); 594 uuid_pack(&uu, out); 595 } 596 597 void uuid_generate_time(uuid_t out) 598 { 599 #ifdef TLS 600 THREAD_LOCAL int num = 0; 601 THREAD_LOCAL struct uuid uu; 602 THREAD_LOCAL time_t last_time = 0; 603 time_t now; 604 605 if (num > 0) { 606 now = time(0); 607 if (now > last_time+1) 608 num = 0; 609 } 610 if (num <= 0) { 611 num = 1000; 612 if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID, 613 out, &num) == 0) { 614 last_time = time(0); 615 uuid_unpack(out, &uu); 616 num--; 617 return; 618 } 619 num = 0; 620 } 621 if (num > 0) { 622 uu.time_low++; 623 if (uu.time_low == 0) { 624 uu.time_mid++; 625 if (uu.time_mid == 0) 626 uu.time_hi_and_version++; 627 } 628 num--; 629 uuid_pack(&uu, out); 630 return; 631 } 632 #else 633 if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0) 634 return; 635 #endif 636 637 uuid__generate_time(out, 0); 638 } 639 640 641 void uuid__generate_random(uuid_t out, int *num) 642 { 643 uuid_t buf; 644 struct uuid uu; 645 int i, n; 646 647 if (!num || !*num) 648 n = 1; 649 else 650 n = *num; 651 652 for (i = 0; i < n; i++) { 653 get_random_bytes(buf, sizeof(buf)); 654 uuid_unpack(buf, &uu); 655 656 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; 657 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) 658 | 0x4000; 659 uuid_pack(&uu, out); 660 out += sizeof(uuid_t); 661 } 662 } 663 664 void uuid_generate_random(uuid_t out) 665 { 666 int num = 1; 667 /* No real reason to use the daemon for random uuid's -- yet */ 668 669 uuid__generate_random(out, &num); 670 } 671 672 673 /* 674 * This is the generic front-end to uuid_generate_random and 675 * uuid_generate_time. It uses uuid_generate_random only if 676 * /dev/urandom is available, since otherwise we won't have 677 * high-quality randomness. 678 */ 679 void uuid_generate(uuid_t out) 680 { 681 if (get_random_fd() >= 0) 682 uuid_generate_random(out); 683 else 684 uuid_generate_time(out); 685 } 686