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 
     41 #include <stdio.h>
     42 #ifdef HAVE_UNISTD_H
     43 #include <unistd.h>
     44 #endif
     45 #ifdef HAVE_STDLIB_H
     46 #include <stdlib.h>
     47 #endif
     48 #include <string.h>
     49 #include <fcntl.h>
     50 #include <errno.h>
     51 #include <sys/types.h>
     52 #include <sys/time.h>
     53 #include <sys/wait.h>
     54 #include <sys/stat.h>
     55 #include <sys/file.h>
     56 #ifdef HAVE_SYS_IOCTL_H
     57 #include <sys/ioctl.h>
     58 #endif
     59 #ifdef HAVE_SYS_SOCKET_H
     60 #include <sys/socket.h>
     61 #endif
     62 #ifdef HAVE_SYS_UN_H
     63 #include <sys/un.h>
     64 #endif
     65 #ifdef HAVE_SYS_SOCKIO_H
     66 #include <sys/sockio.h>
     67 #endif
     68 #ifdef HAVE_NET_IF_H
     69 #include <net/if.h>
     70 #endif
     71 #ifdef HAVE_NETINET_IN_H
     72 #include <netinet/in.h>
     73 #endif
     74 #ifdef HAVE_NET_IF_DL_H
     75 #include <net/if_dl.h>
     76 #endif
     77 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
     78 #include <sys/syscall.h>
     79 #endif
     80 
     81 #include "uuidP.h"
     82 #include "uuidd.h"
     83 
     84 #ifdef HAVE_SRANDOM
     85 #define srand(x) 	srandom(x)
     86 #define rand() 		random()
     87 #endif
     88 
     89 #ifdef TLS
     90 #define THREAD_LOCAL static TLS
     91 #else
     92 #define THREAD_LOCAL static
     93 #endif
     94 
     95 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
     96 #define DO_JRAND_MIX
     97 THREAD_LOCAL unsigned short jrand_seed[3];
     98 #endif
     99 
    100 static int get_random_fd(void)
    101 {
    102 	struct timeval	tv;
    103 	static int	fd = -2;
    104 	int		i;
    105 
    106 	if (fd == -2) {
    107 		gettimeofday(&tv, 0);
    108 		fd = open("/dev/urandom", O_RDONLY);
    109 		if (fd == -1)
    110 			fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
    111 		if (fd >= 0) {
    112 			i = fcntl(fd, F_GETFD);
    113 			if (i >= 0)
    114 				fcntl(fd, F_SETFD, i | FD_CLOEXEC);
    115 		}
    116 		srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
    117 #ifdef DO_JRAND_MIX
    118 		jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
    119 		jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
    120 		jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
    121 #endif
    122 	}
    123 	/* Crank the random number generator a few times */
    124 	gettimeofday(&tv, 0);
    125 	for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
    126 		rand();
    127 	return fd;
    128 }
    129 
    130 
    131 /*
    132  * Generate a series of random bytes.  Use /dev/urandom if possible,
    133  * and if not, use srandom/random.
    134  */
    135 static void get_random_bytes(void *buf, int nbytes)
    136 {
    137 	int i, n = nbytes, fd = get_random_fd();
    138 	int lose_counter = 0;
    139 	unsigned char *cp = (unsigned char *) buf;
    140 	unsigned short tmp_seed[3];
    141 
    142 	if (fd >= 0) {
    143 		while (n > 0) {
    144 			i = read(fd, cp, n);
    145 			if (i <= 0) {
    146 				if (lose_counter++ > 16)
    147 					break;
    148 				continue;
    149 			}
    150 			n -= i;
    151 			cp += i;
    152 			lose_counter = 0;
    153 		}
    154 	}
    155 
    156 	/*
    157 	 * We do this all the time, but this is the only source of
    158 	 * randomness if /dev/random/urandom is out to lunch.
    159 	 */
    160 	for (cp = buf, i = 0; i < nbytes; i++)
    161 		*cp++ ^= (rand() >> 7) & 0xFF;
    162 #ifdef DO_JRAND_MIX
    163 	memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
    164 	jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
    165 	for (cp = buf, i = 0; i < nbytes; i++)
    166 		*cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
    167 	memcpy(jrand_seed, tmp_seed,
    168 	       sizeof(jrand_seed)-sizeof(unsigned short));
    169 #endif
    170 
    171 	return;
    172 }
    173 
    174 /*
    175  * Get the ethernet hardware address, if we can find it...
    176  */
    177 static int get_node_id(unsigned char *node_id)
    178 {
    179 #ifdef HAVE_NET_IF_H
    180 	int 		sd;
    181 	struct ifreq 	ifr, *ifrp;
    182 	struct ifconf 	ifc;
    183 	char buf[1024];
    184 	int		n, i;
    185 	unsigned char 	*a;
    186 #ifdef HAVE_NET_IF_DL_H
    187 	struct sockaddr_dl *sdlp;
    188 #endif
    189 
    190 /*
    191  * BSD 4.4 defines the size of an ifreq to be
    192  * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
    193  * However, under earlier systems, sa_len isn't present, so the size is
    194  * just sizeof(struct ifreq)
    195  */
    196 #ifdef HAVE_SA_LEN
    197 #ifndef max
    198 #define max(a,b) ((a) > (b) ? (a) : (b))
    199 #endif
    200 #define ifreq_size(i) max(sizeof(struct ifreq),\
    201      sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
    202 #else
    203 #define ifreq_size(i) sizeof(struct ifreq)
    204 #endif /* HAVE_SA_LEN*/
    205 
    206 	sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    207 	if (sd < 0) {
    208 		return -1;
    209 	}
    210 	memset(buf, 0, sizeof(buf));
    211 	ifc.ifc_len = sizeof(buf);
    212 	ifc.ifc_buf = buf;
    213 	if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
    214 		close(sd);
    215 		return -1;
    216 	}
    217 	n = ifc.ifc_len;
    218 	for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
    219 		ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
    220 		strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
    221 #ifdef SIOCGIFHWADDR
    222 		if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    223 			continue;
    224 		a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
    225 #else
    226 #ifdef SIOCGENADDR
    227 		if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
    228 			continue;
    229 		a = (unsigned char *) ifr.ifr_enaddr;
    230 #else
    231 #ifdef HAVE_NET_IF_DL_H
    232 		sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
    233 		if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
    234 			continue;
    235 		a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
    236 #else
    237 		/*
    238 		 * XXX we don't have a way of getting the hardware
    239 		 * address
    240 		 */
    241 		close(sd);
    242 		return 0;
    243 #endif /* HAVE_NET_IF_DL_H */
    244 #endif /* SIOCGENADDR */
    245 #endif /* SIOCGIFHWADDR */
    246 		if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
    247 			continue;
    248 		if (node_id) {
    249 			memcpy(node_id, a, 6);
    250 			close(sd);
    251 			return 1;
    252 		}
    253 	}
    254 	close(sd);
    255 #endif
    256 	return 0;
    257 }
    258 
    259 /* Assume that the gettimeofday() has microsecond granularity */
    260 #define MAX_ADJUSTMENT 10
    261 
    262 static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
    263 		     uint16_t *ret_clock_seq, int *num)
    264 {
    265 	THREAD_LOCAL int		adjustment = 0;
    266 	THREAD_LOCAL struct timeval	last = {0, 0};
    267 	THREAD_LOCAL int		state_fd = -2;
    268 	THREAD_LOCAL FILE		*state_f;
    269 	THREAD_LOCAL uint16_t		clock_seq;
    270 	struct timeval 			tv;
    271 	struct flock			fl;
    272 	unsigned long long		clock_reg;
    273 	mode_t				save_umask;
    274 
    275 	if (state_fd == -2) {
    276 		save_umask = umask(0);
    277 		state_fd = open("/var/lib/libuuid/clock.txt",
    278 				O_RDWR|O_CREAT, 0660);
    279 		(void) umask(save_umask);
    280 		state_f = fdopen(state_fd, "r+");
    281 		if (!state_f) {
    282 			close(state_fd);
    283 			state_fd = -1;
    284 		}
    285 	}
    286 	fl.l_type = F_WRLCK;
    287 	fl.l_whence = SEEK_SET;
    288 	fl.l_start = 0;
    289 	fl.l_len = 0;
    290 	fl.l_pid = 0;
    291 	if (state_fd >= 0) {
    292 		rewind(state_f);
    293 		while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
    294 			if ((errno == EAGAIN) || (errno == EINTR))
    295 				continue;
    296 			fclose(state_f);
    297 			close(state_fd);
    298 			state_fd = -1;
    299 			break;
    300 		}
    301 	}
    302 	if (state_fd >= 0) {
    303 		unsigned int cl;
    304 		unsigned long tv1, tv2;
    305 		int a;
    306 
    307 		if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
    308 			   &cl, &tv1, &tv2, &a) == 4) {
    309 			clock_seq = cl & 0x3FFF;
    310 			last.tv_sec = tv1;
    311 			last.tv_usec = tv2;
    312 			adjustment = a;
    313 		}
    314 	}
    315 
    316 	if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
    317 		get_random_bytes(&clock_seq, sizeof(clock_seq));
    318 		clock_seq &= 0x3FFF;
    319 		last = tv;
    320 		last.tv_sec--;
    321 	}
    322 
    323 try_again:
    324 	gettimeofday(&tv, 0);
    325 	if ((tv.tv_sec < last.tv_sec) ||
    326 	    ((tv.tv_sec == last.tv_sec) &&
    327 	     (tv.tv_usec < last.tv_usec))) {
    328 		clock_seq = (clock_seq+1) & 0x3FFF;
    329 		adjustment = 0;
    330 		last = tv;
    331 	} else if ((tv.tv_sec == last.tv_sec) &&
    332 	    (tv.tv_usec == last.tv_usec)) {
    333 		if (adjustment >= MAX_ADJUSTMENT)
    334 			goto try_again;
    335 		adjustment++;
    336 	} else {
    337 		adjustment = 0;
    338 		last = tv;
    339 	}
    340 
    341 	clock_reg = tv.tv_usec*10 + adjustment;
    342 	clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
    343 	clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
    344 
    345 	if (num && (*num > 1)) {
    346 		adjustment += *num - 1;
    347 		last.tv_usec += adjustment / 10;
    348 		adjustment = adjustment % 10;
    349 		last.tv_sec += last.tv_usec / 1000000;
    350 		last.tv_usec = last.tv_usec % 1000000;
    351 	}
    352 
    353 	if (state_fd > 0) {
    354 		rewind(state_f);
    355 		ftruncate(state_fd, 0);
    356 		fprintf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
    357 			clock_seq, last.tv_sec, last.tv_usec, adjustment);
    358 		fflush(state_f);
    359 		rewind(state_f);
    360 		fl.l_type = F_UNLCK;
    361 		fcntl(state_fd, F_SETLK, &fl);
    362 	}
    363 
    364 	*clock_high = clock_reg >> 32;
    365 	*clock_low = clock_reg;
    366 	*ret_clock_seq = clock_seq;
    367 	return 0;
    368 }
    369 
    370 static ssize_t read_all(int fd, char *buf, size_t count)
    371 {
    372 	ssize_t ret;
    373 	ssize_t c = 0;
    374 
    375 	memset(buf, 0, count);
    376 	while (count > 0) {
    377 		ret = read(fd, buf, count);
    378 		if (ret < 0) {
    379 			if ((errno == EAGAIN) || (errno == EINTR))
    380 				continue;
    381 			return -1;
    382 		}
    383 		count -= ret;
    384 		buf += ret;
    385 		c += ret;
    386 	}
    387 	return c;
    388 }
    389 
    390 
    391 /*
    392  * Try using the uuidd daemon to generate the UUID
    393  *
    394  * Returns 0 on success, non-zero on failure.
    395  */
    396 static int get_uuid_via_daemon(int op, uuid_t out, int *num)
    397 {
    398 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
    399 	char op_buf[64];
    400 	int op_len;
    401 	int s;
    402 	ssize_t ret;
    403 	int32_t reply_len = 0, expected = 16;
    404 	struct sockaddr_un srv_addr;
    405 	pid_t pid;
    406 	static const char *uuidd_path = UUIDD_PATH;
    407 	static int access_ret = -2;
    408 	static int start_attempts = 0;
    409 
    410 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    411 		return -1;
    412 
    413 	srv_addr.sun_family = AF_UNIX;
    414 	strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
    415 
    416 	if (connect(s, (const struct sockaddr *) &srv_addr,
    417 		    sizeof(struct sockaddr_un)) < 0) {
    418 		if (access_ret == -2)
    419 			access_ret = access(uuidd_path, X_OK);
    420 		if (access_ret == 0 && start_attempts++ < 5) {
    421 			if ((pid = fork()) == 0) {
    422 				execl(uuidd_path, "uuidd", "-qT", "300",
    423 				      (char *) NULL);
    424 				exit(1);
    425 			}
    426 			(void) waitpid(pid, 0, 0);
    427 			if (connect(s, (const struct sockaddr *) &srv_addr,
    428 				    sizeof(struct sockaddr_un)) < 0)
    429 				goto fail;
    430 		} else
    431 			goto fail;
    432 	}
    433 	op_buf[0] = op;
    434 	op_len = 1;
    435 	if (op == UUIDD_OP_BULK_TIME_UUID) {
    436 		memcpy(op_buf+1, num, sizeof(*num));
    437 		op_len += sizeof(*num);
    438 		expected += sizeof(*num);
    439 	}
    440 
    441 	ret = write(s, op_buf, op_len);
    442 	if (ret < 1)
    443 		goto fail;
    444 
    445 	ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
    446 	if (ret < 0)
    447 		goto fail;
    448 
    449 	if (reply_len != expected)
    450 		goto fail;
    451 
    452 	ret = read_all(s, op_buf, reply_len);
    453 
    454 	if (op == UUIDD_OP_BULK_TIME_UUID)
    455 		memcpy(op_buf+16, num, sizeof(int));
    456 
    457 	memcpy(out, op_buf, 16);
    458 
    459 	close(s);
    460 	return ((ret == expected) ? 0 : -1);
    461 
    462 fail:
    463 	close(s);
    464 #endif
    465 	return -1;
    466 }
    467 
    468 void uuid__generate_time(uuid_t out, int *num)
    469 {
    470 	static unsigned char node_id[6];
    471 	static int has_init = 0;
    472 	struct uuid uu;
    473 	uint32_t	clock_mid;
    474 
    475 	if (!has_init) {
    476 		if (get_node_id(node_id) <= 0) {
    477 			get_random_bytes(node_id, 6);
    478 			/*
    479 			 * Set multicast bit, to prevent conflicts
    480 			 * with IEEE 802 addresses obtained from
    481 			 * network cards
    482 			 */
    483 			node_id[0] |= 0x01;
    484 		}
    485 		has_init = 1;
    486 	}
    487 	get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
    488 	uu.clock_seq |= 0x8000;
    489 	uu.time_mid = (uint16_t) clock_mid;
    490 	uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
    491 	memcpy(uu.node, node_id, 6);
    492 	uuid_pack(&uu, out);
    493 }
    494 
    495 void uuid_generate_time(uuid_t out)
    496 {
    497 #ifdef TLS
    498 	THREAD_LOCAL int		num = 0;
    499 	THREAD_LOCAL struct uuid	uu;
    500 	THREAD_LOCAL time_t		last_time = 0;
    501 	time_t				now;
    502 
    503 	if (num > 0) {
    504 		now = time(0);
    505 		if (now > last_time+1)
    506 			num = 0;
    507 	}
    508 	if (num <= 0) {
    509 		num = 1000;
    510 		if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
    511 					out, &num) == 0) {
    512 			last_time = time(0);
    513 			uuid_unpack(out, &uu);
    514 			num--;
    515 			return;
    516 		}
    517 		num = 0;
    518 	}
    519 	if (num > 0) {
    520 		uu.time_low++;
    521 		if (uu.time_low == 0) {
    522 			uu.time_mid++;
    523 			if (uu.time_mid == 0)
    524 				uu.time_hi_and_version++;
    525 		}
    526 		num--;
    527 		uuid_pack(&uu, out);
    528 		return;
    529 	}
    530 #else
    531 	if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
    532 		return;
    533 #endif
    534 
    535 	uuid__generate_time(out, 0);
    536 }
    537 
    538 
    539 void uuid__generate_random(uuid_t out, int *num)
    540 {
    541 	uuid_t	buf;
    542 	struct uuid uu;
    543 	int i, n;
    544 
    545 	if (!num || !*num)
    546 		n = 1;
    547 	else
    548 		n = *num;
    549 
    550 	for (i = 0; i < n; i++) {
    551 		get_random_bytes(buf, sizeof(buf));
    552 		uuid_unpack(buf, &uu);
    553 
    554 		uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
    555 		uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
    556 			| 0x4000;
    557 		uuid_pack(&uu, out);
    558 		out += sizeof(uuid_t);
    559 	}
    560 }
    561 
    562 void uuid_generate_random(uuid_t out)
    563 {
    564 	int	num = 1;
    565 	/* No real reason to use the daemon for random uuid's -- yet */
    566 
    567 	uuid__generate_random(out, &num);
    568 }
    569 
    570 
    571 /*
    572  * This is the generic front-end to uuid_generate_random and
    573  * uuid_generate_time.  It uses uuid_generate_random only if
    574  * /dev/urandom is available, since otherwise we won't have
    575  * high-quality randomness.
    576  */
    577 void uuid_generate(uuid_t out)
    578 {
    579 	if (get_random_fd() >= 0)
    580 		uuid_generate_random(out);
    581 	else
    582 		uuid_generate_time(out);
    583 }
    584