1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/endian.h> 34 #include <sys/kernel.h> 35 #include <sys/lock.h> 36 #include <sys/mutex.h> 37 #include <sys/sbuf.h> 38 #include <sys/socket.h> 39 #include <sys/sysproto.h> 40 #include <sys/systm.h> 41 #include <sys/jail.h> 42 #include <sys/uuid.h> 43 44 #include <net/if.h> 45 #include <net/if_dl.h> 46 #include <net/if_types.h> 47 #include <net/vnet.h> 48 49 /* 50 * See also: 51 * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 52 * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm 53 * 54 * Note that the generator state is itself an UUID, but the time and clock 55 * sequence fields are written in the native byte order. 56 */ 57 58 CTASSERT(sizeof(struct uuid) == 16); 59 60 /* We use an alternative, more convenient representation in the generator. */ 61 struct uuid_private { 62 union { 63 uint64_t ll; /* internal, for uuid_last only */ 64 struct { 65 uint32_t low; 66 uint16_t mid; 67 uint16_t hi; 68 } x; 69 } time; 70 uint16_t seq; /* Big-endian. */ 71 uint16_t node[UUID_NODE_LEN>>1]; 72 }; 73 74 CTASSERT(sizeof(struct uuid_private) == 16); 75 76 struct uuid_macaddr { 77 uint16_t state; 78 #define UUID_ETHER_EMPTY 0 79 #define UUID_ETHER_RANDOM 1 80 #define UUID_ETHER_UNIQUE 2 81 uint16_t node[UUID_NODE_LEN>>1]; 82 }; 83 84 static struct uuid_private uuid_last; 85 86 #define UUID_NETHER 4 87 static struct uuid_macaddr uuid_ether[UUID_NETHER]; 88 89 static struct mtx uuid_mutex; 90 MTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF); 91 92 /* 93 * Return the first MAC address added in the array. If it's empty, then 94 * construct a sufficiently random multicast MAC address first. Any 95 * addresses added later will bump the random MAC address up tp the next 96 * index. 97 */ 98 static void 99 uuid_node(uint16_t *node) 100 { 101 int i; 102 103 if (uuid_ether[0].state == UUID_ETHER_EMPTY) { 104 for (i = 0; i < (UUID_NODE_LEN>>1); i++) 105 uuid_ether[0].node[i] = (uint16_t)arc4random(); 106 *((uint8_t*)uuid_ether[0].node) |= 0x01; 107 uuid_ether[0].state = UUID_ETHER_RANDOM; 108 } 109 for (i = 0; i < (UUID_NODE_LEN>>1); i++) 110 node[i] = uuid_ether[0].node[i]; 111 } 112 113 /* 114 * Get the current time as a 60 bit count of 100-nanosecond intervals 115 * since 00:00:00.00, October 15,1582. We apply a magic offset to convert 116 * the Unix time since 00:00:00.00, January 1, 1970 to the date of the 117 * Gregorian reform to the Christian calendar. 118 */ 119 static uint64_t 120 uuid_time(void) 121 { 122 struct bintime bt; 123 uint64_t time = 0x01B21DD213814000LL; 124 125 bintime(&bt); 126 time += (uint64_t)bt.sec * 10000000LL; 127 time += (10000000LL * (uint32_t)(bt.frac >> 32)) >> 32; 128 return (time & ((1LL << 60) - 1LL)); 129 } 130 131 struct uuid * 132 kern_uuidgen(struct uuid *store, size_t count) 133 { 134 struct uuid_private uuid; 135 uint64_t time; 136 size_t n; 137 138 mtx_lock(&uuid_mutex); 139 140 uuid_node(uuid.node); 141 time = uuid_time(); 142 143 if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] || 144 uuid_last.node[1] != uuid.node[1] || 145 uuid_last.node[2] != uuid.node[2]) 146 uuid.seq = (uint16_t)arc4random() & 0x3fff; 147 else if (uuid_last.time.ll >= time) 148 uuid.seq = (uuid_last.seq + 1) & 0x3fff; 149 else 150 uuid.seq = uuid_last.seq; 151 152 uuid_last = uuid; 153 uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL); 154 155 mtx_unlock(&uuid_mutex); 156 157 /* Set sequence and variant and deal with byte order. */ 158 uuid.seq = htobe16(uuid.seq | 0x8000); 159 160 for (n = 0; n < count; n++) { 161 /* Set time and version (=1). */ 162 uuid.time.x.low = (uint32_t)time; 163 uuid.time.x.mid = (uint16_t)(time >> 32); 164 uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12); 165 store[n] = *(struct uuid *)&uuid; 166 time++; 167 } 168 169 return (store); 170 } 171 172 #ifndef _SYS_SYSPROTO_H_ 173 struct uuidgen_args { 174 struct uuid *store; 175 int count; 176 }; 177 #endif 178 int 179 sys_uuidgen(struct thread *td, struct uuidgen_args *uap) 180 { 181 struct uuid *store; 182 size_t count; 183 int error; 184 185 /* 186 * Limit the number of UUIDs that can be created at the same time 187 * to some arbitrary number. This isn't really necessary, but I 188 * like to have some sort of upper-bound that's less than 2G :-) 189 * XXX probably needs to be tunable. 190 */ 191 if (uap->count < 1 || uap->count > 2048) 192 return (EINVAL); 193 194 count = uap->count; 195 store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK); 196 kern_uuidgen(store, count); 197 error = copyout(store, uap->store, count * sizeof(struct uuid)); 198 free(store, M_TEMP); 199 return (error); 200 } 201 202 int 203 uuid_ether_add(const uint8_t *addr) 204 { 205 int i, sum; 206 207 /* 208 * Validate input. No multicast (flag 0x1), no locally administered 209 * (flag 0x2) and no 'all-zeroes' addresses. 210 */ 211 if (addr[0] & 0x03) 212 return (EINVAL); 213 sum = 0; 214 for (i = 0; i < UUID_NODE_LEN; i++) 215 sum += addr[i]; 216 if (sum == 0) 217 return (EINVAL); 218 219 mtx_lock(&uuid_mutex); 220 221 /* Make sure the MAC isn't known already and that there's space. */ 222 i = 0; 223 while (i < UUID_NETHER && uuid_ether[i].state == UUID_ETHER_UNIQUE) { 224 if (!bcmp(addr, uuid_ether[i].node, UUID_NODE_LEN)) { 225 mtx_unlock(&uuid_mutex); 226 return (EEXIST); 227 } 228 i++; 229 } 230 if (i == UUID_NETHER) { 231 mtx_unlock(&uuid_mutex); 232 return (ENOSPC); 233 } 234 235 /* Insert MAC at index, moving the non-empty entry if possible. */ 236 if (uuid_ether[i].state == UUID_ETHER_RANDOM && i < UUID_NETHER - 1) 237 uuid_ether[i + 1] = uuid_ether[i]; 238 uuid_ether[i].state = UUID_ETHER_UNIQUE; 239 bcopy(addr, uuid_ether[i].node, UUID_NODE_LEN); 240 mtx_unlock(&uuid_mutex); 241 return (0); 242 } 243 244 int 245 uuid_ether_del(const uint8_t *addr) 246 { 247 int i; 248 249 mtx_lock(&uuid_mutex); 250 i = 0; 251 while (i < UUID_NETHER && uuid_ether[i].state == UUID_ETHER_UNIQUE && 252 bcmp(addr, uuid_ether[i].node, UUID_NODE_LEN)) 253 i++; 254 if (i == UUID_NETHER || uuid_ether[i].state != UUID_ETHER_UNIQUE) { 255 mtx_unlock(&uuid_mutex); 256 return (ENOENT); 257 } 258 259 /* Remove it by shifting higher index entries down. */ 260 while (i < UUID_NETHER - 1 && uuid_ether[i].state != UUID_ETHER_EMPTY) { 261 uuid_ether[i] = uuid_ether[i + 1]; 262 i++; 263 } 264 if (uuid_ether[i].state != UUID_ETHER_EMPTY) { 265 uuid_ether[i].state = UUID_ETHER_EMPTY; 266 bzero(uuid_ether[i].node, UUID_NODE_LEN); 267 } 268 mtx_unlock(&uuid_mutex); 269 return (0); 270 } 271 272 int 273 snprintf_uuid(char *buf, size_t sz, struct uuid *uuid) 274 { 275 struct uuid_private *id; 276 int cnt; 277 278 id = (struct uuid_private *)uuid; 279 cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x", 280 id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq), 281 be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2])); 282 return (cnt); 283 } 284 285 int 286 printf_uuid(struct uuid *uuid) 287 { 288 char buf[38]; 289 290 snprintf_uuid(buf, sizeof(buf), uuid); 291 return (printf("%s", buf)); 292 } 293 294 int 295 sbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid) 296 { 297 char buf[38]; 298 299 snprintf_uuid(buf, sizeof(buf), uuid); 300 return (sbuf_printf(sb, "%s", buf)); 301 } 302 303 /* 304 * Encode/Decode UUID into byte-stream. 305 * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 306 * 307 * 0 1 2 3 308 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 309 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 310 * | time_low | 311 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 312 * | time_mid | time_hi_and_version | 313 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 314 * |clk_seq_hi_res | clk_seq_low | node (0-1) | 315 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 316 * | node (2-5) | 317 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 318 */ 319 320 void 321 le_uuid_enc(void *buf, struct uuid const *uuid) 322 { 323 u_char *p; 324 int i; 325 326 p = buf; 327 le32enc(p, uuid->time_low); 328 le16enc(p + 4, uuid->time_mid); 329 le16enc(p + 6, uuid->time_hi_and_version); 330 p[8] = uuid->clock_seq_hi_and_reserved; 331 p[9] = uuid->clock_seq_low; 332 for (i = 0; i < _UUID_NODE_LEN; i++) 333 p[10 + i] = uuid->node[i]; 334 } 335 336 void 337 le_uuid_dec(void const *buf, struct uuid *uuid) 338 { 339 u_char const *p; 340 int i; 341 342 p = buf; 343 uuid->time_low = le32dec(p); 344 uuid->time_mid = le16dec(p + 4); 345 uuid->time_hi_and_version = le16dec(p + 6); 346 uuid->clock_seq_hi_and_reserved = p[8]; 347 uuid->clock_seq_low = p[9]; 348 for (i = 0; i < _UUID_NODE_LEN; i++) 349 uuid->node[i] = p[10 + i]; 350 } 351 352 void 353 be_uuid_enc(void *buf, struct uuid const *uuid) 354 { 355 u_char *p; 356 int i; 357 358 p = buf; 359 be32enc(p, uuid->time_low); 360 be16enc(p + 4, uuid->time_mid); 361 be16enc(p + 6, uuid->time_hi_and_version); 362 p[8] = uuid->clock_seq_hi_and_reserved; 363 p[9] = uuid->clock_seq_low; 364 for (i = 0; i < _UUID_NODE_LEN; i++) 365 p[10 + i] = uuid->node[i]; 366 } 367 368 void 369 be_uuid_dec(void const *buf, struct uuid *uuid) 370 { 371 u_char const *p; 372 int i; 373 374 p = buf; 375 uuid->time_low = be32dec(p); 376 uuid->time_mid = be16dec(p + 4); 377 uuid->time_hi_and_version = be16dec(p + 6); 378 uuid->clock_seq_hi_and_reserved = p[8]; 379 uuid->clock_seq_low = p[9]; 380 for (i = 0; i < _UUID_NODE_LEN; i++) 381 uuid->node[i] = p[10 + i]; 382 } 383 384 int 385 parse_uuid(const char *str, struct uuid *uuid) 386 { 387 u_int c[11]; 388 int n; 389 390 /* An empty string represents a nil UUID. */ 391 if (*str == '\0') { 392 bzero(uuid, sizeof(*uuid)); 393 return (0); 394 } 395 396 /* The UUID string representation has a fixed length. */ 397 if (strlen(str) != 36) 398 return (EINVAL); 399 400 /* 401 * We only work with "new" UUIDs. New UUIDs have the form: 402 * 01234567-89ab-cdef-0123-456789abcdef 403 * The so called "old" UUIDs, which we don't support, have the form: 404 * 0123456789ab.cd.ef.01.23.45.67.89.ab 405 */ 406 if (str[8] != '-') 407 return (EINVAL); 408 409 n = sscanf(str, "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", c + 0, c + 1, 410 c + 2, c + 3, c + 4, c + 5, c + 6, c + 7, c + 8, c + 9, c + 10); 411 /* Make sure we have all conversions. */ 412 if (n != 11) 413 return (EINVAL); 414 415 /* Successful scan. Build the UUID. */ 416 uuid->time_low = c[0]; 417 uuid->time_mid = c[1]; 418 uuid->time_hi_and_version = c[2]; 419 uuid->clock_seq_hi_and_reserved = c[3]; 420 uuid->clock_seq_low = c[4]; 421 for (n = 0; n < 6; n++) 422 uuid->node[n] = c[n + 5]; 423 424 /* Check semantics... */ 425 return (((c[3] & 0x80) != 0x00 && /* variant 0? */ 426 (c[3] & 0xc0) != 0x80 && /* variant 1? */ 427 (c[3] & 0xe0) != 0xc0) ? EINVAL : 0); /* variant 2? */ 428 } 429 430 int 431 uuidcmp(const struct uuid *uuid1, const struct uuid *uuid2) 432 { 433 434 return (memcmp(uuid1, uuid2, sizeof(struct uuid))); 435 } 436