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