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 | |
43 | extern int uuid_get_ethernet(u_int8_t *); |
44 | |
45 | static void |
46 | read_node(uint8_t *node) |
47 | { |
48 | #if NETWORKING |
49 | if (uuid_get_ethernet(node) == 0) { |
50 | return; |
51 | } |
52 | #endif /* NETWORKING */ |
53 | |
54 | read_random(buffer: node, numBytes: 6); |
55 | node[0] |= 0x01; |
56 | } |
57 | |
58 | static uint64_t |
59 | read_time(void) |
60 | { |
61 | struct timespec tv; |
62 | |
63 | nanotime(ts: &tv); |
64 | |
65 | return (tv.tv_sec * 10000000ULL) + (tv.tv_nsec / 100ULL) + 0x01B21DD213814000ULL; |
66 | } |
67 | |
68 | void |
69 | uuid_clear(uuid_t uu) |
70 | { |
71 | memset(s: uu, c: 0, n: sizeof(uuid_t)); |
72 | } |
73 | |
74 | int |
75 | uuid_compare(const uuid_t uu1, const uuid_t uu2) |
76 | { |
77 | return memcmp(s1: uu1, s2: uu2, n: sizeof(uuid_t)); |
78 | } |
79 | |
80 | void |
81 | uuid_copy(uuid_t dst, const uuid_t src) |
82 | { |
83 | memcpy(dst, src, n: sizeof(uuid_t)); |
84 | } |
85 | |
86 | static void |
87 | uuid_random_setflags(uuid_t out) |
88 | { |
89 | out[6] = (out[6] & 0x0F) | 0x40; |
90 | out[8] = (out[8] & 0x3F) | 0x80; |
91 | } |
92 | |
93 | void |
94 | uuid_generate_random(uuid_t out) |
95 | { |
96 | read_random(buffer: out, numBytes: sizeof(uuid_t)); |
97 | uuid_random_setflags(out); |
98 | } |
99 | |
100 | void |
101 | uuid_generate_early_random(uuid_t out) |
102 | { |
103 | read_frandom(buffer: out, numBytes: sizeof(uuid_t)); |
104 | uuid_random_setflags(out); |
105 | } |
106 | |
107 | void |
108 | uuid_generate_time(uuid_t out) |
109 | { |
110 | uint64_t time; |
111 | |
112 | read_node(node: &out[10]); |
113 | read_random(buffer: &out[8], numBytes: 2); |
114 | |
115 | time = read_time(); |
116 | out[0] = (uint8_t)(time >> 24); |
117 | out[1] = (uint8_t)(time >> 16); |
118 | out[2] = (uint8_t)(time >> 8); |
119 | out[3] = (uint8_t)time; |
120 | out[4] = (uint8_t)(time >> 40); |
121 | out[5] = (uint8_t)(time >> 32); |
122 | out[6] = (uint8_t)(time >> 56); |
123 | out[7] = (uint8_t)(time >> 48); |
124 | |
125 | out[6] = (out[6] & 0x0F) | 0x10; |
126 | out[8] = (out[8] & 0x3F) | 0x80; |
127 | } |
128 | |
129 | void |
130 | uuid_generate(uuid_t out) |
131 | { |
132 | uuid_generate_random(out); |
133 | } |
134 | |
135 | int |
136 | uuid_is_null(const uuid_t uu) |
137 | { |
138 | return !memcmp(s1: uu, s2: UUID_NULL, n: sizeof(uuid_t)); |
139 | } |
140 | |
141 | int |
142 | uuid_parse(const uuid_string_t in, uuid_t uu) |
143 | { |
144 | int n = 0; |
145 | |
146 | sscanf(in, |
147 | "%2hhx%2hhx%2hhx%2hhx-" |
148 | "%2hhx%2hhx-" |
149 | "%2hhx%2hhx-" |
150 | "%2hhx%2hhx-" |
151 | "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%n" , |
152 | &uu[0], &uu[1], &uu[2], &uu[3], |
153 | &uu[4], &uu[5], |
154 | &uu[6], &uu[7], |
155 | &uu[8], &uu[9], |
156 | &uu[10], &uu[11], &uu[12], &uu[13], &uu[14], &uu[15], &n); |
157 | |
158 | return n != 36 || in[n] != '\0' ? -1 : 0; |
159 | } |
160 | |
161 | void |
162 | uuid_unparse_lower(const uuid_t uu, uuid_string_t out) |
163 | { |
164 | snprintf(out, |
165 | count: sizeof(uuid_string_t), |
166 | "%02x%02x%02x%02x-" |
167 | "%02x%02x-" |
168 | "%02x%02x-" |
169 | "%02x%02x-" |
170 | "%02x%02x%02x%02x%02x%02x" , |
171 | uu[0], uu[1], uu[2], uu[3], |
172 | uu[4], uu[5], |
173 | uu[6], uu[7], |
174 | uu[8], uu[9], |
175 | uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); |
176 | } |
177 | |
178 | void |
179 | uuid_unparse_upper(const uuid_t uu, uuid_string_t out) |
180 | { |
181 | snprintf(out, |
182 | count: sizeof(uuid_string_t), |
183 | "%02X%02X%02X%02X-" |
184 | "%02X%02X-" |
185 | "%02X%02X-" |
186 | "%02X%02X-" |
187 | "%02X%02X%02X%02X%02X%02X" , |
188 | uu[0], uu[1], uu[2], uu[3], |
189 | uu[4], uu[5], |
190 | uu[6], uu[7], |
191 | uu[8], uu[9], |
192 | uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); |
193 | } |
194 | |
195 | void |
196 | uuid_unparse(const uuid_t uu, uuid_string_t out) |
197 | { |
198 | uuid_unparse_upper(uu, out); |
199 | } |
200 | |