4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 * Copyright 2013 Joyent, Inc. All rights reserved.
29 * The copyright in this file is taken from the original Leach & Salz
30 * UUID specification, from which this implementation is derived.
34 * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
35 * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
36 * Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1998
37 * Microsoft. To anyone who acknowledges that this file is provided
38 * "AS IS" without any express or implied warranty: permission to use,
39 * copy, modify, and distribute this file for any purpose is hereby
40 * granted without fee, provided that the above copyright notices and
41 * this notice appears in all source code copies, and that none of the
42 * names of Open Software Foundation, Inc., Hewlett-Packard Company,
43 * or Digital Equipment Corporation be used in advertising or
44 * publicity pertaining to distribution of the software without
45 * specific, written prior permission. Neither Open Software
46 * Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital
47 * Equipment Corporation makes any representations about the
48 * suitability of this software for any purpose.
52 * This module is the workhorse for generating abstract
53 * UUIDs. It delegates system-specific tasks (such
54 * as obtaining the node identifier or system time)
55 * to the sysdep module.
59 #include <sys/param.h>
69 #include "uuid_misc.h"
71 shared_buffer_t
*data
;
73 static uuid_node_t node_id_cache
;
79 * The urandmtx mutex prevents multiple opens of /dev/urandom and protects the
82 #define RCACHE_SIZE 65535
83 static mutex_t urandmtx
;
84 static int fd_urand
= -1;
85 static char rcache
[RCACHE_SIZE
];
86 static char *rcachep
= rcache
;
91 uint16_t get_random(void);
92 void get_current_time(uuid_time_t
*);
94 void struct_to_string(uuid_t
, struct uuid
*);
95 void string_to_struct(struct uuid
*, uuid_t
);
96 int get_ethernet_address(uuid_node_t
*);
101 static int map_state();
102 static void format_uuid(struct uuid
*, uint16_t, uuid_time_t
,
104 static void fill_random_bytes(uchar_t
*, int);
105 static int uuid_create(struct uuid
*);
106 static void gen_ethernet_address(uuid_node_t
*);
107 static void revalidate_data(uuid_node_t
*);
110 * Generates a uuid based on version 1 format.
111 * Returns 0 on success and -1 on failure.
114 uuid_create(struct uuid
*uuid
)
116 uuid_time_t timestamp
;
117 uuid_node_t system_node
;
118 int ret
, non_unique
= 0;
121 * Get the system MAC address and/or cache it
124 bcopy(&node_id_cache
, &system_node
, sizeof (uuid_node_t
));
126 gen_ethernet_address(&system_node
);
127 bcopy(&system_node
, &node_id_cache
, sizeof (uuid_node_t
));
132 * Access the state file, mmap it and initialize the shared lock.
133 * file_type tells us whether we had access to the state file or
134 * created a temporary one.
136 if (map_state() == -1)
143 if ((ret
= mutex_lock(&data
->lock
)) == 0)
148 revalidate_data(&system_node
);
149 (void) mutex_consistent(&data
->lock
);
150 (void) mutex_unlock(&data
->lock
);
152 case ENOTRECOVERABLE
:
157 /* State file is either new or is temporary, get a random clock seq */
158 if (data
->state
.clock
== 0) {
159 data
->state
.clock
= get_random();
163 if (memcmp(&system_node
, &data
->state
.node
, sizeof (uuid_node_t
)) != 0)
166 get_current_time(×tamp
);
169 * If timestamp is not set or is not in the past, bump
172 if ((data
->state
.ts
== 0) || (data
->state
.ts
>= timestamp
)) {
174 data
->state
.ts
= timestamp
;
178 system_node
.nodeID
[0] |= 0x80;
180 /* Stuff fields into the UUID struct */
181 format_uuid(uuid
, data
->state
.clock
, timestamp
, system_node
);
183 (void) mutex_unlock(&data
->lock
);
189 * Fills system_node with Ethernet address if available,
190 * else fills random numbers
193 gen_ethernet_address(uuid_node_t
*system_node
)
197 if (get_ethernet_address(system_node
) != 0) {
198 fill_random_bytes(node
, 6);
199 (void) memcpy(system_node
->nodeID
, node
, 6);
201 * use 8:0:20 with the multicast bit set
202 * to avoid namespace collisions.
204 system_node
->nodeID
[0] = 0x88;
205 system_node
->nodeID
[1] = 0x00;
206 system_node
->nodeID
[2] = 0x20;
211 * Formats a UUID, given the clock_seq timestamp, and node address.
212 * Fills in passed-in pointer with the resulting uuid.
215 format_uuid(struct uuid
*uuid
, uint16_t clock_seq
,
216 uuid_time_t timestamp
, uuid_node_t node
)
220 * First set up the first 60 bits from the timestamp
222 uuid
->time_low
= (uint32_t)(timestamp
& 0xFFFFFFFF);
223 uuid
->time_mid
= (uint16_t)((timestamp
>> 32) & 0xFFFF);
224 uuid
->time_hi_and_version
= (uint16_t)((timestamp
>> 48) & 0x0FFF);
227 * This is version 1, so say so in the UUID version field (4 bits)
229 uuid
->time_hi_and_version
|= (1 << 12);
232 * Now do the clock sequence
234 uuid
->clock_seq_low
= clock_seq
& 0xFF;
237 * We must save the most-significant 2 bits for the reserved field
239 uuid
->clock_seq_hi_and_reserved
= (clock_seq
& 0x3F00) >> 8;
242 * The variant for this format is the 2 high bits set to 10,
245 uuid
->clock_seq_hi_and_reserved
|= 0x80;
248 * write result to passed-in pointer
250 (void) memcpy(&uuid
->node_addr
, &node
, sizeof (uuid
->node_addr
));
254 * Opens/creates the state file, falling back to a tmp
261 /* If file's mapped, return */
265 if ((fd
= open(STATE_LOCATION
, O_RDWR
)) < 0) {
266 file_type
= TEMP_FILE
;
268 if ((tmp
= tmpfile()) == NULL
)
273 file_type
= STATE_FILE
;
276 (void) ftruncate(fd
, (off_t
)sizeof (shared_buffer_t
));
278 /* LINTED - alignment */
279 data
= (shared_buffer_t
*)mmap(NULL
, sizeof (shared_buffer_t
),
280 PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0);
282 if (data
== MAP_FAILED
)
285 (void) mutex_init(&data
->lock
, USYNC_PROCESS
|LOCK_ROBUST
, 0);
293 revalidate_data(uuid_node_t
*node
)
299 for (i
= 0; i
< sizeof (data
->state
.node
.nodeID
); i
++)
300 data
->state
.node
.nodeID
[i
] = 0;
302 data
->state
.clock
= 0;
304 gen_ethernet_address(node
);
305 bcopy(node
, &node_id_cache
, sizeof (uuid_node_t
));
310 * Prints a nicely-formatted uuid to stdout.
313 uuid_print(struct uuid u
)
317 (void) printf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", u
.time_low
, u
.time_mid
,
318 u
.time_hi_and_version
, u
.clock_seq_hi_and_reserved
,
320 for (i
= 0; i
< 6; i
++)
321 (void) printf("%2.2x", u
.node_addr
[i
]);
326 * Only called with urandmtx held.
327 * Fills/refills the cache of randomness. We know that our allocations of
328 * randomness are always much less than the total size of the cache.
329 * Tries to use /dev/urandom random number generator - if that fails for some
330 * reason, it retries MAX_RETRY times then sets rcachep to NULL so we no
331 * longer use the cache.
337 int nbytes
= RCACHE_SIZE
;
341 i
= read(fd_urand
, buf
, nbytes
);
342 if ((i
< 0) && (errno
== EINTR
)) {
346 if (retries
++ == MAX_RETRY
)
361 * Fills buf with random numbers - nbytes is the number of bytes
362 * to fill-in. Tries to use cached data from the /dev/urandom random number
363 * generator - if that fails for some reason, it uses srand48(3C)
366 fill_random_bytes(uchar_t
*buf
, int nbytes
)
370 if (fd_urand
== -1) {
371 (void) mutex_lock(&urandmtx
);
372 /* check again now that we have the mutex */
373 if (fd_urand
== -1) {
374 if ((fd_urand
= open(URANDOM_PATH
, O_RDONLY
)) >= 0)
377 (void) mutex_unlock(&urandmtx
);
379 if (fd_urand
>= 0 && rcachep
!= NULL
) {
382 (void) mutex_lock(&urandmtx
);
383 if (rcachep
!= NULL
&&
384 (rcachep
+ nbytes
) >= (rcache
+ RCACHE_SIZE
))
387 if (rcachep
!= NULL
) {
388 for (cnt
= 0; cnt
< nbytes
; cnt
++)
390 (void) mutex_unlock(&urandmtx
);
393 (void) mutex_unlock(&urandmtx
);
395 for (i
= 0; i
< nbytes
; i
++) {
396 *buf
++ = get_random() & 0xFF;
401 * Unpacks the structure members in "struct uuid" to a char string "uuid_t".
404 struct_to_string(uuid_t ptr
, struct uuid
*uu
)
410 out
[3] = (uchar_t
)tmp
;
412 out
[2] = (uchar_t
)tmp
;
414 out
[1] = (uchar_t
)tmp
;
416 out
[0] = (uchar_t
)tmp
;
419 out
[5] = (uchar_t
)tmp
;
421 out
[4] = (uchar_t
)tmp
;
423 tmp
= uu
->time_hi_and_version
;
424 out
[7] = (uchar_t
)tmp
;
426 out
[6] = (uchar_t
)tmp
;
428 tmp
= uu
->clock_seq_hi_and_reserved
;
429 out
[8] = (uchar_t
)tmp
;
430 tmp
= uu
->clock_seq_low
;
431 out
[9] = (uchar_t
)tmp
;
433 (void) memcpy(out
+10, uu
->node_addr
, 6);
438 * Packs the values in the "uuid_t" string into "struct uuid".
441 string_to_struct(struct uuid
*uuid
, uuid_t in
)
449 tmp
= (tmp
<< 8) | *ptr
++;
450 tmp
= (tmp
<< 8) | *ptr
++;
451 tmp
= (tmp
<< 8) | *ptr
++;
452 uuid
->time_low
= tmp
;
455 tmp
= (tmp
<< 8) | *ptr
++;
456 uuid
->time_mid
= tmp
;
459 tmp
= (tmp
<< 8) | *ptr
++;
460 uuid
->time_hi_and_version
= tmp
;
463 uuid
->clock_seq_hi_and_reserved
= tmp
;
466 uuid
->clock_seq_low
= tmp
;
468 (void) memcpy(uuid
->node_addr
, ptr
, 6);
473 * Generates UUID based on DCE Version 4
476 uuid_generate_random(uuid_t uu
)
483 (void) memset(uu
, 0, sizeof (uuid_t
));
484 (void) memset(&uuid
, 0, sizeof (struct uuid
));
486 fill_random_bytes(uu
, sizeof (uuid_t
));
487 string_to_struct(&uuid
, uu
);
489 * This is version 4, so say so in the UUID version field (4 bits)
491 uuid
.time_hi_and_version
|= (1 << 14);
493 * we don't want the bit 1 to be set also which is for version 1
495 uuid
.time_hi_and_version
&= VER1_MASK
;
498 * The variant for this format is the 2 high bits set to 10,
501 uuid
.clock_seq_hi_and_reserved
|= 0x80;
504 * Set MSB of Ethernet address to 1 to indicate that it was generated
507 uuid
.node_addr
[0] |= 0x80;
508 struct_to_string(uu
, &uuid
);
512 * Generates UUID based on DCE Version 1.
515 uuid_generate_time(uuid_t uu
)
522 if (uuid_create(&uuid
) < 0) {
523 uuid_generate_random(uu
);
527 struct_to_string(uu
, &uuid
);
531 * Creates a new UUID. The uuid will be generated based on high-quality
532 * randomness from /dev/urandom, if available by calling uuid_generate_random.
533 * If it failed to generate UUID then uuid_generate will call
534 * uuid_generate_time.
537 uuid_generate(uuid_t uu
)
542 if (fd_urand
== -1) {
543 (void) mutex_lock(&urandmtx
);
544 /* check again now that we have the mutex */
545 if (fd_urand
== -1) {
546 if ((fd_urand
= open(URANDOM_PATH
, O_RDONLY
)) >= 0)
549 (void) mutex_unlock(&urandmtx
);
552 uuid_generate_random(uu
);
554 (void) uuid_generate_time(uu
);
559 * Copies the UUID variable src to dst.
562 uuid_copy(uuid_t dst
, uuid_t src
)
564 (void) memcpy(dst
, src
, UUID_LEN
);
568 * Sets the value of the supplied uuid variable uu, to the NULL value.
571 uuid_clear(uuid_t uu
)
573 (void) memset(uu
, 0, UUID_LEN
);
577 * This function converts the supplied UUID uu from the internal
578 * binary format into a 36-byte string (plus trailing null char)
579 * and stores this value in the character string pointed to by out.
582 uuid_unparse(uuid_t uu
, char *out
)
589 /* basic sanity checking */
594 /* XXX user should have allocated enough memory */
596 * if (strlen(out) < UUID_PRINTABLE_STRING_LENGTH) {
600 string_to_struct(&uuid
, uu
);
601 clock_seq
= uuid
.clock_seq_hi_and_reserved
;
602 clock_seq
= (clock_seq
<< 8) | uuid
.clock_seq_low
;
603 for (i
= 0; i
< 6; i
++) {
604 (void) sprintf(ðeraddr
[index
++], "%.2x", uuid
.node_addr
[i
]);
607 etheraddr
[index
] = '\0';
609 (void) snprintf(out
, 25, "%08x-%04x-%04x-%04x-",
610 uuid
.time_low
, uuid
.time_mid
, uuid
.time_hi_and_version
, clock_seq
);
611 (void) strlcat(out
, etheraddr
, UUID_PRINTABLE_STRING_LENGTH
);
615 * The uuid_is_null function compares the value of the supplied
616 * UUID variable uu to the NULL value. If the value is equal
617 * to the NULL UUID, 1 is returned, otherwise 0 is returned.
620 uuid_is_null(uuid_t uu
)
625 (void) memset(null_uu
, 0, sizeof (uuid_t
));
626 i
= memcmp(uu
, null_uu
, sizeof (uuid_t
));
628 /* uu is NULL uuid */
636 * uuid_parse converts the UUID string given by 'in' into the
637 * internal uuid_t format. The input UUID is a string of the form
638 * cefa7a9c-1dd2-11b2-8350-880020adbeef in printf(3C) format.
639 * Upon successfully parsing the input string, UUID is stored
640 * in the location pointed to by uu
643 uuid_parse(char *in
, uuid_t uu
)
651 /* do some sanity checking */
652 if ((strlen(in
) != 36) || (uu
== NULL
) || (in
[36] != '\0')) {
657 for (i
= 0; i
< 36; i
++, ptr
++) {
658 if ((i
== 8) || (i
== 13) || (i
== 18) || (i
== 23)) {
663 if (!isxdigit(*ptr
)) {
669 uuid
.time_low
= strtoul(in
, NULL
, 16);
670 uuid
.time_mid
= strtoul(in
+9, NULL
, 16);
671 uuid
.time_hi_and_version
= strtoul(in
+14, NULL
, 16);
672 clock_seq
= strtoul(in
+19, NULL
, 16);
673 uuid
.clock_seq_hi_and_reserved
= (clock_seq
& 0xFF00) >> 8;
674 uuid
.clock_seq_low
= (clock_seq
& 0xFF);
678 for (i
= 0; i
< 6; i
++) {
681 uuid
.node_addr
[i
] = strtoul(buf
, NULL
, 16);
683 struct_to_string(uu
, &uuid
);
688 * uuid_time extracts the time at which the supplied UUID uu
689 * was created. This function can only extract the creation
690 * time for UUIDs created with the uuid_generate_time function.
691 * The time at which the UUID was created, in seconds and
692 * microseconds since the epoch is stored in the location
693 * pointed to by ret_tv.
696 uuid_time(uuid_t uu
, struct timeval
*ret_tv
)
701 u_longlong_t clock_reg
;
705 string_to_struct(&uuid
, uu
);
706 tmp
= (uuid
.time_hi_and_version
& 0xF000) >> 12;
707 clk
= uuid
.clock_seq_hi_and_reserved
;
709 /* check if uu is NULL, Version = 1 of DCE and Variant = 0b10x */
710 if ((uu
== NULL
) || ((tmp
& 0x01) != 0x01) || ((clk
& 0x80) != 0x80)) {
713 high
= uuid
.time_mid
| ((uuid
.time_hi_and_version
& 0xFFF) << 16);
714 clock_reg
= uuid
.time_low
| ((u_longlong_t
)high
<< 32);
716 clock_reg
-= (((u_longlong_t
)0x01B21DD2) << 32) + 0x13814000;
717 tv
.tv_sec
= clock_reg
/ 10000000;
718 tv
.tv_usec
= (clock_reg
% 10000000) / 10;