1139804Simp/*- 297372Smarcel * Copyright (c) 2002 Marcel Moolenaar 397372Smarcel * All rights reserved. 497372Smarcel * 597372Smarcel * Redistribution and use in source and binary forms, with or without 697372Smarcel * modification, are permitted provided that the following conditions 797372Smarcel * are met: 897372Smarcel * 997372Smarcel * 1. Redistributions of source code must retain the above copyright 1097372Smarcel * notice, this list of conditions and the following disclaimer. 1197372Smarcel * 2. Redistributions in binary form must reproduce the above copyright 1297372Smarcel * notice, this list of conditions and the following disclaimer in the 1397372Smarcel * documentation and/or other materials provided with the distribution. 1497372Smarcel * 1597372Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1697372Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1797372Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1897372Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1997372Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2097372Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2197372Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2297372Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2397372Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2497372Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2597372Smarcel */ 2697372Smarcel 27116182Sobrien#include <sys/cdefs.h> 28116182Sobrien__FBSDID("$FreeBSD$"); 29116182Sobrien 3097372Smarcel#include <sys/param.h> 3197372Smarcel#include <sys/endian.h> 3297372Smarcel#include <sys/kernel.h> 3397372Smarcel#include <sys/lock.h> 3497372Smarcel#include <sys/mutex.h> 3597372Smarcel#include <sys/sbuf.h> 3697372Smarcel#include <sys/socket.h> 3797372Smarcel#include <sys/sysproto.h> 38102263Sbde#include <sys/systm.h> 39196038Sjulian#include <sys/jail.h> 4097372Smarcel#include <sys/uuid.h> 4197372Smarcel 4297372Smarcel#include <net/if.h> 4397372Smarcel#include <net/if_dl.h> 4497372Smarcel#include <net/if_types.h> 45185571Sbz#include <net/vnet.h> 4697372Smarcel 4797372Smarcel/* 4897372Smarcel * See also: 4997372Smarcel * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 5097372Smarcel * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm 5197372Smarcel * 5297372Smarcel * Note that the generator state is itself an UUID, but the time and clock 5397372Smarcel * sequence fields are written in the native byte order. 5497372Smarcel */ 5597372Smarcel 5697372SmarcelCTASSERT(sizeof(struct uuid) == 16); 5797372Smarcel 5897372Smarcel/* We use an alternative, more convenient representation in the generator. */ 5997372Smarcelstruct uuid_private { 6097372Smarcel union { 6197372Smarcel uint64_t ll; /* internal. */ 6297372Smarcel struct { 6397372Smarcel uint32_t low; 6497372Smarcel uint16_t mid; 6597372Smarcel uint16_t hi; 6697372Smarcel } x; 6797372Smarcel } time; 6897372Smarcel uint16_t seq; /* Big-endian. */ 6997372Smarcel uint16_t node[UUID_NODE_LEN>>1]; 7097372Smarcel}; 7197372Smarcel 7297372SmarcelCTASSERT(sizeof(struct uuid_private) == 16); 7397372Smarcel 74253590Smarcelstruct uuid_macaddr { 75253590Smarcel uint16_t state; 76253590Smarcel#define UUID_ETHER_EMPTY 0 77253590Smarcel#define UUID_ETHER_RANDOM 1 78253590Smarcel#define UUID_ETHER_UNIQUE 2 79253590Smarcel uint16_t node[UUID_NODE_LEN>>1]; 80253590Smarcel}; 81253590Smarcel 8297372Smarcelstatic struct uuid_private uuid_last; 8397372Smarcel 84253590Smarcel#define UUID_NETHER 4 85253590Smarcelstatic struct uuid_macaddr uuid_ether[UUID_NETHER]; 86253590Smarcel 8797372Smarcelstatic struct mtx uuid_mutex; 8897372SmarcelMTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF); 8997372Smarcel 9097372Smarcel/* 91253590Smarcel * Return the first MAC address added in the array. If it's empty, then 92253590Smarcel * construct a sufficiently random multicast MAC address first. Any 93253590Smarcel * addresses added later will bump the random MAC address up tp the next 94253590Smarcel * index. 9597372Smarcel */ 9697372Smarcelstatic void 9797372Smarceluuid_node(uint16_t *node) 9897372Smarcel{ 9997372Smarcel int i; 10097372Smarcel 101253590Smarcel if (uuid_ether[0].state == UUID_ETHER_EMPTY) { 102253590Smarcel for (i = 0; i < (UUID_NODE_LEN>>1); i++) 103253590Smarcel uuid_ether[0].node[i] = (uint16_t)arc4random(); 104253590Smarcel *((uint8_t*)uuid_ether[0].node) |= 0x01; 105253590Smarcel uuid_ether[0].state = UUID_ETHER_RANDOM; 10697372Smarcel } 10797372Smarcel for (i = 0; i < (UUID_NODE_LEN>>1); i++) 108253590Smarcel node[i] = uuid_ether[0].node[i]; 10997372Smarcel} 11097372Smarcel 11197372Smarcel/* 11297372Smarcel * Get the current time as a 60 bit count of 100-nanosecond intervals 11397372Smarcel * since 00:00:00.00, October 15,1582. We apply a magic offset to convert 114168975Spjd * the Unix time since 00:00:00.00, January 1, 1970 to the date of the 11597372Smarcel * Gregorian reform to the Christian calendar. 11697372Smarcel */ 11797372Smarcelstatic uint64_t 11897372Smarceluuid_time(void) 11997372Smarcel{ 12097372Smarcel struct bintime bt; 12197372Smarcel uint64_t time = 0x01B21DD213814000LL; 12297372Smarcel 12397372Smarcel bintime(&bt); 12497372Smarcel time += (uint64_t)bt.sec * 10000000LL; 12597372Smarcel time += (10000000LL * (uint32_t)(bt.frac >> 32)) >> 32; 12697372Smarcel return (time & ((1LL << 60) - 1LL)); 12797372Smarcel} 12897372Smarcel 129150303Smarcelstruct uuid * 130150303Smarcelkern_uuidgen(struct uuid *store, size_t count) 13197372Smarcel{ 13297372Smarcel struct uuid_private uuid; 13397372Smarcel uint64_t time; 134150303Smarcel size_t n; 13597372Smarcel 13697372Smarcel mtx_lock(&uuid_mutex); 13797372Smarcel 13897372Smarcel uuid_node(uuid.node); 13997372Smarcel time = uuid_time(); 14097372Smarcel 14197372Smarcel if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] || 14297372Smarcel uuid_last.node[1] != uuid.node[1] || 14397372Smarcel uuid_last.node[2] != uuid.node[2]) 14497372Smarcel uuid.seq = (uint16_t)arc4random() & 0x3fff; 14597372Smarcel else if (uuid_last.time.ll >= time) 14697372Smarcel uuid.seq = (uuid_last.seq + 1) & 0x3fff; 14797372Smarcel else 14897372Smarcel uuid.seq = uuid_last.seq; 14997372Smarcel 15097372Smarcel uuid_last = uuid; 151150303Smarcel uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL); 15297372Smarcel 15397372Smarcel mtx_unlock(&uuid_mutex); 15497372Smarcel 15597372Smarcel /* Set sequence and variant and deal with byte order. */ 15697372Smarcel uuid.seq = htobe16(uuid.seq | 0x8000); 15797372Smarcel 158150303Smarcel for (n = 0; n < count; n++) { 159150303Smarcel /* Set time and version (=1). */ 16097372Smarcel uuid.time.x.low = (uint32_t)time; 16197372Smarcel uuid.time.x.mid = (uint16_t)(time >> 32); 16297372Smarcel uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12); 163150303Smarcel store[n] = *(struct uuid *)&uuid; 16497372Smarcel time++; 165150303Smarcel } 16697372Smarcel 167150303Smarcel return (store); 168150303Smarcel} 169150303Smarcel 170150303Smarcel#ifndef _SYS_SYSPROTO_H_ 171150303Smarcelstruct uuidgen_args { 172150303Smarcel struct uuid *store; 173150303Smarcel int count; 174150303Smarcel}; 175150303Smarcel#endif 176150303Smarcelint 177225617Skmacysys_uuidgen(struct thread *td, struct uuidgen_args *uap) 178150303Smarcel{ 179150303Smarcel struct uuid *store; 180150303Smarcel size_t count; 181150303Smarcel int error; 182150303Smarcel 183150303Smarcel /* 184150303Smarcel * Limit the number of UUIDs that can be created at the same time 185150303Smarcel * to some arbitrary number. This isn't really necessary, but I 186150303Smarcel * like to have some sort of upper-bound that's less than 2G :-) 187150303Smarcel * XXX probably needs to be tunable. 188150303Smarcel */ 189150303Smarcel if (uap->count < 1 || uap->count > 2048) 190150303Smarcel return (EINVAL); 191150303Smarcel 192150303Smarcel count = uap->count; 193150303Smarcel store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK); 194150303Smarcel kern_uuidgen(store, count); 195150303Smarcel error = copyout(store, uap->store, count * sizeof(struct uuid)); 196150303Smarcel free(store, M_TEMP); 19797372Smarcel return (error); 19897372Smarcel} 19997372Smarcel 20097372Smarcelint 201253590Smarceluuid_ether_add(const uint8_t *addr) 202253590Smarcel{ 203253615Smarcel int i, sum; 204253590Smarcel 205253590Smarcel /* 206253617Smarcel * Validate input. No multicast (flag 0x1), no locally administered 207253617Smarcel * (flag 0x2) and no 'all-zeroes' addresses. 208253590Smarcel */ 209253617Smarcel if (addr[0] & 0x03) 210253590Smarcel return (EINVAL); 211253615Smarcel sum = 0; 212253590Smarcel for (i = 0; i < UUID_NODE_LEN; i++) 213253615Smarcel sum += addr[i]; 214253615Smarcel if (sum == 0) 215253590Smarcel return (EINVAL); 216253590Smarcel 217253590Smarcel mtx_lock(&uuid_mutex); 218253590Smarcel 219253590Smarcel /* Make sure the MAC isn't known already and that there's space. */ 220253590Smarcel i = 0; 221253590Smarcel while (i < UUID_NETHER && uuid_ether[i].state == UUID_ETHER_UNIQUE) { 222253590Smarcel if (!bcmp(addr, uuid_ether[i].node, UUID_NODE_LEN)) { 223253590Smarcel mtx_unlock(&uuid_mutex); 224253590Smarcel return (EEXIST); 225253590Smarcel } 226253590Smarcel i++; 227253590Smarcel } 228253590Smarcel if (i == UUID_NETHER) { 229253590Smarcel mtx_unlock(&uuid_mutex); 230253590Smarcel return (ENOSPC); 231253590Smarcel } 232253590Smarcel 233253590Smarcel /* Insert MAC at index, moving the non-empty entry if possible. */ 234253590Smarcel if (uuid_ether[i].state == UUID_ETHER_RANDOM && i < UUID_NETHER - 1) 235253590Smarcel uuid_ether[i + 1] = uuid_ether[i]; 236253590Smarcel uuid_ether[i].state = UUID_ETHER_UNIQUE; 237253590Smarcel bcopy(addr, uuid_ether[i].node, UUID_NODE_LEN); 238253590Smarcel mtx_unlock(&uuid_mutex); 239253590Smarcel return (0); 240253590Smarcel} 241253590Smarcel 242253590Smarcelint 243253590Smarceluuid_ether_del(const uint8_t *addr) 244253590Smarcel{ 245253590Smarcel int i; 246253590Smarcel 247253590Smarcel mtx_lock(&uuid_mutex); 248253590Smarcel i = 0; 249253590Smarcel while (i < UUID_NETHER && uuid_ether[i].state == UUID_ETHER_UNIQUE && 250253590Smarcel bcmp(addr, uuid_ether[i].node, UUID_NODE_LEN)) 251253590Smarcel i++; 252253590Smarcel if (i == UUID_NETHER || uuid_ether[i].state != UUID_ETHER_UNIQUE) { 253253590Smarcel mtx_unlock(&uuid_mutex); 254253590Smarcel return (ENOENT); 255253590Smarcel } 256253590Smarcel 257253590Smarcel /* Remove it by shifting higher index entries down. */ 258253590Smarcel while (i < UUID_NETHER - 1 && uuid_ether[i].state != UUID_ETHER_EMPTY) { 259253590Smarcel uuid_ether[i] = uuid_ether[i + 1]; 260253590Smarcel i++; 261253590Smarcel } 262253590Smarcel if (uuid_ether[i].state != UUID_ETHER_EMPTY) { 263253590Smarcel uuid_ether[i].state = UUID_ETHER_EMPTY; 264253590Smarcel bzero(uuid_ether[i].node, UUID_NODE_LEN); 265253590Smarcel } 266253590Smarcel mtx_unlock(&uuid_mutex); 267253590Smarcel return (0); 268253590Smarcel} 269253590Smarcel 270253590Smarcelint 27197372Smarcelsnprintf_uuid(char *buf, size_t sz, struct uuid *uuid) 27297372Smarcel{ 27397372Smarcel struct uuid_private *id; 27497372Smarcel int cnt; 27597372Smarcel 27697372Smarcel id = (struct uuid_private *)uuid; 27797372Smarcel cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x", 27897372Smarcel id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq), 27997372Smarcel be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2])); 28097372Smarcel return (cnt); 28197372Smarcel} 28297372Smarcel 28397372Smarcelint 28497372Smarcelprintf_uuid(struct uuid *uuid) 28597372Smarcel{ 28697372Smarcel char buf[38]; 28797372Smarcel 28897372Smarcel snprintf_uuid(buf, sizeof(buf), uuid); 28997372Smarcel return (printf("%s", buf)); 29097372Smarcel} 29197372Smarcel 29297372Smarcelint 29397372Smarcelsbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid) 29497372Smarcel{ 29597372Smarcel char buf[38]; 29697372Smarcel 29797372Smarcel snprintf_uuid(buf, sizeof(buf), uuid); 29897372Smarcel return (sbuf_printf(sb, "%s", buf)); 29997372Smarcel} 300115459Sphk 301115459Sphk/* 302115459Sphk * Encode/Decode UUID into byte-stream. 303115459Sphk * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 304115459Sphk * 305115459Sphk * 0 1 2 3 306115459Sphk * 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 307115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 308115459Sphk * | time_low | 309115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 310115459Sphk * | time_mid | time_hi_and_version | 311115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 312115459Sphk * |clk_seq_hi_res | clk_seq_low | node (0-1) | 313115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 314115459Sphk * | node (2-5) | 315115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 316115459Sphk */ 317115459Sphk 318115459Sphkvoid 319115459Sphkle_uuid_enc(void *buf, struct uuid const *uuid) 320115459Sphk{ 321115459Sphk u_char *p; 322115459Sphk int i; 323115459Sphk 324115459Sphk p = buf; 325115459Sphk le32enc(p, uuid->time_low); 326115459Sphk le16enc(p + 4, uuid->time_mid); 327115459Sphk le16enc(p + 6, uuid->time_hi_and_version); 328115459Sphk p[8] = uuid->clock_seq_hi_and_reserved; 329115459Sphk p[9] = uuid->clock_seq_low; 330115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 331115459Sphk p[10 + i] = uuid->node[i]; 332115459Sphk} 333115459Sphk 334115459Sphkvoid 335115459Sphkle_uuid_dec(void const *buf, struct uuid *uuid) 336115459Sphk{ 337115459Sphk u_char const *p; 338115459Sphk int i; 339115459Sphk 340115459Sphk p = buf; 341115459Sphk uuid->time_low = le32dec(p); 342115459Sphk uuid->time_mid = le16dec(p + 4); 343115459Sphk uuid->time_hi_and_version = le16dec(p + 6); 344115459Sphk uuid->clock_seq_hi_and_reserved = p[8]; 345115459Sphk uuid->clock_seq_low = p[9]; 346115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 347115459Sphk uuid->node[i] = p[10 + i]; 348115459Sphk} 349160448Sstefanf 350115459Sphkvoid 351115459Sphkbe_uuid_enc(void *buf, struct uuid const *uuid) 352115459Sphk{ 353115459Sphk u_char *p; 354115459Sphk int i; 355115459Sphk 356115459Sphk p = buf; 357115459Sphk be32enc(p, uuid->time_low); 358115459Sphk be16enc(p + 4, uuid->time_mid); 359115459Sphk be16enc(p + 6, uuid->time_hi_and_version); 360115459Sphk p[8] = uuid->clock_seq_hi_and_reserved; 361115459Sphk p[9] = uuid->clock_seq_low; 362115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 363115459Sphk p[10 + i] = uuid->node[i]; 364115459Sphk} 365115459Sphk 366115459Sphkvoid 367115459Sphkbe_uuid_dec(void const *buf, struct uuid *uuid) 368115459Sphk{ 369115459Sphk u_char const *p; 370115459Sphk int i; 371115459Sphk 372115459Sphk p = buf; 373115459Sphk uuid->time_low = be32dec(p); 374261858Sbrueffer uuid->time_mid = be16dec(p + 4); 375115459Sphk uuid->time_hi_and_version = be16dec(p + 6); 376115459Sphk uuid->clock_seq_hi_and_reserved = p[8]; 377115459Sphk uuid->clock_seq_low = p[9]; 378115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 379115459Sphk uuid->node[i] = p[10 + i]; 380115459Sphk} 381151059Smarcel 382151059Smarcelint 383151059Smarcelparse_uuid(const char *str, struct uuid *uuid) 384151059Smarcel{ 385151059Smarcel u_int c[11]; 386151059Smarcel int n; 387151059Smarcel 388151059Smarcel /* An empty string represents a nil UUID. */ 389151059Smarcel if (*str == '\0') { 390151059Smarcel bzero(uuid, sizeof(*uuid)); 391151059Smarcel return (0); 392151059Smarcel } 393151059Smarcel 394151059Smarcel /* The UUID string representation has a fixed length. */ 395151059Smarcel if (strlen(str) != 36) 396151059Smarcel return (EINVAL); 397151059Smarcel 398151059Smarcel /* 399151059Smarcel * We only work with "new" UUIDs. New UUIDs have the form: 400151059Smarcel * 01234567-89ab-cdef-0123-456789abcdef 401151059Smarcel * The so called "old" UUIDs, which we don't support, have the form: 402151059Smarcel * 0123456789ab.cd.ef.01.23.45.67.89.ab 403151059Smarcel */ 404151059Smarcel if (str[8] != '-') 405151059Smarcel return (EINVAL); 406151059Smarcel 407151059Smarcel n = sscanf(str, "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", c + 0, c + 1, 408151059Smarcel c + 2, c + 3, c + 4, c + 5, c + 6, c + 7, c + 8, c + 9, c + 10); 409151059Smarcel /* Make sure we have all conversions. */ 410151059Smarcel if (n != 11) 411151059Smarcel return (EINVAL); 412151059Smarcel 413151059Smarcel /* Successful scan. Build the UUID. */ 414151059Smarcel uuid->time_low = c[0]; 415151059Smarcel uuid->time_mid = c[1]; 416151059Smarcel uuid->time_hi_and_version = c[2]; 417151059Smarcel uuid->clock_seq_hi_and_reserved = c[3]; 418151059Smarcel uuid->clock_seq_low = c[4]; 419151059Smarcel for (n = 0; n < 6; n++) 420151059Smarcel uuid->node[n] = c[n + 5]; 421151059Smarcel 422151059Smarcel /* Check semantics... */ 423151059Smarcel return (((c[3] & 0x80) != 0x00 && /* variant 0? */ 424151059Smarcel (c[3] & 0xc0) != 0x80 && /* variant 1? */ 425151059Smarcel (c[3] & 0xe0) != 0xc0) ? EINVAL : 0); /* variant 2? */ 426151059Smarcel} 427