Home | History | Annotate | Download | only in uuid
      1 /*
      2  * gen_uuid.c --- generate a DCE-compatible uuid
      3  *
      4  * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
      5  *
      6  * %Begin-Header%
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, and the entire permission notice in its entirety,
     12  *    including the disclaimer of warranties.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote
     17  *    products derived from this software without specific prior
     18  *    written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
     21  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
     23  * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
     24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
     26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     27  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
     30  * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
     31  * DAMAGE.
     32  * %End-Header%
     33  */
     34 
     35 /*
     36  * Force inclusion of SVID stuff since we need it if we're compiling in
     37  * gcc-wall wall mode
     38  */
     39 #define _SVID_SOURCE
     40 #define _DEFAULT_SOURCE	  /* since glibc 2.20 _SVID_SOURCE is deprecated */
     41 
     42 #include "config.h"
     43 
     44 #ifdef _WIN32
     45 #define _WIN32_WINNT 0x0500
     46 #include <windows.h>
     47 #define UUID MYUUID
     48 #endif
     49 #include <stdio.h>
     50 #ifdef HAVE_UNISTD_H
     51 #include <unistd.h>
     52 #endif
     53 #ifdef HAVE_STDLIB_H
     54 #include <stdlib.h>
     55 #endif
     56 #include <string.h>
     57 #include <fcntl.h>
     58 #include <errno.h>
     59 #include <sys/types.h>
     60 #ifdef HAVE_SYS_TIME_H
     61 #include <sys/time.h>
     62 #endif
     63 #ifdef HAVE_SYS_WAIT_H
     64 #include <sys/wait.h>
     65 #endif
     66 #include <sys/stat.h>
     67 #ifdef HAVE_SYS_FILE_H
     68 #include <sys/file.h>
     69 #endif
     70 #ifdef HAVE_SYS_IOCTL_H
     71 #include <sys/ioctl.h>
     72 #endif
     73 #ifdef HAVE_SYS_SOCKET_H
     74 #include <sys/socket.h>
     75 #endif
     76 #ifdef HAVE_SYS_UN_H
     77 #include <sys/un.h>
     78 #endif
     79 #ifdef HAVE_SYS_SOCKIO_H
     80 #include <sys/sockio.h>
     81 #endif
     82 #ifdef HAVE_NET_IF_H
     83 #include <net/if.h>
     84 #endif
     85 #ifdef HAVE_NETINET_IN_H
     86 #include <netinet/in.h>
     87 #endif
     88 #ifdef HAVE_NET_IF_DL_H
     89 #include <net/if_dl.h>
     90 #endif
     91 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
     92 #include <sys/syscall.h>
     93 #endif
     94 #ifdef HAVE_SYS_RESOURCE_H
     95 #include <sys/resource.h>
     96 #endif
     97 
     98 #include "uuidP.h"
     99 #include "uuidd.h"
    100 
    101 #ifdef HAVE_SRANDOM
    102 #define srand(x) 	srandom(x)
    103 #define rand() 		random()
    104 #endif
    105 
    106 #ifdef TLS
    107 #define THREAD_LOCAL static TLS
    108 #else
    109 #define THREAD_LOCAL static
    110 #endif
    111 
    112 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
    113 #define DO_JRAND_MIX
    114 THREAD_LOCAL unsigned short jrand_seed[3];
    115 #endif
    116 
    117 #ifdef _WIN32
    118 #ifndef USE_MINGW
    119 static void gettimeofday (struct timeval *tv, void *dummy)
    120 {
    121 	FILETIME	ftime;
    122 	uint64_t	n;
    123 
    124 	GetSystemTimeAsFileTime (&ftime);
    125 	n = (((uint64_t) ftime.dwHighDateTime << 32)
    126 	     + (uint64_t) ftime.dwLowDateTime);
    127 	if (n) {
    128 		n /= 10;
    129 		n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000;
    130 	}
    131 
    132 	tv->tv_sec = n / 1000000;
    133 	tv->tv_usec = n % 1000000;
    134 }
    135 #endif
    136 #endif
    137 
    138 static int get_random_fd(void)
    139 {
    140 	struct timeval	tv;
    141 	static int	fd = -2;
    142 	int		i;
    143 
    144 	if (fd == -2) {
    145 		gettimeofday(&tv, 0);
    146 #ifndef _WIN32
    147 		fd = open("/dev/urandom", O_RDONLY);
    148 		if (fd == -1)
    149 			fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
    150 		if (fd >= 0) {
    151 			i = fcntl(fd, F_GETFD);
    152 			if (i >= 0)
    153 				fcntl(fd, F_SETFD, i | FD_CLOEXEC);
    154 		}
    155 #endif
    156 		srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
    157 #ifdef DO_JRAND_MIX
    158 		jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
    159 		jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
    160 		jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
    161 #endif
    162 	}
    163 	/* Crank the random number generator a few times */
    164 	gettimeofday(&tv, 0);
    165 	for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
    166 		rand();
    167 	return fd;
    168 }
    169 
    170 
    171 /*
    172  * Generate a series of random bytes.  Use /dev/urandom if possible,
    173  * and if not, use srandom/random.
    174  */
    175 static void get_random_bytes(void *buf, int nbytes)
    176 {
    177 	int i, n = nbytes, fd = get_random_fd();
    178 	int lose_counter = 0;
    179 	unsigned char *cp = buf;
    180 
    181 	if (fd >= 0) {
    182 		while (n > 0) {
    183 			i = read(fd, cp, n);
    184 			if (i <= 0) {
    185 				if (lose_counter++ > 16)
    186 					break;
    187 				continue;
    188 			}
    189 			n -= i;
    190 			cp += i;
    191 			lose_counter = 0;
    192 		}
    193 	}
    194 
    195 	/*
    196 	 * We do this all the time, but this is the only source of
    197 	 * randomness if /dev/random/urandom is out to lunch.
    198 	 */
    199 	for (cp = buf, i = 0; i < nbytes; i++)
    200 		*cp++ ^= (rand() >> 7) & 0xFF;
    201 #ifdef DO_JRAND_MIX
    202 	{
    203 		unsigned short tmp_seed[3];
    204 
    205 		memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
    206 		jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
    207 		for (cp = buf, i = 0; i < nbytes; i++)
    208 			*cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
    209 		memcpy(jrand_seed, tmp_seed,
    210 		       sizeof(jrand_seed) - sizeof(unsigned short));
    211 	}
    212 #endif
    213 
    214 	return;
    215 }
    216 
    217 /*
    218  * Get the ethernet hardware address, if we can find it...
    219  *
    220  * XXX for a windows version, probably should use GetAdaptersInfo:
    221  * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451
    222  * commenting out get_node_id just to get gen_uuid to compile under windows
    223  * is not the right way to go!
    224  */
    225 static int get_node_id(unsigned char *node_id)
    226 {
    227 #ifdef HAVE_NET_IF_H
    228 	int 		sd;
    229 	struct ifreq 	ifr, *ifrp;
    230 	struct ifconf 	ifc;
    231 	char buf[1024];
    232 	int		n, i;
    233 	unsigned char 	*a;
    234 #ifdef HAVE_NET_IF_DL_H
    235 	struct sockaddr_dl *sdlp;
    236 #endif
    237 
    238 /*
    239  * BSD 4.4 defines the size of an ifreq to be
    240  * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
    241  * However, under earlier systems, sa_len isn't present, so the size is
    242  * just sizeof(struct ifreq)
    243  */
    244 #ifdef HAVE_SA_LEN
    245 #ifndef max
    246 #define max(a,b) ((a) > (b) ? (a) : (b))
    247 #endif
    248 #define ifreq_size(i) max(sizeof(struct ifreq),\
    249      sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
    250 #else
    251 #define ifreq_size(i) sizeof(struct ifreq)
    252 #endif /* HAVE_SA_LEN*/
    253 
    254 	sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    255 	if (sd < 0) {
    256 		return -1;
    257 	}
    258 	memset(buf, 0, sizeof(buf));
    259 	ifc.ifc_len = sizeof(buf);
    260 	ifc.ifc_buf = buf;
    261 	if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
    262 		close(sd);
    263 		return -1;
    264 	}
    265 	n = ifc.ifc_len;
    266 	for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
    267 		ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
    268 		strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
    269 #ifdef SIOCGIFHWADDR
    270 		if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    271 			continue;
    272 		a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
    273 #else
    274 #ifdef SIOCGENADDR
    275 		if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
    276 			continue;
    277 		a = (unsigned char *) ifr.ifr_enaddr;
    278 #else
    279 #ifdef HAVE_NET_IF_DL_H
    280 		sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
    281 		if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
    282 			continue;
    283 		a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
    284 #else
    285 		/*
    286 		 * XXX we don't have a way of getting the hardware
    287 		 * address
    288 		 */
    289 		close(sd);
    290 		return 0;
    291 #endif /* HAVE_NET_IF_DL_H */
    292 #endif /* SIOCGENADDR */
    293 #endif /* SIOCGIFHWADDR */
    294 		if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
    295 			continue;
    296 		if (node_id) {
    297 			memcpy(node_id, a, 6);
    298 			close(sd);
    299 			return 1;
    300 		}
    301 	}
    302 	close(sd);
    303 #endif
    304 	return 0;
    305 }
    306 
    307 /* Assume that the gettimeofday() has microsecond granularity */
    308 #define MAX_ADJUSTMENT 10
    309 
    310 static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
    311 		     uint16_t *ret_clock_seq, int *num)
    312 {
    313 	THREAD_LOCAL int		adjustment = 0;
    314 	THREAD_LOCAL struct timeval	last = {0, 0};
    315 	THREAD_LOCAL int		state_fd = -2;
    316 	THREAD_LOCAL FILE		*state_f;
    317 	THREAD_LOCAL uint16_t		clock_seq;
    318 	struct timeval 			tv;
    319 #ifndef _WIN32
    320 	struct flock			fl;
    321 #endif
    322 	uint64_t			clock_reg;
    323 	mode_t				save_umask;
    324 	int				len;
    325 
    326 	if (state_fd == -2) {
    327 		save_umask = umask(0);
    328 		state_fd = open("/var/lib/libuuid/clock.txt",
    329 				O_RDWR|O_CREAT, 0660);
    330 		(void) umask(save_umask);
    331 		if (state_fd >= 0) {
    332 			state_f = fdopen(state_fd, "r+");
    333 			if (!state_f) {
    334 				close(state_fd);
    335 				state_fd = -1;
    336 			}
    337 		}
    338 	}
    339 #ifndef _WIN32
    340 	fl.l_type = F_WRLCK;
    341 	fl.l_whence = SEEK_SET;
    342 	fl.l_start = 0;
    343 	fl.l_len = 0;
    344 	fl.l_pid = 0;
    345 	if (state_fd >= 0) {
    346 		rewind(state_f);
    347 		while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
    348 			if ((errno == EAGAIN) || (errno == EINTR))
    349 				continue;
    350 			fclose(state_f);
    351 			state_fd = -1;
    352 			break;
    353 		}
    354 	}
    355 #endif
    356 	if (state_fd >= 0) {
    357 		unsigned int cl;
    358 		unsigned long tv1, tv2;
    359 		int a;
    360 
    361 		if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
    362 			   &cl, &tv1, &tv2, &a) == 4) {
    363 			clock_seq = cl & 0x3FFF;
    364 			last.tv_sec = tv1;
    365 			last.tv_usec = tv2;
    366 			adjustment = a;
    367 		}
    368 	}
    369 
    370 	if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
    371 		get_random_bytes(&clock_seq, sizeof(clock_seq));
    372 		clock_seq &= 0x3FFF;
    373 		gettimeofday(&last, 0);
    374 		last.tv_sec--;
    375 	}
    376 
    377 try_again:
    378 	gettimeofday(&tv, 0);
    379 	if ((tv.tv_sec < last.tv_sec) ||
    380 	    ((tv.tv_sec == last.tv_sec) &&
    381 	     (tv.tv_usec < last.tv_usec))) {
    382 		clock_seq = (clock_seq+1) & 0x3FFF;
    383 		adjustment = 0;
    384 		last = tv;
    385 	} else if ((tv.tv_sec == last.tv_sec) &&
    386 	    (tv.tv_usec == last.tv_usec)) {
    387 		if (adjustment >= MAX_ADJUSTMENT)
    388 			goto try_again;
    389 		adjustment++;
    390 	} else {
    391 		adjustment = 0;
    392 		last = tv;
    393 	}
    394 
    395 	clock_reg = tv.tv_usec*10 + adjustment;
    396 	clock_reg += ((uint64_t) tv.tv_sec)*10000000;
    397 	clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
    398 
    399 	if (num && (*num > 1)) {
    400 		adjustment += *num - 1;
    401 		last.tv_usec += adjustment / 10;
    402 		adjustment = adjustment % 10;
    403 		last.tv_sec += last.tv_usec / 1000000;
    404 		last.tv_usec = last.tv_usec % 1000000;
    405 	}
    406 
    407 	if (state_fd > 0) {
    408 		rewind(state_f);
    409 		len = fprintf(state_f,
    410 			      "clock: %04x tv: %016lu %08lu adj: %08d\n",
    411 			      clock_seq, last.tv_sec, (long)last.tv_usec,
    412 			      adjustment);
    413 		fflush(state_f);
    414 		if (ftruncate(state_fd, len) < 0) {
    415 			fprintf(state_f, "                   \n");
    416 			fflush(state_f);
    417 		}
    418 		rewind(state_f);
    419 #ifndef _WIN32
    420 		fl.l_type = F_UNLCK;
    421 		if (fcntl(state_fd, F_SETLK, &fl) < 0) {
    422 			fclose(state_f);
    423 			state_fd = -1;
    424 		}
    425 #endif
    426 	}
    427 
    428 	*clock_high = clock_reg >> 32;
    429 	*clock_low = clock_reg;
    430 	*ret_clock_seq = clock_seq;
    431 	return 0;
    432 }
    433 
    434 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
    435 static ssize_t read_all(int fd, char *buf, size_t count)
    436 {
    437 	ssize_t ret;
    438 	ssize_t c = 0;
    439 	int tries = 0;
    440 
    441 	memset(buf, 0, count);
    442 	while (count > 0) {
    443 		ret = read(fd, buf, count);
    444 		if (ret <= 0) {
    445 			if ((errno == EAGAIN || errno == EINTR || ret == 0) &&
    446 			    (tries++ < 5))
    447 				continue;
    448 			return c ? c : -1;
    449 		}
    450 		if (ret > 0)
    451 			tries = 0;
    452 		count -= ret;
    453 		buf += ret;
    454 		c += ret;
    455 	}
    456 	return c;
    457 }
    458 
    459 /*
    460  * Close all file descriptors
    461  */
    462 static void close_all_fds(void)
    463 {
    464 	int i, max;
    465 
    466 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
    467 	max = sysconf(_SC_OPEN_MAX);
    468 #elif defined(HAVE_GETDTABLESIZE)
    469 	max = getdtablesize();
    470 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
    471 	struct rlimit rl;
    472 
    473 	getrlimit(RLIMIT_NOFILE, &rl);
    474 	max = rl.rlim_cur;
    475 #else
    476 	max = OPEN_MAX;
    477 #endif
    478 
    479 	for (i=0; i < max; i++) {
    480 		close(i);
    481 		if (i <= 2)
    482 			open("/dev/null", O_RDWR);
    483 	}
    484 }
    485 #endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */
    486 
    487 #pragma GCC diagnostic push
    488 #if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H)
    489 #pragma GCC diagnostic ignored "-Wunused-parameter"
    490 #endif
    491 /*
    492  * Try using the uuidd daemon to generate the UUID
    493  *
    494  * Returns 0 on success, non-zero on failure.
    495  */
    496 static int get_uuid_via_daemon(int op, uuid_t out, int *num)
    497 {
    498 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
    499 	char op_buf[64];
    500 	int op_len;
    501 	int s;
    502 	ssize_t ret;
    503 	int32_t reply_len = 0, expected = 16;
    504 	struct sockaddr_un srv_addr;
    505 	struct stat st;
    506 	pid_t pid;
    507 	static const char *uuidd_path = UUIDD_PATH;
    508 	static int access_ret = -2;
    509 	static int start_attempts = 0;
    510 
    511 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    512 		return -1;
    513 
    514 	srv_addr.sun_family = AF_UNIX;
    515 	strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
    516 
    517 	if (connect(s, (const struct sockaddr *) &srv_addr,
    518 		    sizeof(struct sockaddr_un)) < 0) {
    519 		if (access_ret == -2)
    520 			access_ret = access(uuidd_path, X_OK);
    521 		if (access_ret == 0)
    522 			access_ret = stat(uuidd_path, &st);
    523 		if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0)
    524 			access_ret = access(UUIDD_DIR, W_OK);
    525 		if (access_ret == 0 && start_attempts++ < 5) {
    526 			if ((pid = fork()) == 0) {
    527 				close_all_fds();
    528 				execl(uuidd_path, "uuidd", "-qT", "300",
    529 				      (char *) NULL);
    530 				exit(1);
    531 			}
    532 			(void) waitpid(pid, 0, 0);
    533 			if (connect(s, (const struct sockaddr *) &srv_addr,
    534 				    sizeof(struct sockaddr_un)) < 0)
    535 				goto fail;
    536 		} else
    537 			goto fail;
    538 	}
    539 	op_buf[0] = op;
    540 	op_len = 1;
    541 	if (op == UUIDD_OP_BULK_TIME_UUID) {
    542 		memcpy(op_buf+1, num, sizeof(*num));
    543 		op_len += sizeof(*num);
    544 		expected += sizeof(*num);
    545 	}
    546 
    547 	ret = write(s, op_buf, op_len);
    548 	if (ret < 1)
    549 		goto fail;
    550 
    551 	ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
    552 	if (ret < 0)
    553 		goto fail;
    554 
    555 	if (reply_len != expected)
    556 		goto fail;
    557 
    558 	ret = read_all(s, op_buf, reply_len);
    559 
    560 	if (op == UUIDD_OP_BULK_TIME_UUID)
    561 		memcpy(op_buf+16, num, sizeof(int));
    562 
    563 	memcpy(out, op_buf, 16);
    564 
    565 	close(s);
    566 	return ((ret == expected) ? 0 : -1);
    567 
    568 fail:
    569 	close(s);
    570 #endif
    571 	return -1;
    572 }
    573 #pragma GCC diagnostic pop
    574 
    575 void uuid__generate_time(uuid_t out, int *num)
    576 {
    577 	static unsigned char node_id[6];
    578 	static int has_init = 0;
    579 	struct uuid uu;
    580 	uint32_t	clock_mid;
    581 
    582 	if (!has_init) {
    583 		if (get_node_id(node_id) <= 0) {
    584 			get_random_bytes(node_id, 6);
    585 			/*
    586 			 * Set multicast bit, to prevent conflicts
    587 			 * with IEEE 802 addresses obtained from
    588 			 * network cards
    589 			 */
    590 			node_id[0] |= 0x01;
    591 		}
    592 		has_init = 1;
    593 	}
    594 	get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
    595 	uu.clock_seq |= 0x8000;
    596 	uu.time_mid = (uint16_t) clock_mid;
    597 	uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
    598 	memcpy(uu.node, node_id, 6);
    599 	uuid_pack(&uu, out);
    600 }
    601 
    602 void uuid_generate_time(uuid_t out)
    603 {
    604 #ifdef TLS
    605 	THREAD_LOCAL int		num = 0;
    606 	THREAD_LOCAL struct uuid	uu;
    607 	THREAD_LOCAL time_t		last_time = 0;
    608 	time_t				now;
    609 
    610 	if (num > 0) {
    611 		now = time(0);
    612 		if (now > last_time+1)
    613 			num = 0;
    614 	}
    615 	if (num <= 0) {
    616 		num = 1000;
    617 		if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
    618 					out, &num) == 0) {
    619 			last_time = time(0);
    620 			uuid_unpack(out, &uu);
    621 			num--;
    622 			return;
    623 		}
    624 		num = 0;
    625 	}
    626 	if (num > 0) {
    627 		uu.time_low++;
    628 		if (uu.time_low == 0) {
    629 			uu.time_mid++;
    630 			if (uu.time_mid == 0)
    631 				uu.time_hi_and_version++;
    632 		}
    633 		num--;
    634 		uuid_pack(&uu, out);
    635 		return;
    636 	}
    637 #else
    638 	if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
    639 		return;
    640 #endif
    641 
    642 	uuid__generate_time(out, 0);
    643 }
    644 
    645 
    646 void uuid__generate_random(uuid_t out, int *num)
    647 {
    648 	uuid_t	buf;
    649 	struct uuid uu;
    650 	int i, n;
    651 
    652 	if (!num || !*num)
    653 		n = 1;
    654 	else
    655 		n = *num;
    656 
    657 	for (i = 0; i < n; i++) {
    658 		get_random_bytes(buf, sizeof(buf));
    659 		uuid_unpack(buf, &uu);
    660 
    661 		uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
    662 		uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
    663 			| 0x4000;
    664 		uuid_pack(&uu, out);
    665 		out += sizeof(uuid_t);
    666 	}
    667 }
    668 
    669 void uuid_generate_random(uuid_t out)
    670 {
    671 	int	num = 1;
    672 	/* No real reason to use the daemon for random uuid's -- yet */
    673 
    674 	uuid__generate_random(out, &num);
    675 }
    676 
    677 
    678 /*
    679  * This is the generic front-end to uuid_generate_random and
    680  * uuid_generate_time.  It uses uuid_generate_random only if
    681  * /dev/urandom is available, since otherwise we won't have
    682  * high-quality randomness.
    683  */
    684 void uuid_generate(uuid_t out)
    685 {
    686 	if (get_random_fd() >= 0)
    687 		uuid_generate_random(out);
    688 	else
    689 		uuid_generate_time(out);
    690 }
    691