File indexing completed on 2025-05-11 08:24:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038
0039
0040
0041
0042
0043 #define _SVID_SOURCE
0044
0045 #ifdef _WIN32
0046 #define _WIN32_WINNT 0x0500
0047 #include <windows.h>
0048 #define UUID MYUUID
0049 #endif
0050 #include <stdio.h>
0051 #include <limits.h> /* for CHAR_BIT */
0052 #ifdef HAVE_UNISTD_H
0053 #include <unistd.h>
0054 #endif
0055 #ifdef HAVE_STDLIB_H
0056 #include <stdlib.h>
0057 #endif
0058 #include <string.h>
0059 #include <fcntl.h>
0060 #include <errno.h>
0061 #include <sys/types.h>
0062 #ifdef HAVE_SYS_TIME_H
0063 #include <sys/time.h>
0064 #endif
0065 #include <sys/wait.h>
0066 #include <sys/stat.h>
0067 #ifdef HAVE_SYS_FILE_H
0068 #include <sys/file.h>
0069 #endif
0070 #ifdef HAVE_SYS_IOCTL_H
0071 #include <sys/ioctl.h>
0072 #endif
0073 #ifdef HAVE_SYS_SOCKET_H
0074 #include <sys/socket.h>
0075 #endif
0076 #ifdef HAVE_SYS_UN_H
0077 #include <sys/un.h>
0078 #endif
0079 #ifdef HAVE_SYS_SOCKIO_H
0080 #include <sys/sockio.h>
0081 #endif
0082 #ifdef HAVE_NET_IF_H
0083 #include <net/if.h>
0084 #endif
0085 #ifdef HAVE_NETINET_IN_H
0086 #include <netinet/in.h>
0087 #endif
0088 #ifdef HAVE_NET_IF_DL_H
0089 #include <net/if_dl.h>
0090 #endif
0091 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
0092 #include <sys/syscall.h>
0093 #endif
0094 #ifdef HAVE_SYS_RESOURCE_H
0095 #include <sys/resource.h>
0096 #endif
0097
0098 #if SIZEOF_TIME_T == 8
0099 #define PRIutime_t PRIu64
0100 #define SCNutime_t SCNu64
0101 #define utime_t uint64_t
0102 #elif SIZEOF_TIME_T == 4
0103 #define PRIutime_t PRIu32
0104 #define SCNutime_t SCNu32
0105 #define utime_t uint32_t
0106 #else
0107 #error "unsupport size of time_t"
0108 #endif
0109
0110 #include "uuidP.h"
0111 #include "uuidd.h"
0112
0113 #ifdef HAVE_SRANDOM
0114 #define srand(x) srandom(x)
0115 #define rand() random()
0116 #endif
0117
0118 #ifdef TLS
0119 #define THREAD_LOCAL static TLS
0120 #else
0121 #define THREAD_LOCAL static
0122 #endif
0123
0124 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
0125 #define DO_JRAND_MIX
0126 THREAD_LOCAL unsigned short jrand_seed[3];
0127 #endif
0128
0129 #ifdef _WIN32
0130 static void gettimeofday (struct timeval *__restrict tv, void *__restrict dummy)
0131 {
0132 FILETIME ftime;
0133 uint64_t n;
0134
0135 GetSystemTimeAsFileTime (&ftime);
0136 n = (((uint64_t) ftime.dwHighDateTime << 32)
0137 + (uint64_t) ftime.dwLowDateTime);
0138 if (n) {
0139 n /= 10;
0140 n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000;
0141 }
0142
0143 tv->tv_sec = n / 1000000;
0144 tv->tv_usec = n % 1000000;
0145 }
0146
0147 static int getuid (void)
0148 {
0149 return 1;
0150 }
0151 #endif
0152
0153 static int get_random_fd(void)
0154 {
0155 struct timeval tv;
0156 static int fd = -2;
0157 int i;
0158
0159 if (fd == -2) {
0160 gettimeofday(&tv, 0);
0161 #ifndef _WIN32
0162 fd = open("/dev/urandom", O_RDONLY);
0163 if (fd == -1)
0164 fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
0165 if (fd >= 0) {
0166 i = fcntl(fd, F_GETFD);
0167 if (i >= 0)
0168 #ifdef __rtems__
0169 (void)
0170 #endif
0171 fcntl(fd, F_SETFD, i | FD_CLOEXEC);
0172 }
0173 #endif
0174 #ifdef __rtems__
0175 srand((((time_t)getpid()) << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid()
0176 ^ tv.tv_sec ^ tv.tv_usec);
0177 #else
0178 srand((getpid() << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
0179 #endif
0180 #ifdef DO_JRAND_MIX
0181 jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
0182 jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
0183 jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
0184 #endif
0185 }
0186
0187 gettimeofday(&tv, 0);
0188 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
0189 rand();
0190 return fd;
0191 }
0192
0193
0194
0195
0196
0197
0198 static void get_random_bytes(void *buf, int nbytes)
0199 {
0200 int i, n = nbytes, fd = get_random_fd();
0201 int lose_counter = 0;
0202 unsigned char *cp = (unsigned char *) buf;
0203 #ifdef DO_JRAND_MIX
0204 unsigned short tmp_seed[3];
0205 #endif
0206
0207 if (fd >= 0) {
0208 while (n > 0) {
0209 i = read(fd, cp, n);
0210 if (i <= 0) {
0211 if (lose_counter++ > 16)
0212 break;
0213 continue;
0214 }
0215 n -= i;
0216 cp += i;
0217 lose_counter = 0;
0218 }
0219 }
0220
0221
0222
0223
0224
0225 for (cp = buf, i = 0; i < nbytes; i++)
0226 *cp++ ^= (rand() >> 7) & 0xFF;
0227 #ifdef DO_JRAND_MIX
0228 memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
0229 jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
0230 for (cp = buf, i = 0; i < nbytes; i++)
0231 *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
0232 memcpy(jrand_seed, tmp_seed,
0233 sizeof(jrand_seed)-sizeof(unsigned short));
0234 #endif
0235
0236 return;
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 static int get_node_id(unsigned char *node_id)
0248 {
0249 #ifdef HAVE_NET_IF_H
0250 int sd;
0251 struct ifreq ifr, *ifrp;
0252 struct ifconf ifc;
0253 char buf[1024];
0254 int n, i;
0255 unsigned char *a;
0256 #ifdef HAVE_NET_IF_DL_H
0257 struct sockaddr_dl *sdlp;
0258 #endif
0259
0260
0261
0262
0263
0264
0265
0266 #ifdef HAVE_SA_LEN
0267 #ifndef max
0268 #define max(a,b) ((a) > (b) ? (a) : (b))
0269 #endif
0270 #define ifreq_size(i) max(sizeof(struct ifreq),\
0271 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
0272 #else
0273 #define ifreq_size(i) sizeof(struct ifreq)
0274 #endif
0275
0276 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
0277 if (sd < 0) {
0278 return -1;
0279 }
0280 memset(buf, 0, sizeof(buf));
0281 ifc.ifc_len = sizeof(buf);
0282 ifc.ifc_buf = buf;
0283 if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
0284 close(sd);
0285 return -1;
0286 }
0287 n = ifc.ifc_len;
0288 for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
0289 ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
0290 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
0291 #ifdef SIOCGIFHWADDR
0292 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
0293 continue;
0294 a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
0295 #else
0296 #ifdef SIOCGENADDR
0297 if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
0298 continue;
0299 a = (unsigned char *) ifr.ifr_enaddr;
0300 #else
0301 #ifdef HAVE_NET_IF_DL_H
0302 sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
0303 if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
0304 continue;
0305 a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
0306 #else
0307
0308
0309
0310
0311 close(sd);
0312 return 0;
0313 #endif
0314 #endif
0315 #endif
0316 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
0317 continue;
0318 if (node_id) {
0319 memcpy(node_id, a, 6);
0320 close(sd);
0321 return 1;
0322 }
0323 }
0324 close(sd);
0325 #endif
0326 return 0;
0327 }
0328
0329
0330 #define MAX_ADJUSTMENT 10
0331
0332 static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
0333 uint16_t *ret_clock_seq, int *num)
0334 {
0335 THREAD_LOCAL int adjustment = 0;
0336 THREAD_LOCAL struct timeval last = {0, 0};
0337 THREAD_LOCAL int state_fd = -2;
0338 THREAD_LOCAL FILE *state_f;
0339 THREAD_LOCAL uint16_t clock_seq;
0340 struct timeval tv;
0341 struct flock fl;
0342 uint64_t clock_reg;
0343 mode_t save_umask;
0344 int len;
0345
0346 if (state_fd == -2) {
0347 save_umask = umask(0);
0348 state_fd = open("/var/lib/libuuid/clock.txt",
0349 O_RDWR|O_CREAT, 0660);
0350 (void) umask(save_umask);
0351 #ifdef __rtems__
0352 if (state_fd >= 0) {
0353 #endif
0354 state_f = fdopen(state_fd, "r+");
0355 if (!state_f) {
0356 close(state_fd);
0357 state_fd = -1;
0358 }
0359 #ifdef __rtems__
0360 }
0361 #endif
0362 }
0363 fl.l_type = F_WRLCK;
0364 fl.l_whence = SEEK_SET;
0365 fl.l_start = 0;
0366 fl.l_len = 0;
0367 fl.l_pid = 0;
0368 if (state_fd >= 0) {
0369 rewind(state_f);
0370 while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
0371 if ((errno == EAGAIN) || (errno == EINTR))
0372 continue;
0373 fclose(state_f);
0374 close(state_fd);
0375 state_fd = -1;
0376 break;
0377 }
0378 }
0379 if (state_fd >= 0) {
0380 unsigned int cl;
0381 utime_t tv1;
0382 unsigned long tv2;
0383 int a;
0384
0385 if (fscanf(state_f, "clock: %04x tv: %" SCNutime_t " %lu adj: %d\n",
0386 &cl, &tv1, &tv2, &a) == 4) {
0387 clock_seq = cl & 0x3FFF;
0388 last.tv_sec = tv1;
0389 last.tv_usec = tv2;
0390 adjustment = a;
0391 }
0392 }
0393
0394 if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
0395 get_random_bytes(&clock_seq, sizeof(clock_seq));
0396 clock_seq &= 0x3FFF;
0397 gettimeofday(&last, 0);
0398 last.tv_sec--;
0399 }
0400
0401 try_again:
0402 gettimeofday(&tv, 0);
0403 if ((tv.tv_sec < last.tv_sec) ||
0404 ((tv.tv_sec == last.tv_sec) &&
0405 (tv.tv_usec < last.tv_usec))) {
0406 clock_seq = (clock_seq+1) & 0x3FFF;
0407 adjustment = 0;
0408 last = tv;
0409 } else if ((tv.tv_sec == last.tv_sec) &&
0410 (tv.tv_usec == last.tv_usec)) {
0411 if (adjustment >= MAX_ADJUSTMENT)
0412 goto try_again;
0413 adjustment++;
0414 } else {
0415 adjustment = 0;
0416 last = tv;
0417 }
0418
0419 clock_reg = ((uint64_t) tv.tv_usec)*10 + adjustment;
0420 clock_reg += ((uint64_t) tv.tv_sec)*10000000;
0421 clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
0422
0423 if (num && (*num > 1)) {
0424 adjustment += *num - 1;
0425 last.tv_usec += adjustment / 10;
0426 adjustment = adjustment % 10;
0427 last.tv_sec += last.tv_usec / 1000000;
0428 last.tv_usec = last.tv_usec % 1000000;
0429 }
0430
0431 if (state_fd > 0) {
0432 rewind(state_f);
0433 len = fprintf(state_f,
0434 "clock: %04x tv: %016" PRIutime_t " %08lu adj: %08d\n",
0435 clock_seq, last.tv_sec, last.tv_usec, adjustment);
0436 fflush(state_f);
0437 if (ftruncate(state_fd, len) < 0) {
0438 fprintf(state_f, " \n");
0439 fflush(state_f);
0440 }
0441 rewind(state_f);
0442 fl.l_type = F_UNLCK;
0443 #ifdef __rtems__
0444 (void)
0445 #endif
0446 fcntl(state_fd, F_SETLK, &fl);
0447 }
0448
0449 *clock_high = clock_reg >> 32;
0450 *clock_low = clock_reg;
0451 *ret_clock_seq = clock_seq;
0452 return 0;
0453 }
0454
0455
0456 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
0457 static ssize_t read_all(int fd, char *buf, size_t count)
0458 {
0459 ssize_t ret;
0460 ssize_t c = 0;
0461
0462 memset(buf, 0, count);
0463 while (count > 0) {
0464 ret = read(fd, buf, count);
0465 if (ret < 0) {
0466 if ((errno == EAGAIN) || (errno == EINTR))
0467 continue;
0468 return -1;
0469 }
0470 count -= ret;
0471 buf += ret;
0472 c += ret;
0473 }
0474 return c;
0475 }
0476 #endif
0477
0478 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
0479
0480
0481
0482
0483 static void close_all_fds(void)
0484 {
0485 int i, max;
0486
0487 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
0488 max = sysconf(_SC_OPEN_MAX);
0489 #elif defined(HAVE_GETDTABLESIZE)
0490 max = getdtablesize();
0491 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
0492 struct rlimit rl;
0493
0494 getrlimit(RLIMIT_NOFILE, &rl);
0495 max = rl.rlim_cur;
0496 #else
0497 max = OPEN_MAX;
0498 #endif
0499
0500 for (i=0; i < max; i++)
0501 close(i);
0502 }
0503
0504 #endif
0505
0506
0507
0508
0509
0510
0511
0512 static int get_uuid_via_daemon(int op, uuid_t out, int *num)
0513 {
0514 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
0515 char op_buf[64];
0516 int op_len;
0517 int s;
0518 ssize_t ret;
0519 int32_t reply_len = 0, expected = 16;
0520 struct sockaddr_un srv_addr;
0521 pid_t pid;
0522 static const char *uuidd_path = UUIDD_PATH;
0523 static int access_ret = -2;
0524 static int start_attempts = 0;
0525
0526 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
0527 return -1;
0528
0529 srv_addr.sun_family = AF_UNIX;
0530 strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
0531
0532 if (connect(s, (const struct sockaddr *) &srv_addr,
0533 sizeof(struct sockaddr_un)) < 0) {
0534 if (access_ret == -2)
0535 access_ret = access(uuidd_path, X_OK);
0536 if (access_ret == 0 && start_attempts++ < 5) {
0537 if ((pid = fork()) == 0) {
0538 close_all_fds();
0539 execl(uuidd_path, "uuidd", "-qT", "300",
0540 (char *) NULL);
0541 exit(1);
0542 }
0543 (void) waitpid(pid, 0, 0);
0544 if (connect(s, (const struct sockaddr *) &srv_addr,
0545 sizeof(struct sockaddr_un)) < 0)
0546 goto fail;
0547 } else
0548 goto fail;
0549 }
0550 op_buf[0] = op;
0551 op_len = 1;
0552 if (op == UUIDD_OP_BULK_TIME_UUID) {
0553 memcpy(op_buf+1, num, sizeof(*num));
0554 op_len += sizeof(*num);
0555 expected += sizeof(*num);
0556 }
0557
0558 ret = write(s, op_buf, op_len);
0559 if (ret < 1)
0560 goto fail;
0561
0562 ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
0563 if (ret < 0)
0564 goto fail;
0565
0566 if (reply_len != expected)
0567 goto fail;
0568
0569 ret = read_all(s, op_buf, reply_len);
0570
0571 if (op == UUIDD_OP_BULK_TIME_UUID)
0572 memcpy(op_buf+16, num, sizeof(int));
0573
0574 memcpy(out, op_buf, 16);
0575
0576 close(s);
0577 return ((ret == expected) ? 0 : -1);
0578
0579 fail:
0580 close(s);
0581 #endif
0582 return -1;
0583 }
0584
0585 void uuid__generate_time(uuid_t out, int *num)
0586 {
0587 static unsigned char node_id[6];
0588 static int has_init = 0;
0589 struct uuid uu;
0590 uint32_t clock_mid;
0591
0592 if (!has_init) {
0593 if (get_node_id(node_id) <= 0) {
0594 get_random_bytes(node_id, 6);
0595
0596
0597
0598
0599
0600 node_id[0] |= 0x01;
0601 }
0602 has_init = 1;
0603 }
0604 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
0605 uu.clock_seq |= 0x8000;
0606 uu.time_mid = (uint16_t) clock_mid;
0607 uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
0608 memcpy(uu.node, node_id, 6);
0609 uuid_pack(&uu, out);
0610 }
0611
0612 void uuid_generate_time(uuid_t out)
0613 {
0614 #ifdef TLS
0615 THREAD_LOCAL int num = 0;
0616 THREAD_LOCAL struct uuid uu;
0617 THREAD_LOCAL time_t last_time = 0;
0618 time_t now;
0619
0620 if (num > 0) {
0621 now = time(0);
0622 if (now > last_time+1)
0623 num = 0;
0624 }
0625 if (num <= 0) {
0626 num = 1000;
0627 if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
0628 out, &num) == 0) {
0629 last_time = time(0);
0630 uuid_unpack(out, &uu);
0631 num--;
0632 return;
0633 }
0634 num = 0;
0635 }
0636 if (num > 0) {
0637 uu.time_low++;
0638 if (uu.time_low == 0) {
0639 uu.time_mid++;
0640 if (uu.time_mid == 0)
0641 uu.time_hi_and_version++;
0642 }
0643 num--;
0644 uuid_pack(&uu, out);
0645 return;
0646 }
0647 #else
0648 if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
0649 return;
0650 #endif
0651
0652 uuid__generate_time(out, 0);
0653 }
0654
0655
0656 void uuid__generate_random(uuid_t out, int *num)
0657 {
0658 uuid_t buf;
0659 struct uuid uu;
0660 int i, n;
0661
0662 if (!num || !*num)
0663 n = 1;
0664 else
0665 n = *num;
0666
0667 for (i = 0; i < n; i++) {
0668 get_random_bytes(buf, sizeof(buf));
0669 uuid_unpack(buf, &uu);
0670
0671 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
0672 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
0673 | 0x4000;
0674 uuid_pack(&uu, out);
0675 out += sizeof(uuid_t);
0676 }
0677 }
0678
0679 void uuid_generate_random(uuid_t out)
0680 {
0681 int num = 1;
0682
0683
0684 uuid__generate_random(out, &num);
0685 }
0686
0687
0688
0689
0690
0691
0692
0693
0694 void uuid_generate(uuid_t out)
0695 {
0696 if (get_random_fd() >= 0)
0697 uuid_generate_random(out);
0698 else
0699 uuid_generate_time(out);
0700 }