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 35ae91e64bSmrg#include <sys/param.h> 368cb1c0efSmrg#include <stdio.h> 378cb1c0efSmrg#ifdef HAVE_UNISTD_H 388cb1c0efSmrg#include <unistd.h> 398cb1c0efSmrg#endif 408cb1c0efSmrg#ifdef HAVE_STDLIB_H 418cb1c0efSmrg#include <stdlib.h> 428cb1c0efSmrg#endif 438cb1c0efSmrg#include <string.h> 448cb1c0efSmrg#include <fcntl.h> 458cb1c0efSmrg#include <errno.h> 468cb1c0efSmrg#include <limits.h> 478cb1c0efSmrg#include <sys/types.h> 488cb1c0efSmrg#ifdef HAVE_SYS_TIME_H 498cb1c0efSmrg#include <sys/time.h> 508cb1c0efSmrg#endif 518cb1c0efSmrg#include <sys/stat.h> 528cb1c0efSmrg#ifdef HAVE_SYS_FILE_H 538cb1c0efSmrg#include <sys/file.h> 548cb1c0efSmrg#endif 558cb1c0efSmrg#ifdef HAVE_SYS_IOCTL_H 568cb1c0efSmrg#include <sys/ioctl.h> 578cb1c0efSmrg#endif 588cb1c0efSmrg#ifdef HAVE_SYS_SOCKET_H 598cb1c0efSmrg#include <sys/socket.h> 608cb1c0efSmrg#endif 618cb1c0efSmrg#ifdef HAVE_SYS_UN_H 628cb1c0efSmrg#include <sys/un.h> 638cb1c0efSmrg#endif 648cb1c0efSmrg#ifdef HAVE_SYS_SOCKIO_H 658cb1c0efSmrg#include <sys/sockio.h> 668cb1c0efSmrg#endif 678cb1c0efSmrg#ifdef HAVE_NET_IF_H 688cb1c0efSmrg#include <net/if.h> 698cb1c0efSmrg#endif 708cb1c0efSmrg#ifdef HAVE_NETINET_IN_H 718cb1c0efSmrg#include <netinet/in.h> 728cb1c0efSmrg#endif 738cb1c0efSmrg#ifdef HAVE_NET_IF_DL_H 748cb1c0efSmrg#include <net/if_dl.h> 758cb1c0efSmrg#endif 768cb1c0efSmrg#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) 778cb1c0efSmrg#include <sys/syscall.h> 788cb1c0efSmrg#endif 798cb1c0efSmrg 808cb1c0efSmrg#include "uuidP.h" 818cb1c0efSmrg#include "randutils.h" 82ae91e64bSmrg 83ae91e64bSmrg#define read_all(a,b,c) read(a,b,c) 848cb1c0efSmrg 858cb1c0efSmrg#ifdef HAVE_TLS 868cb1c0efSmrg#define THREAD_LOCAL static __thread 878cb1c0efSmrg#else 888cb1c0efSmrg#define THREAD_LOCAL static 898cb1c0efSmrg#endif 908cb1c0efSmrg 918cb1c0efSmrg/* index with UUID_VARIANT_xxx and shift 5 bits */ 928cb1c0efSmrgstatic unsigned char variant_bits[] = { 0x00, 0x04, 0x06, 0x07 }; 938cb1c0efSmrg 948cb1c0efSmrg/* 958cb1c0efSmrg * Get the ethernet hardware address, if we can find it... 968cb1c0efSmrg * 978cb1c0efSmrg * XXX for a windows version, probably should use GetAdaptersInfo: 988cb1c0efSmrg * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 998cb1c0efSmrg * commenting out get_node_id just to get gen_uuid to compile under windows 1008cb1c0efSmrg * is not the right way to go! 1018cb1c0efSmrg */ 1028cb1c0efSmrgstatic int get_node_id(unsigned char *node_id) 1038cb1c0efSmrg{ 1048cb1c0efSmrg#ifdef HAVE_NET_IF_H 1058cb1c0efSmrg int sd; 1068cb1c0efSmrg struct ifreq ifr, *ifrp; 1078cb1c0efSmrg struct ifconf ifc; 1088cb1c0efSmrg char buf[1024]; 1098cb1c0efSmrg int n, i; 1108cb1c0efSmrg unsigned char *a; 1118cb1c0efSmrg#ifdef HAVE_NET_IF_DL_H 1128cb1c0efSmrg struct sockaddr_dl *sdlp; 1138cb1c0efSmrg#endif 1148cb1c0efSmrg 1158cb1c0efSmrg/* 1168cb1c0efSmrg * BSD 4.4 defines the size of an ifreq to be 1178cb1c0efSmrg * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len 1188cb1c0efSmrg * However, under earlier systems, sa_len isn't present, so the size is 1198cb1c0efSmrg * just sizeof(struct ifreq) 1208cb1c0efSmrg */ 1218cb1c0efSmrg#ifdef HAVE_SA_LEN 122ae91e64bSmrg#define ifreq_size(i) MAX(sizeof(struct ifreq),\ 1238cb1c0efSmrg sizeof((i).ifr_name)+(i).ifr_addr.sa_len) 1248cb1c0efSmrg#else 1258cb1c0efSmrg#define ifreq_size(i) sizeof(struct ifreq) 1268cb1c0efSmrg#endif /* HAVE_SA_LEN */ 1278cb1c0efSmrg 1288cb1c0efSmrg sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 1298cb1c0efSmrg if (sd < 0) { 1308cb1c0efSmrg return -1; 1318cb1c0efSmrg } 1328cb1c0efSmrg memset(buf, 0, sizeof(buf)); 1338cb1c0efSmrg ifc.ifc_len = sizeof(buf); 1348cb1c0efSmrg ifc.ifc_buf = buf; 1358cb1c0efSmrg if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { 1368cb1c0efSmrg close(sd); 1378cb1c0efSmrg return -1; 1388cb1c0efSmrg } 1398cb1c0efSmrg n = ifc.ifc_len; 1408cb1c0efSmrg for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { 1418cb1c0efSmrg ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); 1428cb1c0efSmrg strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); 143ae91e64bSmrg#if defined(SIOCGIFHWADDR) && !defined(__sun) 1448cb1c0efSmrg if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) 1458cb1c0efSmrg continue; 1468cb1c0efSmrg a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 1478cb1c0efSmrg#else 1488cb1c0efSmrg#ifdef SIOCGENADDR 1498cb1c0efSmrg if (ioctl(sd, SIOCGENADDR, &ifr) < 0) 1508cb1c0efSmrg continue; 1518cb1c0efSmrg a = (unsigned char *) ifr.ifr_enaddr; 1528cb1c0efSmrg#else 1538cb1c0efSmrg#ifdef HAVE_NET_IF_DL_H 1548cb1c0efSmrg sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; 1558cb1c0efSmrg if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) 1568cb1c0efSmrg continue; 1578cb1c0efSmrg a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; 1588cb1c0efSmrg#else 1598cb1c0efSmrg /* 1608cb1c0efSmrg * XXX we don't have a way of getting the hardware 1618cb1c0efSmrg * address 1628cb1c0efSmrg */ 1638cb1c0efSmrg close(sd); 1648cb1c0efSmrg return 0; 1658cb1c0efSmrg#endif /* HAVE_NET_IF_DL_H */ 1668cb1c0efSmrg#endif /* SIOCGENADDR */ 1678cb1c0efSmrg#endif /* SIOCGIFHWADDR */ 1688cb1c0efSmrg if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) 1698cb1c0efSmrg continue; 1708cb1c0efSmrg if (node_id) { 1718cb1c0efSmrg memcpy(node_id, a, 6); 1728cb1c0efSmrg close(sd); 1738cb1c0efSmrg return 1; 1748cb1c0efSmrg } 1758cb1c0efSmrg } 1768cb1c0efSmrg close(sd); 1778cb1c0efSmrg#endif 1788cb1c0efSmrg return 0; 1798cb1c0efSmrg} 1808cb1c0efSmrg 1818cb1c0efSmrg/* Assume that the gettimeofday() has microsecond granularity */ 1828cb1c0efSmrg#define MAX_ADJUSTMENT 10 1838cb1c0efSmrg 1848cb1c0efSmrg/* 1858cb1c0efSmrg * Get clock from global sequence clock counter. 1868cb1c0efSmrg * 1878cb1c0efSmrg * Return -1 if the clock counter could not be opened/locked (in this case 1888cb1c0efSmrg * pseudorandom value is returned in @ret_clock_seq), otherwise return 0. 1898cb1c0efSmrg */ 1908cb1c0efSmrgstatic int get_clock(uint32_t *clock_high, uint32_t *clock_low, 1918cb1c0efSmrg uint16_t *ret_clock_seq, int *num) 1928cb1c0efSmrg{ 1938cb1c0efSmrg THREAD_LOCAL int adjustment = 0; 1948cb1c0efSmrg THREAD_LOCAL struct timeval last = {0, 0}; 1958cb1c0efSmrg THREAD_LOCAL int state_fd = -2; 1968cb1c0efSmrg THREAD_LOCAL FILE *state_f; 1978cb1c0efSmrg THREAD_LOCAL uint16_t clock_seq; 1988cb1c0efSmrg struct timeval tv; 1998cb1c0efSmrg uint64_t clock_reg; 2008cb1c0efSmrg mode_t save_umask; 2018cb1c0efSmrg int len; 2028cb1c0efSmrg int ret = 0; 2038cb1c0efSmrg 2048cb1c0efSmrg if (state_fd == -1) 2058cb1c0efSmrg ret = -1; 2068cb1c0efSmrg 2078cb1c0efSmrg if (state_fd == -2) { 2088cb1c0efSmrg save_umask = umask(0); 2098cb1c0efSmrg state_fd = open(LIBUUID_CLOCK_FILE, O_RDWR|O_CREAT|O_CLOEXEC, 0660); 2108cb1c0efSmrg (void) umask(save_umask); 2118cb1c0efSmrg if (state_fd != -1) { 2128cb1c0efSmrg state_f = fdopen(state_fd, "r+" UL_CLOEXECSTR); 2138cb1c0efSmrg if (!state_f) { 2148cb1c0efSmrg close(state_fd); 2158cb1c0efSmrg state_fd = -1; 2168cb1c0efSmrg ret = -1; 2178cb1c0efSmrg } 2188cb1c0efSmrg } 2198cb1c0efSmrg else 2208cb1c0efSmrg ret = -1; 2218cb1c0efSmrg } 2228cb1c0efSmrg if (state_fd >= 0) { 2238cb1c0efSmrg rewind(state_f); 2248cb1c0efSmrg while (flock(state_fd, LOCK_EX) < 0) { 2258cb1c0efSmrg if ((errno == EAGAIN) || (errno == EINTR)) 2268cb1c0efSmrg continue; 2278cb1c0efSmrg fclose(state_f); 2288cb1c0efSmrg close(state_fd); 2298cb1c0efSmrg state_fd = -1; 2308cb1c0efSmrg ret = -1; 2318cb1c0efSmrg break; 2328cb1c0efSmrg } 2338cb1c0efSmrg } 2348cb1c0efSmrg if (state_fd >= 0) { 2358cb1c0efSmrg unsigned int cl; 2368cb1c0efSmrg unsigned long tv1, tv2; 2378cb1c0efSmrg int a; 2388cb1c0efSmrg 2398cb1c0efSmrg if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", 2408cb1c0efSmrg &cl, &tv1, &tv2, &a) == 4) { 2418cb1c0efSmrg clock_seq = cl & 0x3FFF; 2428cb1c0efSmrg last.tv_sec = tv1; 2438cb1c0efSmrg last.tv_usec = tv2; 2448cb1c0efSmrg adjustment = a; 2458cb1c0efSmrg } 2468cb1c0efSmrg } 2478cb1c0efSmrg 2488cb1c0efSmrg if ((last.tv_sec == 0) && (last.tv_usec == 0)) { 2498cb1c0efSmrg random_get_bytes(&clock_seq, sizeof(clock_seq)); 2508cb1c0efSmrg clock_seq &= 0x3FFF; 2518cb1c0efSmrg gettimeofday(&last, NULL); 2528cb1c0efSmrg last.tv_sec--; 2538cb1c0efSmrg } 2548cb1c0efSmrg 2558cb1c0efSmrgtry_again: 2568cb1c0efSmrg gettimeofday(&tv, NULL); 2578cb1c0efSmrg if ((tv.tv_sec < last.tv_sec) || 2588cb1c0efSmrg ((tv.tv_sec == last.tv_sec) && 2598cb1c0efSmrg (tv.tv_usec < last.tv_usec))) { 2608cb1c0efSmrg clock_seq = (clock_seq+1) & 0x3FFF; 2618cb1c0efSmrg adjustment = 0; 2628cb1c0efSmrg last = tv; 2638cb1c0efSmrg } else if ((tv.tv_sec == last.tv_sec) && 2648cb1c0efSmrg (tv.tv_usec == last.tv_usec)) { 2658cb1c0efSmrg if (adjustment >= MAX_ADJUSTMENT) 2668cb1c0efSmrg goto try_again; 2678cb1c0efSmrg adjustment++; 2688cb1c0efSmrg } else { 2698cb1c0efSmrg adjustment = 0; 2708cb1c0efSmrg last = tv; 2718cb1c0efSmrg } 2728cb1c0efSmrg 2738cb1c0efSmrg clock_reg = tv.tv_usec*10 + adjustment; 2748cb1c0efSmrg clock_reg += ((uint64_t) tv.tv_sec)*10000000; 2758cb1c0efSmrg clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; 2768cb1c0efSmrg 2778cb1c0efSmrg if (num && (*num > 1)) { 2788cb1c0efSmrg adjustment += *num - 1; 2798cb1c0efSmrg last.tv_usec += adjustment / 10; 2808cb1c0efSmrg adjustment = adjustment % 10; 2818cb1c0efSmrg last.tv_sec += last.tv_usec / 1000000; 2828cb1c0efSmrg last.tv_usec = last.tv_usec % 1000000; 2838cb1c0efSmrg } 2848cb1c0efSmrg 2858cb1c0efSmrg if (state_fd >= 0) { 2868cb1c0efSmrg rewind(state_f); 2878cb1c0efSmrg len = fprintf(state_f, 2888cb1c0efSmrg "clock: %04x tv: %016ld %08ld adj: %08d\n", 2898cb1c0efSmrg clock_seq, (long)last.tv_sec, (long)last.tv_usec, adjustment); 2908cb1c0efSmrg fflush(state_f); 2918cb1c0efSmrg if (ftruncate(state_fd, len) < 0) { 2928cb1c0efSmrg fprintf(state_f, " \n"); 2938cb1c0efSmrg fflush(state_f); 2948cb1c0efSmrg } 2958cb1c0efSmrg rewind(state_f); 2968cb1c0efSmrg flock(state_fd, LOCK_UN); 2978cb1c0efSmrg } 2988cb1c0efSmrg 2998cb1c0efSmrg *clock_high = clock_reg >> 32; 3008cb1c0efSmrg *clock_low = clock_reg; 3018cb1c0efSmrg *ret_clock_seq = clock_seq; 3028cb1c0efSmrg return ret; 3038cb1c0efSmrg} 3048cb1c0efSmrg 305ae91e64bSmrgstatic int __uuid_generate_time(uuid_t out, int *num) 3068cb1c0efSmrg{ 3078cb1c0efSmrg static unsigned char node_id[6]; 3088cb1c0efSmrg static int has_init = 0; 3098cb1c0efSmrg struct uuid uu; 3108cb1c0efSmrg uint32_t clock_mid; 3118cb1c0efSmrg int ret; 3128cb1c0efSmrg 3138cb1c0efSmrg if (!has_init) { 3148cb1c0efSmrg if (get_node_id(node_id) <= 0) { 3158cb1c0efSmrg random_get_bytes(node_id, 6); 3168cb1c0efSmrg /* 3178cb1c0efSmrg * Set multicast bit, to prevent conflicts 3188cb1c0efSmrg * with IEEE 802 addresses obtained from 3198cb1c0efSmrg * network cards 3208cb1c0efSmrg */ 3218cb1c0efSmrg node_id[0] |= 0x01; 3228cb1c0efSmrg } 3238cb1c0efSmrg has_init = 1; 3248cb1c0efSmrg } 3258cb1c0efSmrg ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); 3268cb1c0efSmrg uu.clock_seq |= 0x8000; 3278cb1c0efSmrg uu.time_mid = (uint16_t) clock_mid; 3288cb1c0efSmrg uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; 3298cb1c0efSmrg memcpy(uu.node, node_id, 6); 3308cb1c0efSmrg uuid_pack(&uu, out); 3318cb1c0efSmrg return ret; 3328cb1c0efSmrg} 3338cb1c0efSmrg 3348cb1c0efSmrg/* 3358cb1c0efSmrg * Generate time-based UUID and store it to @out 3368cb1c0efSmrg * 3378cb1c0efSmrg * Tries to guarantee uniqueness of the generated UUIDs by obtaining them from the uuidd daemon, 3388cb1c0efSmrg * or, if uuidd is not usable, by using the global clock state counter (see get_clock()). 3398cb1c0efSmrg * If neither of these is possible (e.g. because of insufficient permissions), it generates 3408cb1c0efSmrg * the UUID anyway, but returns -1. Otherwise, returns 0. 3418cb1c0efSmrg */ 3428cb1c0efSmrgstatic int uuid_generate_time_generic(uuid_t out) { 3438cb1c0efSmrg return __uuid_generate_time(out, NULL); 3448cb1c0efSmrg} 3458cb1c0efSmrg 3468cb1c0efSmrg/* 3478cb1c0efSmrg * Generate time-based UUID and store it to @out. 3488cb1c0efSmrg * 3498cb1c0efSmrg * Discards return value from uuid_generate_time_generic() 3508cb1c0efSmrg */ 351ae91e64bSmrgstatic void uuid_generate_time(uuid_t out) 3528cb1c0efSmrg{ 3538cb1c0efSmrg (void)uuid_generate_time_generic(out); 3548cb1c0efSmrg} 3558cb1c0efSmrg 356ae91e64bSmrgstatic void __uuid_generate_random(uuid_t out, int *num) 3578cb1c0efSmrg{ 3588cb1c0efSmrg uuid_t buf; 3598cb1c0efSmrg struct uuid uu; 3608cb1c0efSmrg int i, n; 3618cb1c0efSmrg 3628cb1c0efSmrg if (!num || !*num) 3638cb1c0efSmrg n = 1; 3648cb1c0efSmrg else 3658cb1c0efSmrg n = *num; 3668cb1c0efSmrg 3678cb1c0efSmrg for (i = 0; i < n; i++) { 3688cb1c0efSmrg random_get_bytes(buf, sizeof(buf)); 3698cb1c0efSmrg uuid_unpack(buf, &uu); 3708cb1c0efSmrg 3718cb1c0efSmrg uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; 3728cb1c0efSmrg uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) 3738cb1c0efSmrg | 0x4000; 3748cb1c0efSmrg uuid_pack(&uu, out); 3758cb1c0efSmrg out += sizeof(uuid_t); 3768cb1c0efSmrg } 3778cb1c0efSmrg} 3788cb1c0efSmrg 3798cb1c0efSmrgvoid uuid_generate_random(uuid_t out) 3808cb1c0efSmrg{ 3818cb1c0efSmrg int num = 1; 3828cb1c0efSmrg /* No real reason to use the daemon for random uuid's -- yet */ 3838cb1c0efSmrg 3848cb1c0efSmrg __uuid_generate_random(out, &num); 3858cb1c0efSmrg} 3868cb1c0efSmrg 3878cb1c0efSmrg/* 3888cb1c0efSmrg * Check whether good random source (/dev/random or /dev/urandom) 3898cb1c0efSmrg * is available. 3908cb1c0efSmrg */ 3918cb1c0efSmrgstatic int have_random_source(void) 3928cb1c0efSmrg{ 3938cb1c0efSmrg return (access("/dev/random", R_OK) == 0 || 3948cb1c0efSmrg access("/dev/urandom", R_OK) == 0); 3958cb1c0efSmrg} 3968cb1c0efSmrg 3978cb1c0efSmrg 3988cb1c0efSmrg/* 3998cb1c0efSmrg * This is the generic front-end to uuid_generate_random and 4008cb1c0efSmrg * uuid_generate_time. It uses uuid_generate_random only if 4018cb1c0efSmrg * /dev/urandom is available, since otherwise we won't have 4028cb1c0efSmrg * high-quality randomness. 4038cb1c0efSmrg */ 4048cb1c0efSmrgvoid uuid_generate(uuid_t out) 4058cb1c0efSmrg{ 4068cb1c0efSmrg if (have_random_source()) 4078cb1c0efSmrg uuid_generate_random(out); 4088cb1c0efSmrg else 4098cb1c0efSmrg uuid_generate_time(out); 4108cb1c0efSmrg} 411