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