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