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