]>
Commit | Line | Data |
---|---|---|
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(node, 6); | |
55 | node[0] |= 0x01; | |
56 | } | |
57 | ||
58 | static uint64_t | |
59 | read_time(void) | |
60 | { | |
61 | struct timespec tv; | |
62 | ||
63 | nanotime(&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(uu, 0, sizeof(uuid_t)); | |
72 | } | |
73 | ||
74 | int | |
75 | uuid_compare(const uuid_t uu1, const uuid_t uu2) | |
76 | { | |
77 | return memcmp(uu1, uu2, sizeof(uuid_t)); | |
78 | } | |
79 | ||
80 | void | |
81 | uuid_copy(uuid_t dst, const uuid_t src) | |
82 | { | |
83 | memcpy(dst, src, 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(out, sizeof(uuid_t)); | |
97 | uuid_random_setflags(out); | |
98 | } | |
99 | ||
100 | void | |
101 | uuid_generate_early_random(uuid_t out) | |
102 | { | |
103 | read_frandom(out, 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(&out[10]); | |
113 | read_random(&out[8], 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(uu, UUID_NULL, 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 | 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 | 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 | } |