1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 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. 26 */ 27 28 /* 29 * The copyright in this file is taken from the original Leach & Salz 30 * UUID specification, from which this implementation is derived. 31 */ 32 33 /* 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. 49 */ 50 51 /* 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. 56 */ 57 58 #include <ctype.h> 59 #include <sys/param.h> 60 #include <sys/stat.h> 61 #include <errno.h> 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <strings.h> 65 #include <fcntl.h> 66 #include <unistd.h> 67 #include <synch.h> 68 #include <sys/mman.h> 69 #include "uuid_misc.h" 70 71 shared_buffer_t *data; 72 73 static uuid_node_t node_id_cache; 74 static int node_init; 75 static int file_type; 76 static int fd; 77 78 /* 79 * The urandmtx mutex prevents multiple opens of /dev/urandom and protects the 80 * cache. 81 */ 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; 87 88 /* 89 * misc routines 90 */ 91 uint16_t get_random(void); 92 void get_current_time(uuid_time_t *); 93 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 *); 97 98 /* 99 * local functions 100 */ 101 static int map_state(); 102 static void format_uuid(struct uuid *, uint16_t, uuid_time_t, 103 uuid_node_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 *); 108 109 /* 110 * Generates a uuid based on version 1 format. 111 * Returns 0 on success and -1 on failure. 112 */ 113 static int 114 uuid_create(struct uuid *uuid) 115 { 116 uuid_time_t timestamp; 117 uuid_node_t system_node; 118 int ret, non_unique = 0; 119 120 /* 121 * Get the system MAC address and/or cache it 122 */ 123 if (node_init) { 124 bcopy(&node_id_cache, &system_node, sizeof (uuid_node_t)); 125 } else { 126 gen_ethernet_address(&system_node); 127 bcopy(&system_node, &node_id_cache, sizeof (uuid_node_t)); 128 node_init = 1; 129 } 130 131 /* 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. 135 */ 136 if (map_state() == -1) 137 return (-1); 138 139 /* 140 * Acquire the lock 141 */ 142 for (;;) { 143 if ((ret = mutex_lock(&data->lock)) == 0) 144 break; 145 else 146 switch (ret) { 147 case EOWNERDEAD: 148 revalidate_data(&system_node); 149 (void) mutex_consistent(&data->lock); 150 (void) mutex_unlock(&data->lock); 151 break; 152 case ENOTRECOVERABLE: 153 return (ret); 154 } 155 } 156 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(); 160 non_unique++; 161 } 162 163 if (memcmp(&system_node, &data->state.node, sizeof (uuid_node_t)) != 0) 164 data->state.clock++; 165 166 get_current_time(×tamp); 167 168 /* 169 * If timestamp is not set or is not in the past, bump 170 * data->state.clock 171 */ 172 if ((data->state.ts == 0) || (data->state.ts >= timestamp)) { 173 data->state.clock++; 174 data->state.ts = timestamp; 175 } 176 177 if (non_unique) 178 system_node.nodeID[0] |= 0x80; 179 180 /* Stuff fields into the UUID struct */ 181 format_uuid(uuid, data->state.clock, timestamp, system_node); 182 183 (void) mutex_unlock(&data->lock); 184 185 return (0); 186 } 187 188 /* 189 * Fills system_node with Ethernet address if available, 190 * else fills random numbers 191 */ 192 static void 193 gen_ethernet_address(uuid_node_t *system_node) 194 { 195 uchar_t node[6]; 196 197 if (get_ethernet_address(system_node) != 0) { 198 fill_random_bytes(node, 6); 199 (void) memcpy(system_node->nodeID, node, 6); 200 /* 201 * use 8:0:20 with the multicast bit set 202 * to avoid namespace collisions. 203 */ 204 system_node->nodeID[0] = 0x88; 205 system_node->nodeID[1] = 0x00; 206 system_node->nodeID[2] = 0x20; 207 } 208 } 209 210 /* 211 * Formats a UUID, given the clock_seq timestamp, and node address. 212 * Fills in passed-in pointer with the resulting uuid. 213 */ 214 static void 215 format_uuid(struct uuid *uuid, uint16_t clock_seq, 216 uuid_time_t timestamp, uuid_node_t node) 217 { 218 219 /* 220 * First set up the first 60 bits from the timestamp 221 */ 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); 225 226 /* 227 * This is version 1, so say so in the UUID version field (4 bits) 228 */ 229 uuid->time_hi_and_version |= (1 << 12); 230 231 /* 232 * Now do the clock sequence 233 */ 234 uuid->clock_seq_low = clock_seq & 0xFF; 235 236 /* 237 * We must save the most-significant 2 bits for the reserved field 238 */ 239 uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8; 240 241 /* 242 * The variant for this format is the 2 high bits set to 10, 243 * so here it is 244 */ 245 uuid->clock_seq_hi_and_reserved |= 0x80; 246 247 /* 248 * write result to passed-in pointer 249 */ 250 (void) memcpy(&uuid->node_addr, &node, sizeof (uuid->node_addr)); 251 } 252 253 /* 254 * Opens/creates the state file, falling back to a tmp 255 */ 256 static int 257 map_state() 258 { 259 FILE *tmp; 260 261 /* If file's mapped, return */ 262 if (file_type != 0) 263 return (1); 264 265 if ((fd = open(STATE_LOCATION, O_RDWR)) < 0) { 266 file_type = TEMP_FILE; 267 268 if ((tmp = tmpfile()) == NULL) 269 return (-1); 270 else 271 fd = fileno(tmp); 272 } else { 273 file_type = STATE_FILE; 274 } 275 276 (void) ftruncate(fd, (off_t)sizeof (shared_buffer_t)); 277 278 /* LINTED - alignment */ 279 data = (shared_buffer_t *)mmap(NULL, sizeof (shared_buffer_t), 280 PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 281 282 if (data == MAP_FAILED) 283 return (-1); 284 285 (void) mutex_init(&data->lock, USYNC_PROCESS|LOCK_ROBUST, 0); 286 287 (void) close(fd); 288 289 return (1); 290 } 291 292 static void 293 revalidate_data(uuid_node_t *node) 294 { 295 int i; 296 297 data->state.ts = 0; 298 299 for (i = 0; i < sizeof (data->state.node.nodeID); i++) 300 data->state.node.nodeID[i] = 0; 301 302 data->state.clock = 0; 303 304 gen_ethernet_address(node); 305 bcopy(node, &node_id_cache, sizeof (uuid_node_t)); 306 node_init = 1; 307 } 308 309 /* 310 * Prints a nicely-formatted uuid to stdout. 311 */ 312 void 313 uuid_print(struct uuid u) 314 { 315 int i; 316 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, 319 u.clock_seq_low); 320 for (i = 0; i < 6; i++) 321 (void) printf("%2.2x", u.node_addr[i]); 322 (void) printf("\n"); 323 } 324 325 /* 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. 332 */ 333 static void 334 load_cache() 335 { 336 int i, retries = 0; 337 int nbytes = RCACHE_SIZE; 338 char *buf = rcache; 339 340 while (nbytes > 0) { 341 i = read(fd_urand, buf, nbytes); 342 if ((i < 0) && (errno == EINTR)) { 343 continue; 344 } 345 if (i <= 0) { 346 if (retries++ == MAX_RETRY) 347 break; 348 continue; 349 } 350 nbytes -= i; 351 buf += i; 352 retries = 0; 353 } 354 if (nbytes == 0) 355 rcachep = rcache; 356 else 357 rcachep = NULL; 358 } 359 360 /* 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) 364 */ 365 static void 366 fill_random_bytes(uchar_t *buf, int nbytes) 367 { 368 int i; 369 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) 375 load_cache(); 376 } 377 (void) mutex_unlock(&urandmtx); 378 } 379 if (fd_urand >= 0 && rcachep != NULL) { 380 int cnt; 381 382 (void) mutex_lock(&urandmtx); 383 if (rcachep != NULL && 384 (rcachep + nbytes) >= (rcache + RCACHE_SIZE)) 385 load_cache(); 386 387 if (rcachep != NULL) { 388 for (cnt = 0; cnt < nbytes; cnt++) 389 *buf++ = *rcachep++; 390 (void) mutex_unlock(&urandmtx); 391 return; 392 } 393 (void) mutex_unlock(&urandmtx); 394 } 395 for (i = 0; i < nbytes; i++) { 396 *buf++ = get_random() & 0xFF; 397 } 398 } 399 400 /* 401 * Unpacks the structure members in "struct uuid" to a char string "uuid_t". 402 */ 403 void 404 struct_to_string(uuid_t ptr, struct uuid *uu) 405 { 406 uint_t tmp; 407 uchar_t *out = ptr; 408 409 tmp = uu->time_low; 410 out[3] = (uchar_t)tmp; 411 tmp >>= 8; 412 out[2] = (uchar_t)tmp; 413 tmp >>= 8; 414 out[1] = (uchar_t)tmp; 415 tmp >>= 8; 416 out[0] = (uchar_t)tmp; 417 418 tmp = uu->time_mid; 419 out[5] = (uchar_t)tmp; 420 tmp >>= 8; 421 out[4] = (uchar_t)tmp; 422 423 tmp = uu->time_hi_and_version; 424 out[7] = (uchar_t)tmp; 425 tmp >>= 8; 426 out[6] = (uchar_t)tmp; 427 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; 432 433 (void) memcpy(out+10, uu->node_addr, 6); 434 435 } 436 437 /* 438 * Packs the values in the "uuid_t" string into "struct uuid". 439 */ 440 void 441 string_to_struct(struct uuid *uuid, uuid_t in) 442 { 443 uchar_t *ptr; 444 uint_t tmp; 445 446 ptr = in; 447 448 tmp = *ptr++; 449 tmp = (tmp << 8) | *ptr++; 450 tmp = (tmp << 8) | *ptr++; 451 tmp = (tmp << 8) | *ptr++; 452 uuid->time_low = tmp; 453 454 tmp = *ptr++; 455 tmp = (tmp << 8) | *ptr++; 456 uuid->time_mid = tmp; 457 458 tmp = *ptr++; 459 tmp = (tmp << 8) | *ptr++; 460 uuid->time_hi_and_version = tmp; 461 462 tmp = *ptr++; 463 uuid->clock_seq_hi_and_reserved = tmp; 464 465 tmp = *ptr++; 466 uuid->clock_seq_low = tmp; 467 468 (void) memcpy(uuid->node_addr, ptr, 6); 469 470 } 471 472 /* 473 * Generates UUID based on DCE Version 4 474 */ 475 void 476 uuid_generate_random(uuid_t uu) 477 { 478 struct uuid uuid; 479 480 if (uu == NULL) 481 return; 482 483 (void) memset(uu, 0, sizeof (uuid_t)); 484 (void) memset(&uuid, 0, sizeof (struct uuid)); 485 486 fill_random_bytes(uu, sizeof (uuid_t)); 487 string_to_struct(&uuid, uu); 488 /* 489 * This is version 4, so say so in the UUID version field (4 bits) 490 */ 491 uuid.time_hi_and_version |= (1 << 14); 492 /* 493 * we don't want the bit 1 to be set also which is for version 1 494 */ 495 uuid.time_hi_and_version &= VER1_MASK; 496 497 /* 498 * The variant for this format is the 2 high bits set to 10, 499 * so here it is 500 */ 501 uuid.clock_seq_hi_and_reserved |= 0x80; 502 503 /* 504 * Set MSB of Ethernet address to 1 to indicate that it was generated 505 * randomly 506 */ 507 uuid.node_addr[0] |= 0x80; 508 struct_to_string(uu, &uuid); 509 } 510 511 /* 512 * Generates UUID based on DCE Version 1. 513 */ 514 void 515 uuid_generate_time(uuid_t uu) 516 { 517 struct uuid uuid; 518 519 if (uu == NULL) 520 return; 521 522 if (uuid_create(&uuid) < 0) { 523 uuid_generate_random(uu); 524 return; 525 } 526 527 struct_to_string(uu, &uuid); 528 } 529 530 /* 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. 535 */ 536 void 537 uuid_generate(uuid_t uu) 538 { 539 if (uu == NULL) { 540 return; 541 } 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) 547 load_cache(); 548 } 549 (void) mutex_unlock(&urandmtx); 550 } 551 if (fd_urand >= 0) { 552 uuid_generate_random(uu); 553 } else { 554 (void) uuid_generate_time(uu); 555 } 556 } 557 558 /* 559 * Copies the UUID variable src to dst. 560 */ 561 void 562 uuid_copy(uuid_t dst, uuid_t src) 563 { 564 (void) memcpy(dst, src, UUID_LEN); 565 } 566 567 /* 568 * Sets the value of the supplied uuid variable uu, to the NULL value. 569 */ 570 void 571 uuid_clear(uuid_t uu) 572 { 573 (void) memset(uu, 0, UUID_LEN); 574 } 575 576 /* 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. 580 */ 581 void 582 uuid_unparse(uuid_t uu, char *out) 583 { 584 struct uuid uuid; 585 uint16_t clock_seq; 586 char etheraddr[13]; 587 int index = 0, i; 588 589 /* basic sanity checking */ 590 if (uu == NULL) { 591 return; 592 } 593 594 /* XXX user should have allocated enough memory */ 595 /* 596 * if (strlen(out) < UUID_PRINTABLE_STRING_LENGTH) { 597 * return; 598 * } 599 */ 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]); 605 index++; 606 } 607 etheraddr[index] = '\0'; 608 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); 612 } 613 614 /* 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. 618 */ 619 int 620 uuid_is_null(uuid_t uu) 621 { 622 int i; 623 uuid_t null_uu; 624 625 (void) memset(null_uu, 0, sizeof (uuid_t)); 626 i = memcmp(uu, null_uu, sizeof (uuid_t)); 627 if (i == 0) { 628 /* uu is NULL uuid */ 629 return (1); 630 } else { 631 return (0); 632 } 633 } 634 635 /* 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 641 */ 642 int 643 uuid_parse(char *in, uuid_t uu) 644 { 645 646 char *ptr, buf[3]; 647 int i; 648 struct uuid uuid; 649 uint16_t clock_seq; 650 651 /* do some sanity checking */ 652 if ((strlen(in) != 36) || (uu == NULL) || (in[36] != '\0')) { 653 return (-1); 654 } 655 656 ptr = in; 657 for (i = 0; i < 36; i++, ptr++) { 658 if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { 659 if (*ptr != '-') { 660 return (-1); 661 } 662 } else { 663 if (!isxdigit(*ptr)) { 664 return (-1); 665 } 666 } 667 } 668 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); 675 676 ptr = in+24; 677 buf[2] = '\0'; 678 for (i = 0; i < 6; i++) { 679 buf[0] = *ptr++; 680 buf[1] = *ptr++; 681 uuid.node_addr[i] = strtoul(buf, NULL, 16); 682 } 683 struct_to_string(uu, &uuid); 684 return (0); 685 } 686 687 /* 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. 694 */ 695 time_t 696 uuid_time(uuid_t uu, struct timeval *ret_tv) 697 { 698 struct uuid uuid; 699 uint_t high; 700 struct timeval tv; 701 u_longlong_t clock_reg; 702 uint_t tmp; 703 uint8_t clk; 704 705 string_to_struct(&uuid, uu); 706 tmp = (uuid.time_hi_and_version & 0xF000) >> 12; 707 clk = uuid.clock_seq_hi_and_reserved; 708 709 /* check if uu is NULL, Version = 1 of DCE and Variant = 0b10x */ 710 if ((uu == NULL) || ((tmp & 0x01) != 0x01) || ((clk & 0x80) != 0x80)) { 711 return (-1); 712 } 713 high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); 714 clock_reg = uuid.time_low | ((u_longlong_t)high << 32); 715 716 clock_reg -= (((u_longlong_t)0x01B21DD2) << 32) + 0x13814000; 717 tv.tv_sec = clock_reg / 10000000; 718 tv.tv_usec = (clock_reg % 10000000) / 10; 719 720 if (ret_tv) { 721 *ret_tv = tv; 722 } 723 724 return (tv.tv_sec); 725 } 726