1/* 2 * Copyright (c) 2004-2011 Apple Inc. All rights reserved. 3 * 4 * %Begin-Header% 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, and the entire permission notice in its entirety, 10 * including the disclaimer of warranties. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote 15 * products derived from this software without specific prior 16 * written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 21 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 28 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 29 * DAMAGE. 30 * %End-Header% 31 */ 32 33#include <uuid/uuid.h> 34 35#include <stdint.h> 36#include <string.h> 37 38#include <sys/random.h> 39#include <sys/socket.h> 40#include <sys/systm.h> 41#include <sys/time.h> 42 43extern int uuid_get_ethernet(u_int8_t *); 44 45UUID_DEFINE(UUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 46 47static void 48read_node(uint8_t *node) 49{ 50#if NETWORKING 51 if (uuid_get_ethernet(node) == 0) 52 return; 53#endif /* NETWORKING */ 54 55 read_random(node, 6); 56 node[0] |= 0x01; 57} 58 59static uint64_t 60read_time(void) 61{ 62 struct timespec tv; 63 64 nanotime(&tv); 65 66 return (tv.tv_sec * 10000000ULL) + (tv.tv_nsec / 100ULL) + 0x01B21DD213814000ULL; 67} 68 69void 70uuid_clear(uuid_t uu) 71{ 72 memset(uu, 0, sizeof(uuid_t)); 73} 74 75int 76uuid_compare(const uuid_t uu1, const uuid_t uu2) 77{ 78 return memcmp(uu1, uu2, sizeof(uuid_t)); 79} 80 81void 82uuid_copy(uuid_t dst, const uuid_t src) 83{ 84 memcpy(dst, src, sizeof(uuid_t)); 85} 86 87void 88uuid_generate_random(uuid_t out) 89{ 90 read_random(out, sizeof(uuid_t)); 91 92 out[6] = (out[6] & 0x0F) | 0x40; 93 out[8] = (out[8] & 0x3F) | 0x80; 94} 95 96void 97uuid_generate_time(uuid_t out) 98{ 99 uint64_t time; 100 101 read_node(&out[10]); 102 read_random(&out[8], 2); 103 104 time = read_time(); 105 out[0] = (uint8_t)(time >> 24); 106 out[1] = (uint8_t)(time >> 16); 107 out[2] = (uint8_t)(time >> 8); 108 out[3] = (uint8_t)time; 109 out[4] = (uint8_t)(time >> 40); 110 out[5] = (uint8_t)(time >> 32); 111 out[6] = (uint8_t)(time >> 56); 112 out[7] = (uint8_t)(time >> 48); 113 114 out[6] = (out[6] & 0x0F) | 0x10; 115 out[8] = (out[8] & 0x3F) | 0x80; 116} 117 118void 119uuid_generate(uuid_t out) 120{ 121 uuid_generate_random(out); 122} 123 124int 125uuid_is_null(const uuid_t uu) 126{ 127 return !memcmp(uu, UUID_NULL, sizeof(uuid_t)); 128} 129 130int 131uuid_parse(const uuid_string_t in, uuid_t uu) 132{ 133 int n = 0; 134 135 sscanf(in, 136 "%2hhx%2hhx%2hhx%2hhx-" 137 "%2hhx%2hhx-" 138 "%2hhx%2hhx-" 139 "%2hhx%2hhx-" 140 "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%n", 141 &uu[0], &uu[1], &uu[2], &uu[3], 142 &uu[4], &uu[5], 143 &uu[6], &uu[7], 144 &uu[8], &uu[9], 145 &uu[10], &uu[11], &uu[12], &uu[13], &uu[14], &uu[15], &n); 146 147 return (n != 36 || in[n] != '\0' ? -1 : 0); 148} 149 150void 151uuid_unparse_lower(const uuid_t uu, uuid_string_t out) 152{ 153 snprintf(out, 154 sizeof(uuid_string_t), 155 "%02x%02x%02x%02x-" 156 "%02x%02x-" 157 "%02x%02x-" 158 "%02x%02x-" 159 "%02x%02x%02x%02x%02x%02x", 160 uu[0], uu[1], uu[2], uu[3], 161 uu[4], uu[5], 162 uu[6], uu[7], 163 uu[8], uu[9], 164 uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); 165} 166 167void 168uuid_unparse_upper(const uuid_t uu, uuid_string_t out) 169{ 170 snprintf(out, 171 sizeof(uuid_string_t), 172 "%02X%02X%02X%02X-" 173 "%02X%02X-" 174 "%02X%02X-" 175 "%02X%02X-" 176 "%02X%02X%02X%02X%02X%02X", 177 uu[0], uu[1], uu[2], uu[3], 178 uu[4], uu[5], 179 uu[6], uu[7], 180 uu[8], uu[9], 181 uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); 182} 183 184void 185uuid_unparse(const uuid_t uu, uuid_string_t out) 186{ 187 uuid_unparse_upper(uu, out); 188} 189