gen_uuid.c revision 8cb1c0ef
18cb1c0efSmrg/* 28cb1c0efSmrg * gen_uuid.c --- generate a DCE-compatible uuid 38cb1c0efSmrg * 48cb1c0efSmrg * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. 58cb1c0efSmrg * 68cb1c0efSmrg * %Begin-Header% 78cb1c0efSmrg * Redistribution and use in source and binary forms, with or without 88cb1c0efSmrg * modification, are permitted provided that the following conditions 98cb1c0efSmrg * are met: 108cb1c0efSmrg * 1. Redistributions of source code must retain the above copyright 118cb1c0efSmrg * notice, and the entire permission notice in its entirety, 128cb1c0efSmrg * including the disclaimer of warranties. 138cb1c0efSmrg * 2. Redistributions in binary form must reproduce the above copyright 148cb1c0efSmrg * notice, this list of conditions and the following disclaimer in the 158cb1c0efSmrg * documentation and/or other materials provided with the distribution. 168cb1c0efSmrg * 3. The name of the author may not be used to endorse or promote 178cb1c0efSmrg * products derived from this software without specific prior 188cb1c0efSmrg * written permission. 198cb1c0efSmrg * 208cb1c0efSmrg * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 218cb1c0efSmrg * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 228cb1c0efSmrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 238cb1c0efSmrg * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 248cb1c0efSmrg * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258cb1c0efSmrg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 268cb1c0efSmrg * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 278cb1c0efSmrg * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 288cb1c0efSmrg * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 298cb1c0efSmrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 308cb1c0efSmrg * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 318cb1c0efSmrg * DAMAGE. 328cb1c0efSmrg * %End-Header% 338cb1c0efSmrg */ 348cb1c0efSmrg 358cb1c0efSmrg#ifdef _WIN32 368cb1c0efSmrg#define _WIN32_WINNT 0x0500 378cb1c0efSmrg#include <windows.h> 388cb1c0efSmrg#define UUID MYUUID 398cb1c0efSmrg#endif 408cb1c0efSmrg#include <stdio.h> 418cb1c0efSmrg#ifdef HAVE_UNISTD_H 428cb1c0efSmrg#include <unistd.h> 438cb1c0efSmrg#endif 448cb1c0efSmrg#ifdef HAVE_STDLIB_H 458cb1c0efSmrg#include <stdlib.h> 468cb1c0efSmrg#endif 478cb1c0efSmrg#include <string.h> 488cb1c0efSmrg#include <fcntl.h> 498cb1c0efSmrg#include <errno.h> 508cb1c0efSmrg#include <limits.h> 518cb1c0efSmrg#include <sys/types.h> 528cb1c0efSmrg#ifdef HAVE_SYS_TIME_H 538cb1c0efSmrg#include <sys/time.h> 548cb1c0efSmrg#endif 558cb1c0efSmrg#include <sys/stat.h> 568cb1c0efSmrg#ifdef HAVE_SYS_FILE_H 578cb1c0efSmrg#include <sys/file.h> 588cb1c0efSmrg#endif 598cb1c0efSmrg#ifdef HAVE_SYS_IOCTL_H 608cb1c0efSmrg#include <sys/ioctl.h> 618cb1c0efSmrg#endif 628cb1c0efSmrg#ifdef HAVE_SYS_SOCKET_H 638cb1c0efSmrg#include <sys/socket.h> 648cb1c0efSmrg#endif 658cb1c0efSmrg#ifdef HAVE_SYS_UN_H 668cb1c0efSmrg#include <sys/un.h> 678cb1c0efSmrg#endif 688cb1c0efSmrg#ifdef HAVE_SYS_SOCKIO_H 698cb1c0efSmrg#include <sys/sockio.h> 708cb1c0efSmrg#endif 718cb1c0efSmrg#ifdef HAVE_NET_IF_H 728cb1c0efSmrg#include <net/if.h> 738cb1c0efSmrg#endif 748cb1c0efSmrg#ifdef HAVE_NETINET_IN_H 758cb1c0efSmrg#include <netinet/in.h> 768cb1c0efSmrg#endif 778cb1c0efSmrg#ifdef HAVE_NET_IF_DL_H 788cb1c0efSmrg#include <net/if_dl.h> 798cb1c0efSmrg#endif 808cb1c0efSmrg#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) 818cb1c0efSmrg#include <sys/syscall.h> 828cb1c0efSmrg#endif 838cb1c0efSmrg 848cb1c0efSmrg#include "all-io.h" 858cb1c0efSmrg#include "uuidP.h" 868cb1c0efSmrg#include "uuidd.h" 878cb1c0efSmrg#include "randutils.h" 888cb1c0efSmrg#include "strutils.h" 898cb1c0efSmrg#include "c.h" 908cb1c0efSmrg#include "md5.h" 918cb1c0efSmrg#include "sha1.h" 928cb1c0efSmrg 938cb1c0efSmrg#ifdef HAVE_TLS 948cb1c0efSmrg#define THREAD_LOCAL static __thread 958cb1c0efSmrg#else 968cb1c0efSmrg#define THREAD_LOCAL static 978cb1c0efSmrg#endif 988cb1c0efSmrg 998cb1c0efSmrg/* index with UUID_VARIANT_xxx and shift 5 bits */ 1008cb1c0efSmrgstatic unsigned char variant_bits[] = { 0x00, 0x04, 0x06, 0x07 }; 1018cb1c0efSmrg 1028cb1c0efSmrg#ifdef _WIN32 1038cb1c0efSmrgstatic void gettimeofday (struct timeval *tv, void *dummy) 1048cb1c0efSmrg{ 1058cb1c0efSmrg FILETIME ftime; 1068cb1c0efSmrg uint64_t n; 1078cb1c0efSmrg 1088cb1c0efSmrg GetSystemTimeAsFileTime (&ftime); 1098cb1c0efSmrg n = (((uint64_t) ftime.dwHighDateTime << 32) 1108cb1c0efSmrg + (uint64_t) ftime.dwLowDateTime); 1118cb1c0efSmrg if (n) { 1128cb1c0efSmrg n /= 10; 1138cb1c0efSmrg n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000; 1148cb1c0efSmrg } 1158cb1c0efSmrg 1168cb1c0efSmrg tv->tv_sec = n / 1000000; 1178cb1c0efSmrg tv->tv_usec = n % 1000000; 1188cb1c0efSmrg} 1198cb1c0efSmrg 1208cb1c0efSmrgstatic int getuid (void) 1218cb1c0efSmrg{ 1228cb1c0efSmrg return 1; 1238cb1c0efSmrg} 1248cb1c0efSmrg#endif 1258cb1c0efSmrg 1268cb1c0efSmrg/* 1278cb1c0efSmrg * Get the ethernet hardware address, if we can find it... 1288cb1c0efSmrg * 1298cb1c0efSmrg * XXX for a windows version, probably should use GetAdaptersInfo: 1308cb1c0efSmrg * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 1318cb1c0efSmrg * commenting out get_node_id just to get gen_uuid to compile under windows 1328cb1c0efSmrg * is not the right way to go! 1338cb1c0efSmrg */ 1348cb1c0efSmrgstatic int get_node_id(unsigned char *node_id) 1358cb1c0efSmrg{ 1368cb1c0efSmrg#ifdef HAVE_NET_IF_H 1378cb1c0efSmrg int sd; 1388cb1c0efSmrg struct ifreq ifr, *ifrp; 1398cb1c0efSmrg struct ifconf ifc; 1408cb1c0efSmrg char buf[1024]; 1418cb1c0efSmrg int n, i; 1428cb1c0efSmrg unsigned char *a; 1438cb1c0efSmrg#ifdef HAVE_NET_IF_DL_H 1448cb1c0efSmrg struct sockaddr_dl *sdlp; 1458cb1c0efSmrg#endif 1468cb1c0efSmrg 1478cb1c0efSmrg/* 1488cb1c0efSmrg * BSD 4.4 defines the size of an ifreq to be 1498cb1c0efSmrg * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len 1508cb1c0efSmrg * However, under earlier systems, sa_len isn't present, so the size is 1518cb1c0efSmrg * just sizeof(struct ifreq) 1528cb1c0efSmrg */ 1538cb1c0efSmrg#ifdef HAVE_SA_LEN 1548cb1c0efSmrg#define ifreq_size(i) max(sizeof(struct ifreq),\ 1558cb1c0efSmrg sizeof((i).ifr_name)+(i).ifr_addr.sa_len) 1568cb1c0efSmrg#else 1578cb1c0efSmrg#define ifreq_size(i) sizeof(struct ifreq) 1588cb1c0efSmrg#endif /* HAVE_SA_LEN */ 1598cb1c0efSmrg 1608cb1c0efSmrg sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 1618cb1c0efSmrg if (sd < 0) { 1628cb1c0efSmrg return -1; 1638cb1c0efSmrg } 1648cb1c0efSmrg memset(buf, 0, sizeof(buf)); 1658cb1c0efSmrg ifc.ifc_len = sizeof(buf); 1668cb1c0efSmrg ifc.ifc_buf = buf; 1678cb1c0efSmrg if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { 1688cb1c0efSmrg close(sd); 1698cb1c0efSmrg return -1; 1708cb1c0efSmrg } 1718cb1c0efSmrg n = ifc.ifc_len; 1728cb1c0efSmrg for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { 1738cb1c0efSmrg ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); 1748cb1c0efSmrg strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); 1758cb1c0efSmrg#ifdef SIOCGIFHWADDR 1768cb1c0efSmrg if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) 1778cb1c0efSmrg continue; 1788cb1c0efSmrg a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 1798cb1c0efSmrg#else 1808cb1c0efSmrg#ifdef SIOCGENADDR 1818cb1c0efSmrg if (ioctl(sd, SIOCGENADDR, &ifr) < 0) 1828cb1c0efSmrg continue; 1838cb1c0efSmrg a = (unsigned char *) ifr.ifr_enaddr; 1848cb1c0efSmrg#else 1858cb1c0efSmrg#ifdef HAVE_NET_IF_DL_H 1868cb1c0efSmrg sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; 1878cb1c0efSmrg if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) 1888cb1c0efSmrg continue; 1898cb1c0efSmrg a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; 1908cb1c0efSmrg#else 1918cb1c0efSmrg /* 1928cb1c0efSmrg * XXX we don't have a way of getting the hardware 1938cb1c0efSmrg * address 1948cb1c0efSmrg */ 1958cb1c0efSmrg close(sd); 1968cb1c0efSmrg return 0; 1978cb1c0efSmrg#endif /* HAVE_NET_IF_DL_H */ 1988cb1c0efSmrg#endif /* SIOCGENADDR */ 1998cb1c0efSmrg#endif /* SIOCGIFHWADDR */ 2008cb1c0efSmrg if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) 2018cb1c0efSmrg continue; 2028cb1c0efSmrg if (node_id) { 2038cb1c0efSmrg memcpy(node_id, a, 6); 2048cb1c0efSmrg close(sd); 2058cb1c0efSmrg return 1; 2068cb1c0efSmrg } 2078cb1c0efSmrg } 2088cb1c0efSmrg close(sd); 2098cb1c0efSmrg#endif 2108cb1c0efSmrg return 0; 2118cb1c0efSmrg} 2128cb1c0efSmrg 2138cb1c0efSmrg/* Assume that the gettimeofday() has microsecond granularity */ 2148cb1c0efSmrg#define MAX_ADJUSTMENT 10 2158cb1c0efSmrg 2168cb1c0efSmrg/* 2178cb1c0efSmrg * Get clock from global sequence clock counter. 2188cb1c0efSmrg * 2198cb1c0efSmrg * Return -1 if the clock counter could not be opened/locked (in this case 2208cb1c0efSmrg * pseudorandom value is returned in @ret_clock_seq), otherwise return 0. 2218cb1c0efSmrg */ 2228cb1c0efSmrgstatic int get_clock(uint32_t *clock_high, uint32_t *clock_low, 2238cb1c0efSmrg uint16_t *ret_clock_seq, int *num) 2248cb1c0efSmrg{ 2258cb1c0efSmrg THREAD_LOCAL int adjustment = 0; 2268cb1c0efSmrg THREAD_LOCAL struct timeval last = {0, 0}; 2278cb1c0efSmrg THREAD_LOCAL int state_fd = -2; 2288cb1c0efSmrg THREAD_LOCAL FILE *state_f; 2298cb1c0efSmrg THREAD_LOCAL uint16_t clock_seq; 2308cb1c0efSmrg struct timeval tv; 2318cb1c0efSmrg uint64_t clock_reg; 2328cb1c0efSmrg mode_t save_umask; 2338cb1c0efSmrg int len; 2348cb1c0efSmrg int ret = 0; 2358cb1c0efSmrg 2368cb1c0efSmrg if (state_fd == -1) 2378cb1c0efSmrg ret = -1; 2388cb1c0efSmrg 2398cb1c0efSmrg if (state_fd == -2) { 2408cb1c0efSmrg save_umask = umask(0); 2418cb1c0efSmrg state_fd = open(LIBUUID_CLOCK_FILE, O_RDWR|O_CREAT|O_CLOEXEC, 0660); 2428cb1c0efSmrg (void) umask(save_umask); 2438cb1c0efSmrg if (state_fd != -1) { 2448cb1c0efSmrg state_f = fdopen(state_fd, "r+" UL_CLOEXECSTR); 2458cb1c0efSmrg if (!state_f) { 2468cb1c0efSmrg close(state_fd); 2478cb1c0efSmrg state_fd = -1; 2488cb1c0efSmrg ret = -1; 2498cb1c0efSmrg } 2508cb1c0efSmrg } 2518cb1c0efSmrg else 2528cb1c0efSmrg ret = -1; 2538cb1c0efSmrg } 2548cb1c0efSmrg if (state_fd >= 0) { 2558cb1c0efSmrg rewind(state_f); 2568cb1c0efSmrg while (flock(state_fd, LOCK_EX) < 0) { 2578cb1c0efSmrg if ((errno == EAGAIN) || (errno == EINTR)) 2588cb1c0efSmrg continue; 2598cb1c0efSmrg fclose(state_f); 2608cb1c0efSmrg close(state_fd); 2618cb1c0efSmrg state_fd = -1; 2628cb1c0efSmrg ret = -1; 2638cb1c0efSmrg break; 2648cb1c0efSmrg } 2658cb1c0efSmrg } 2668cb1c0efSmrg if (state_fd >= 0) { 2678cb1c0efSmrg unsigned int cl; 2688cb1c0efSmrg unsigned long tv1, tv2; 2698cb1c0efSmrg int a; 2708cb1c0efSmrg 2718cb1c0efSmrg if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", 2728cb1c0efSmrg &cl, &tv1, &tv2, &a) == 4) { 2738cb1c0efSmrg clock_seq = cl & 0x3FFF; 2748cb1c0efSmrg last.tv_sec = tv1; 2758cb1c0efSmrg last.tv_usec = tv2; 2768cb1c0efSmrg adjustment = a; 2778cb1c0efSmrg } 2788cb1c0efSmrg } 2798cb1c0efSmrg 2808cb1c0efSmrg if ((last.tv_sec == 0) && (last.tv_usec == 0)) { 2818cb1c0efSmrg random_get_bytes(&clock_seq, sizeof(clock_seq)); 2828cb1c0efSmrg clock_seq &= 0x3FFF; 2838cb1c0efSmrg gettimeofday(&last, NULL); 2848cb1c0efSmrg last.tv_sec--; 2858cb1c0efSmrg } 2868cb1c0efSmrg 2878cb1c0efSmrgtry_again: 2888cb1c0efSmrg gettimeofday(&tv, NULL); 2898cb1c0efSmrg if ((tv.tv_sec < last.tv_sec) || 2908cb1c0efSmrg ((tv.tv_sec == last.tv_sec) && 2918cb1c0efSmrg (tv.tv_usec < last.tv_usec))) { 2928cb1c0efSmrg clock_seq = (clock_seq+1) & 0x3FFF; 2938cb1c0efSmrg adjustment = 0; 2948cb1c0efSmrg last = tv; 2958cb1c0efSmrg } else if ((tv.tv_sec == last.tv_sec) && 2968cb1c0efSmrg (tv.tv_usec == last.tv_usec)) { 2978cb1c0efSmrg if (adjustment >= MAX_ADJUSTMENT) 2988cb1c0efSmrg goto try_again; 2998cb1c0efSmrg adjustment++; 3008cb1c0efSmrg } else { 3018cb1c0efSmrg adjustment = 0; 3028cb1c0efSmrg last = tv; 3038cb1c0efSmrg } 3048cb1c0efSmrg 3058cb1c0efSmrg clock_reg = tv.tv_usec*10 + adjustment; 3068cb1c0efSmrg clock_reg += ((uint64_t) tv.tv_sec)*10000000; 3078cb1c0efSmrg clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; 3088cb1c0efSmrg 3098cb1c0efSmrg if (num && (*num > 1)) { 3108cb1c0efSmrg adjustment += *num - 1; 3118cb1c0efSmrg last.tv_usec += adjustment / 10; 3128cb1c0efSmrg adjustment = adjustment % 10; 3138cb1c0efSmrg last.tv_sec += last.tv_usec / 1000000; 3148cb1c0efSmrg last.tv_usec = last.tv_usec % 1000000; 3158cb1c0efSmrg } 3168cb1c0efSmrg 3178cb1c0efSmrg if (state_fd >= 0) { 3188cb1c0efSmrg rewind(state_f); 3198cb1c0efSmrg len = fprintf(state_f, 3208cb1c0efSmrg "clock: %04x tv: %016ld %08ld adj: %08d\n", 3218cb1c0efSmrg clock_seq, (long)last.tv_sec, (long)last.tv_usec, adjustment); 3228cb1c0efSmrg fflush(state_f); 3238cb1c0efSmrg if (ftruncate(state_fd, len) < 0) { 3248cb1c0efSmrg fprintf(state_f, " \n"); 3258cb1c0efSmrg fflush(state_f); 3268cb1c0efSmrg } 3278cb1c0efSmrg rewind(state_f); 3288cb1c0efSmrg flock(state_fd, LOCK_UN); 3298cb1c0efSmrg } 3308cb1c0efSmrg 3318cb1c0efSmrg *clock_high = clock_reg >> 32; 3328cb1c0efSmrg *clock_low = clock_reg; 3338cb1c0efSmrg *ret_clock_seq = clock_seq; 3348cb1c0efSmrg return ret; 3358cb1c0efSmrg} 3368cb1c0efSmrg 3378cb1c0efSmrg#if defined(HAVE_UUIDD) && defined(HAVE_SYS_UN_H) 3388cb1c0efSmrg 3398cb1c0efSmrg/* 3408cb1c0efSmrg * Try using the uuidd daemon to generate the UUID 3418cb1c0efSmrg * 3428cb1c0efSmrg * Returns 0 on success, non-zero on failure. 3438cb1c0efSmrg */ 3448cb1c0efSmrgstatic int get_uuid_via_daemon(int op, uuid_t out, int *num) 3458cb1c0efSmrg{ 3468cb1c0efSmrg char op_buf[64]; 3478cb1c0efSmrg int op_len; 3488cb1c0efSmrg int s; 3498cb1c0efSmrg ssize_t ret; 3508cb1c0efSmrg int32_t reply_len = 0, expected = 16; 3518cb1c0efSmrg struct sockaddr_un srv_addr; 3528cb1c0efSmrg 3538cb1c0efSmrg if (sizeof(UUIDD_SOCKET_PATH) > sizeof(srv_addr.sun_path)) 3548cb1c0efSmrg return -1; 3558cb1c0efSmrg 3568cb1c0efSmrg if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 3578cb1c0efSmrg return -1; 3588cb1c0efSmrg 3598cb1c0efSmrg srv_addr.sun_family = AF_UNIX; 3608cb1c0efSmrg xstrncpy(srv_addr.sun_path, UUIDD_SOCKET_PATH, sizeof(srv_addr.sun_path)); 3618cb1c0efSmrg 3628cb1c0efSmrg if (connect(s, (const struct sockaddr *) &srv_addr, 3638cb1c0efSmrg sizeof(struct sockaddr_un)) < 0) 3648cb1c0efSmrg goto fail; 3658cb1c0efSmrg 3668cb1c0efSmrg op_buf[0] = op; 3678cb1c0efSmrg op_len = 1; 3688cb1c0efSmrg if (op == UUIDD_OP_BULK_TIME_UUID) { 3698cb1c0efSmrg memcpy(op_buf+1, num, sizeof(*num)); 3708cb1c0efSmrg op_len += sizeof(*num); 3718cb1c0efSmrg expected += sizeof(*num); 3728cb1c0efSmrg } 3738cb1c0efSmrg 3748cb1c0efSmrg ret = write(s, op_buf, op_len); 3758cb1c0efSmrg if (ret < 1) 3768cb1c0efSmrg goto fail; 3778cb1c0efSmrg 3788cb1c0efSmrg ret = read_all(s, (char *) &reply_len, sizeof(reply_len)); 3798cb1c0efSmrg if (ret < 0) 3808cb1c0efSmrg goto fail; 3818cb1c0efSmrg 3828cb1c0efSmrg if (reply_len != expected) 3838cb1c0efSmrg goto fail; 3848cb1c0efSmrg 3858cb1c0efSmrg ret = read_all(s, op_buf, reply_len); 3868cb1c0efSmrg 3878cb1c0efSmrg if (op == UUIDD_OP_BULK_TIME_UUID) 3888cb1c0efSmrg memcpy(op_buf+16, num, sizeof(int)); 3898cb1c0efSmrg 3908cb1c0efSmrg memcpy(out, op_buf, 16); 3918cb1c0efSmrg 3928cb1c0efSmrg close(s); 3938cb1c0efSmrg return ((ret == expected) ? 0 : -1); 3948cb1c0efSmrg 3958cb1c0efSmrgfail: 3968cb1c0efSmrg close(s); 3978cb1c0efSmrg return -1; 3988cb1c0efSmrg} 3998cb1c0efSmrg 4008cb1c0efSmrg#else /* !defined(HAVE_UUIDD) && defined(HAVE_SYS_UN_H) */ 4018cb1c0efSmrgstatic int get_uuid_via_daemon(int op __attribute__((__unused__)), 4028cb1c0efSmrg uuid_t out __attribute__((__unused__)), 4038cb1c0efSmrg int *num __attribute__((__unused__))) 4048cb1c0efSmrg{ 4058cb1c0efSmrg return -1; 4068cb1c0efSmrg} 4078cb1c0efSmrg#endif 4088cb1c0efSmrg 4098cb1c0efSmrgint __uuid_generate_time(uuid_t out, int *num) 4108cb1c0efSmrg{ 4118cb1c0efSmrg static unsigned char node_id[6]; 4128cb1c0efSmrg static int has_init = 0; 4138cb1c0efSmrg struct uuid uu; 4148cb1c0efSmrg uint32_t clock_mid; 4158cb1c0efSmrg int ret; 4168cb1c0efSmrg 4178cb1c0efSmrg if (!has_init) { 4188cb1c0efSmrg if (get_node_id(node_id) <= 0) { 4198cb1c0efSmrg random_get_bytes(node_id, 6); 4208cb1c0efSmrg /* 4218cb1c0efSmrg * Set multicast bit, to prevent conflicts 4228cb1c0efSmrg * with IEEE 802 addresses obtained from 4238cb1c0efSmrg * network cards 4248cb1c0efSmrg */ 4258cb1c0efSmrg node_id[0] |= 0x01; 4268cb1c0efSmrg } 4278cb1c0efSmrg has_init = 1; 4288cb1c0efSmrg } 4298cb1c0efSmrg ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); 4308cb1c0efSmrg uu.clock_seq |= 0x8000; 4318cb1c0efSmrg uu.time_mid = (uint16_t) clock_mid; 4328cb1c0efSmrg uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; 4338cb1c0efSmrg memcpy(uu.node, node_id, 6); 4348cb1c0efSmrg uuid_pack(&uu, out); 4358cb1c0efSmrg return ret; 4368cb1c0efSmrg} 4378cb1c0efSmrg 4388cb1c0efSmrg/* 4398cb1c0efSmrg * Generate time-based UUID and store it to @out 4408cb1c0efSmrg * 4418cb1c0efSmrg * Tries to guarantee uniqueness of the generated UUIDs by obtaining them from the uuidd daemon, 4428cb1c0efSmrg * or, if uuidd is not usable, by using the global clock state counter (see get_clock()). 4438cb1c0efSmrg * If neither of these is possible (e.g. because of insufficient permissions), it generates 4448cb1c0efSmrg * the UUID anyway, but returns -1. Otherwise, returns 0. 4458cb1c0efSmrg */ 4468cb1c0efSmrgstatic int uuid_generate_time_generic(uuid_t out) { 4478cb1c0efSmrg#ifdef HAVE_TLS 4488cb1c0efSmrg THREAD_LOCAL int num = 0; 4498cb1c0efSmrg THREAD_LOCAL struct uuid uu; 4508cb1c0efSmrg THREAD_LOCAL time_t last_time = 0; 4518cb1c0efSmrg time_t now; 4528cb1c0efSmrg 4538cb1c0efSmrg if (num > 0) { 4548cb1c0efSmrg now = time(NULL); 4558cb1c0efSmrg if (now > last_time+1) 4568cb1c0efSmrg num = 0; 4578cb1c0efSmrg } 4588cb1c0efSmrg if (num <= 0) { 4598cb1c0efSmrg num = 1000; 4608cb1c0efSmrg if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID, 4618cb1c0efSmrg out, &num) == 0) { 4628cb1c0efSmrg last_time = time(NULL); 4638cb1c0efSmrg uuid_unpack(out, &uu); 4648cb1c0efSmrg num--; 4658cb1c0efSmrg return 0; 4668cb1c0efSmrg } 4678cb1c0efSmrg num = 0; 4688cb1c0efSmrg } 4698cb1c0efSmrg if (num > 0) { 4708cb1c0efSmrg uu.time_low++; 4718cb1c0efSmrg if (uu.time_low == 0) { 4728cb1c0efSmrg uu.time_mid++; 4738cb1c0efSmrg if (uu.time_mid == 0) 4748cb1c0efSmrg uu.time_hi_and_version++; 4758cb1c0efSmrg } 4768cb1c0efSmrg num--; 4778cb1c0efSmrg uuid_pack(&uu, out); 4788cb1c0efSmrg return 0; 4798cb1c0efSmrg } 4808cb1c0efSmrg#else 4818cb1c0efSmrg if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0) 4828cb1c0efSmrg return 0; 4838cb1c0efSmrg#endif 4848cb1c0efSmrg 4858cb1c0efSmrg return __uuid_generate_time(out, NULL); 4868cb1c0efSmrg} 4878cb1c0efSmrg 4888cb1c0efSmrg/* 4898cb1c0efSmrg * Generate time-based UUID and store it to @out. 4908cb1c0efSmrg * 4918cb1c0efSmrg * Discards return value from uuid_generate_time_generic() 4928cb1c0efSmrg */ 4938cb1c0efSmrgvoid uuid_generate_time(uuid_t out) 4948cb1c0efSmrg{ 4958cb1c0efSmrg (void)uuid_generate_time_generic(out); 4968cb1c0efSmrg} 4978cb1c0efSmrg 4988cb1c0efSmrg 4998cb1c0efSmrgint uuid_generate_time_safe(uuid_t out) 5008cb1c0efSmrg{ 5018cb1c0efSmrg return uuid_generate_time_generic(out); 5028cb1c0efSmrg} 5038cb1c0efSmrg 5048cb1c0efSmrg 5058cb1c0efSmrgvoid __uuid_generate_random(uuid_t out, int *num) 5068cb1c0efSmrg{ 5078cb1c0efSmrg uuid_t buf; 5088cb1c0efSmrg struct uuid uu; 5098cb1c0efSmrg int i, n; 5108cb1c0efSmrg 5118cb1c0efSmrg if (!num || !*num) 5128cb1c0efSmrg n = 1; 5138cb1c0efSmrg else 5148cb1c0efSmrg n = *num; 5158cb1c0efSmrg 5168cb1c0efSmrg for (i = 0; i < n; i++) { 5178cb1c0efSmrg random_get_bytes(buf, sizeof(buf)); 5188cb1c0efSmrg uuid_unpack(buf, &uu); 5198cb1c0efSmrg 5208cb1c0efSmrg uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; 5218cb1c0efSmrg uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) 5228cb1c0efSmrg | 0x4000; 5238cb1c0efSmrg uuid_pack(&uu, out); 5248cb1c0efSmrg out += sizeof(uuid_t); 5258cb1c0efSmrg } 5268cb1c0efSmrg} 5278cb1c0efSmrg 5288cb1c0efSmrgvoid uuid_generate_random(uuid_t out) 5298cb1c0efSmrg{ 5308cb1c0efSmrg int num = 1; 5318cb1c0efSmrg /* No real reason to use the daemon for random uuid's -- yet */ 5328cb1c0efSmrg 5338cb1c0efSmrg __uuid_generate_random(out, &num); 5348cb1c0efSmrg} 5358cb1c0efSmrg 5368cb1c0efSmrg/* 5378cb1c0efSmrg * Check whether good random source (/dev/random or /dev/urandom) 5388cb1c0efSmrg * is available. 5398cb1c0efSmrg */ 5408cb1c0efSmrgstatic int have_random_source(void) 5418cb1c0efSmrg{ 5428cb1c0efSmrg return (access("/dev/random", R_OK) == 0 || 5438cb1c0efSmrg access("/dev/urandom", R_OK) == 0); 5448cb1c0efSmrg} 5458cb1c0efSmrg 5468cb1c0efSmrg 5478cb1c0efSmrg/* 5488cb1c0efSmrg * This is the generic front-end to uuid_generate_random and 5498cb1c0efSmrg * uuid_generate_time. It uses uuid_generate_random only if 5508cb1c0efSmrg * /dev/urandom is available, since otherwise we won't have 5518cb1c0efSmrg * high-quality randomness. 5528cb1c0efSmrg */ 5538cb1c0efSmrgvoid uuid_generate(uuid_t out) 5548cb1c0efSmrg{ 5558cb1c0efSmrg if (have_random_source()) 5568cb1c0efSmrg uuid_generate_random(out); 5578cb1c0efSmrg else 5588cb1c0efSmrg uuid_generate_time(out); 5598cb1c0efSmrg} 5608cb1c0efSmrg 5618cb1c0efSmrg/* 5628cb1c0efSmrg * Generate an MD5 hashed (predictable) UUID based on a well-known UUID 5638cb1c0efSmrg * providing the namespace and an arbitrary binary string. 5648cb1c0efSmrg */ 5658cb1c0efSmrgvoid uuid_generate_md5(uuid_t out, const uuid_t ns, const char *name, size_t len) 5668cb1c0efSmrg{ 5678cb1c0efSmrg UL_MD5_CTX ctx; 5688cb1c0efSmrg char hash[UL_MD5LENGTH]; 5698cb1c0efSmrg 5708cb1c0efSmrg ul_MD5Init(&ctx); 5718cb1c0efSmrg /* hash concatenation of well-known UUID with name */ 5728cb1c0efSmrg ul_MD5Update(&ctx, ns, sizeof(uuid_t)); 5738cb1c0efSmrg ul_MD5Update(&ctx, (const unsigned char *)name, len); 5748cb1c0efSmrg 5758cb1c0efSmrg ul_MD5Final((unsigned char *)hash, &ctx); 5768cb1c0efSmrg 5778cb1c0efSmrg memcpy(out, hash, sizeof(uuid_t)); 5788cb1c0efSmrg 5798cb1c0efSmrg out[6] &= ~(UUID_TYPE_MASK << UUID_TYPE_SHIFT); 5808cb1c0efSmrg out[6] |= (UUID_TYPE_DCE_MD5 << UUID_TYPE_SHIFT); 5818cb1c0efSmrg 5828cb1c0efSmrg out[8] &= ~(UUID_VARIANT_MASK << UUID_VARIANT_SHIFT); 5838cb1c0efSmrg out[8] |= (variant_bits[UUID_VARIANT_DCE] << UUID_VARIANT_SHIFT); 5848cb1c0efSmrg} 5858cb1c0efSmrg 5868cb1c0efSmrg/* 5878cb1c0efSmrg * Generate a SHA1 hashed (predictable) UUID based on a well-known UUID 5888cb1c0efSmrg * providing the namespace and an arbitrary binary string. 5898cb1c0efSmrg */ 5908cb1c0efSmrgvoid uuid_generate_sha1(uuid_t out, const uuid_t ns, const char *name, size_t len) 5918cb1c0efSmrg{ 5928cb1c0efSmrg UL_SHA1_CTX ctx; 5938cb1c0efSmrg char hash[UL_SHA1LENGTH]; 5948cb1c0efSmrg 5958cb1c0efSmrg ul_SHA1Init(&ctx); 5968cb1c0efSmrg /* hash concatenation of well-known UUID with name */ 5978cb1c0efSmrg ul_SHA1Update(&ctx, ns, sizeof(uuid_t)); 5988cb1c0efSmrg ul_SHA1Update(&ctx, (const unsigned char *)name, len); 5998cb1c0efSmrg 6008cb1c0efSmrg ul_SHA1Final((unsigned char *)hash, &ctx); 6018cb1c0efSmrg 6028cb1c0efSmrg memcpy(out, hash, sizeof(uuid_t)); 6038cb1c0efSmrg 6048cb1c0efSmrg out[6] &= ~(UUID_TYPE_MASK << UUID_TYPE_SHIFT); 6058cb1c0efSmrg out[6] |= (UUID_TYPE_DCE_SHA1 << UUID_TYPE_SHIFT); 6068cb1c0efSmrg 6078cb1c0efSmrg out[8] &= ~(UUID_VARIANT_MASK << UUID_VARIANT_SHIFT); 6088cb1c0efSmrg out[8] |= (variant_bits[UUID_VARIANT_DCE] << UUID_VARIANT_SHIFT); 6098cb1c0efSmrg} 6108cb1c0efSmrg 611