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 7497372Smarcelstatic struct uuid_private uuid_last; 7597372Smarcel 7697372Smarcelstatic struct mtx uuid_mutex; 7797372SmarcelMTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF); 7897372Smarcel 7997372Smarcel/* 8097372Smarcel * Return the first MAC address we encounter or, if none was found, 8197372Smarcel * construct a sufficiently random multicast address. We don't try 8297372Smarcel * to return the same MAC address as previously returned. We always 8397372Smarcel * generate a new multicast address if no MAC address exists in the 8497372Smarcel * system. 8597372Smarcel * It would be nice to know if 'ifnet' or any of its sub-structures 8697372Smarcel * has been changed in any way. If not, we could simply skip the 8797372Smarcel * scan and safely return the MAC address we returned before. 8897372Smarcel */ 8997372Smarcelstatic void 9097372Smarceluuid_node(uint16_t *node) 9197372Smarcel{ 9297372Smarcel struct ifnet *ifp; 9397372Smarcel struct ifaddr *ifa; 9497372Smarcel struct sockaddr_dl *sdl; 9597372Smarcel int i; 9697372Smarcel 97196038Sjulian CURVNET_SET(TD_TO_VNET(curthread)); 98196481Srwatson IFNET_RLOCK_NOSLEEP(); 99181803Sbz TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 10097372Smarcel /* Walk the address list */ 101233200Sjhb IF_ADDR_RLOCK(ifp); 10297372Smarcel TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 10397372Smarcel sdl = (struct sockaddr_dl*)ifa->ifa_addr; 10497372Smarcel if (sdl != NULL && sdl->sdl_family == AF_LINK && 10597372Smarcel sdl->sdl_type == IFT_ETHER) { 10697372Smarcel /* Got a MAC address. */ 10797372Smarcel bcopy(LLADDR(sdl), node, UUID_NODE_LEN); 108233200Sjhb IF_ADDR_RUNLOCK(ifp); 109196481Srwatson IFNET_RUNLOCK_NOSLEEP(); 110196038Sjulian CURVNET_RESTORE(); 11197372Smarcel return; 11297372Smarcel } 11397372Smarcel } 114233200Sjhb IF_ADDR_RUNLOCK(ifp); 11597372Smarcel } 116196481Srwatson IFNET_RUNLOCK_NOSLEEP(); 11797372Smarcel 11897372Smarcel for (i = 0; i < (UUID_NODE_LEN>>1); i++) 11997372Smarcel node[i] = (uint16_t)arc4random(); 120124835Srse *((uint8_t*)node) |= 0x01; 121196038Sjulian CURVNET_RESTORE(); 12297372Smarcel} 12397372Smarcel 12497372Smarcel/* 12597372Smarcel * Get the current time as a 60 bit count of 100-nanosecond intervals 12697372Smarcel * since 00:00:00.00, October 15,1582. We apply a magic offset to convert 127168975Spjd * the Unix time since 00:00:00.00, January 1, 1970 to the date of the 12897372Smarcel * Gregorian reform to the Christian calendar. 12997372Smarcel */ 13097372Smarcelstatic uint64_t 13197372Smarceluuid_time(void) 13297372Smarcel{ 13397372Smarcel struct bintime bt; 13497372Smarcel uint64_t time = 0x01B21DD213814000LL; 13597372Smarcel 13697372Smarcel bintime(&bt); 13797372Smarcel time += (uint64_t)bt.sec * 10000000LL; 13897372Smarcel time += (10000000LL * (uint32_t)(bt.frac >> 32)) >> 32; 13997372Smarcel return (time & ((1LL << 60) - 1LL)); 14097372Smarcel} 14197372Smarcel 142150303Smarcelstruct uuid * 143150303Smarcelkern_uuidgen(struct uuid *store, size_t count) 14497372Smarcel{ 14597372Smarcel struct uuid_private uuid; 14697372Smarcel uint64_t time; 147150303Smarcel size_t n; 14897372Smarcel 14997372Smarcel mtx_lock(&uuid_mutex); 15097372Smarcel 15197372Smarcel uuid_node(uuid.node); 15297372Smarcel time = uuid_time(); 15397372Smarcel 15497372Smarcel if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] || 15597372Smarcel uuid_last.node[1] != uuid.node[1] || 15697372Smarcel uuid_last.node[2] != uuid.node[2]) 15797372Smarcel uuid.seq = (uint16_t)arc4random() & 0x3fff; 15897372Smarcel else if (uuid_last.time.ll >= time) 15997372Smarcel uuid.seq = (uuid_last.seq + 1) & 0x3fff; 16097372Smarcel else 16197372Smarcel uuid.seq = uuid_last.seq; 16297372Smarcel 16397372Smarcel uuid_last = uuid; 164150303Smarcel uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL); 16597372Smarcel 16697372Smarcel mtx_unlock(&uuid_mutex); 16797372Smarcel 16897372Smarcel /* Set sequence and variant and deal with byte order. */ 16997372Smarcel uuid.seq = htobe16(uuid.seq | 0x8000); 17097372Smarcel 171150303Smarcel for (n = 0; n < count; n++) { 172150303Smarcel /* Set time and version (=1). */ 17397372Smarcel uuid.time.x.low = (uint32_t)time; 17497372Smarcel uuid.time.x.mid = (uint16_t)(time >> 32); 17597372Smarcel uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12); 176150303Smarcel store[n] = *(struct uuid *)&uuid; 17797372Smarcel time++; 178150303Smarcel } 17997372Smarcel 180150303Smarcel return (store); 181150303Smarcel} 182150303Smarcel 183150303Smarcel#ifndef _SYS_SYSPROTO_H_ 184150303Smarcelstruct uuidgen_args { 185150303Smarcel struct uuid *store; 186150303Smarcel int count; 187150303Smarcel}; 188150303Smarcel#endif 189150303Smarcelint 190225617Skmacysys_uuidgen(struct thread *td, struct uuidgen_args *uap) 191150303Smarcel{ 192150303Smarcel struct uuid *store; 193150303Smarcel size_t count; 194150303Smarcel int error; 195150303Smarcel 196150303Smarcel /* 197150303Smarcel * Limit the number of UUIDs that can be created at the same time 198150303Smarcel * to some arbitrary number. This isn't really necessary, but I 199150303Smarcel * like to have some sort of upper-bound that's less than 2G :-) 200150303Smarcel * XXX probably needs to be tunable. 201150303Smarcel */ 202150303Smarcel if (uap->count < 1 || uap->count > 2048) 203150303Smarcel return (EINVAL); 204150303Smarcel 205150303Smarcel count = uap->count; 206150303Smarcel store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK); 207150303Smarcel kern_uuidgen(store, count); 208150303Smarcel error = copyout(store, uap->store, count * sizeof(struct uuid)); 209150303Smarcel free(store, M_TEMP); 21097372Smarcel return (error); 21197372Smarcel} 21297372Smarcel 21397372Smarcelint 21497372Smarcelsnprintf_uuid(char *buf, size_t sz, struct uuid *uuid) 21597372Smarcel{ 21697372Smarcel struct uuid_private *id; 21797372Smarcel int cnt; 21897372Smarcel 21997372Smarcel id = (struct uuid_private *)uuid; 22097372Smarcel cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x", 22197372Smarcel id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq), 22297372Smarcel be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2])); 22397372Smarcel return (cnt); 22497372Smarcel} 22597372Smarcel 22697372Smarcelint 22797372Smarcelprintf_uuid(struct uuid *uuid) 22897372Smarcel{ 22997372Smarcel char buf[38]; 23097372Smarcel 23197372Smarcel snprintf_uuid(buf, sizeof(buf), uuid); 23297372Smarcel return (printf("%s", buf)); 23397372Smarcel} 23497372Smarcel 23597372Smarcelint 23697372Smarcelsbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid) 23797372Smarcel{ 23897372Smarcel char buf[38]; 23997372Smarcel 24097372Smarcel snprintf_uuid(buf, sizeof(buf), uuid); 24197372Smarcel return (sbuf_printf(sb, "%s", buf)); 24297372Smarcel} 243115459Sphk 244115459Sphk/* 245115459Sphk * Encode/Decode UUID into byte-stream. 246115459Sphk * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 247115459Sphk * 248115459Sphk * 0 1 2 3 249115459Sphk * 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 250115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 251115459Sphk * | time_low | 252115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 253115459Sphk * | time_mid | time_hi_and_version | 254115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 255115459Sphk * |clk_seq_hi_res | clk_seq_low | node (0-1) | 256115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 257115459Sphk * | node (2-5) | 258115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 259115459Sphk */ 260115459Sphk 261115459Sphkvoid 262115459Sphkle_uuid_enc(void *buf, struct uuid const *uuid) 263115459Sphk{ 264115459Sphk u_char *p; 265115459Sphk int i; 266115459Sphk 267115459Sphk p = buf; 268115459Sphk le32enc(p, uuid->time_low); 269115459Sphk le16enc(p + 4, uuid->time_mid); 270115459Sphk le16enc(p + 6, uuid->time_hi_and_version); 271115459Sphk p[8] = uuid->clock_seq_hi_and_reserved; 272115459Sphk p[9] = uuid->clock_seq_low; 273115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 274115459Sphk p[10 + i] = uuid->node[i]; 275115459Sphk} 276115459Sphk 277115459Sphkvoid 278115459Sphkle_uuid_dec(void const *buf, struct uuid *uuid) 279115459Sphk{ 280115459Sphk u_char const *p; 281115459Sphk int i; 282115459Sphk 283115459Sphk p = buf; 284115459Sphk uuid->time_low = le32dec(p); 285115459Sphk uuid->time_mid = le16dec(p + 4); 286115459Sphk uuid->time_hi_and_version = le16dec(p + 6); 287115459Sphk uuid->clock_seq_hi_and_reserved = p[8]; 288115459Sphk uuid->clock_seq_low = p[9]; 289115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 290115459Sphk uuid->node[i] = p[10 + i]; 291115459Sphk} 292160448Sstefanf 293115459Sphkvoid 294115459Sphkbe_uuid_enc(void *buf, struct uuid const *uuid) 295115459Sphk{ 296115459Sphk u_char *p; 297115459Sphk int i; 298115459Sphk 299115459Sphk p = buf; 300115459Sphk be32enc(p, uuid->time_low); 301115459Sphk be16enc(p + 4, uuid->time_mid); 302115459Sphk be16enc(p + 6, uuid->time_hi_and_version); 303115459Sphk p[8] = uuid->clock_seq_hi_and_reserved; 304115459Sphk p[9] = uuid->clock_seq_low; 305115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 306115459Sphk p[10 + i] = uuid->node[i]; 307115459Sphk} 308115459Sphk 309115459Sphkvoid 310115459Sphkbe_uuid_dec(void const *buf, struct uuid *uuid) 311115459Sphk{ 312115459Sphk u_char const *p; 313115459Sphk int i; 314115459Sphk 315115459Sphk p = buf; 316115459Sphk uuid->time_low = be32dec(p); 317262240Sbrueffer uuid->time_mid = be16dec(p + 4); 318115459Sphk uuid->time_hi_and_version = be16dec(p + 6); 319115459Sphk uuid->clock_seq_hi_and_reserved = p[8]; 320115459Sphk uuid->clock_seq_low = p[9]; 321115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 322115459Sphk uuid->node[i] = p[10 + i]; 323115459Sphk} 324151059Smarcel 325151059Smarcelint 326151059Smarcelparse_uuid(const char *str, struct uuid *uuid) 327151059Smarcel{ 328151059Smarcel u_int c[11]; 329151059Smarcel int n; 330151059Smarcel 331151059Smarcel /* An empty string represents a nil UUID. */ 332151059Smarcel if (*str == '\0') { 333151059Smarcel bzero(uuid, sizeof(*uuid)); 334151059Smarcel return (0); 335151059Smarcel } 336151059Smarcel 337151059Smarcel /* The UUID string representation has a fixed length. */ 338151059Smarcel if (strlen(str) != 36) 339151059Smarcel return (EINVAL); 340151059Smarcel 341151059Smarcel /* 342151059Smarcel * We only work with "new" UUIDs. New UUIDs have the form: 343151059Smarcel * 01234567-89ab-cdef-0123-456789abcdef 344151059Smarcel * The so called "old" UUIDs, which we don't support, have the form: 345151059Smarcel * 0123456789ab.cd.ef.01.23.45.67.89.ab 346151059Smarcel */ 347151059Smarcel if (str[8] != '-') 348151059Smarcel return (EINVAL); 349151059Smarcel 350151059Smarcel n = sscanf(str, "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", c + 0, c + 1, 351151059Smarcel c + 2, c + 3, c + 4, c + 5, c + 6, c + 7, c + 8, c + 9, c + 10); 352151059Smarcel /* Make sure we have all conversions. */ 353151059Smarcel if (n != 11) 354151059Smarcel return (EINVAL); 355151059Smarcel 356151059Smarcel /* Successful scan. Build the UUID. */ 357151059Smarcel uuid->time_low = c[0]; 358151059Smarcel uuid->time_mid = c[1]; 359151059Smarcel uuid->time_hi_and_version = c[2]; 360151059Smarcel uuid->clock_seq_hi_and_reserved = c[3]; 361151059Smarcel uuid->clock_seq_low = c[4]; 362151059Smarcel for (n = 0; n < 6; n++) 363151059Smarcel uuid->node[n] = c[n + 5]; 364151059Smarcel 365151059Smarcel /* Check semantics... */ 366151059Smarcel return (((c[3] & 0x80) != 0x00 && /* variant 0? */ 367151059Smarcel (c[3] & 0xc0) != 0x80 && /* variant 1? */ 368151059Smarcel (c[3] & 0xe0) != 0xc0) ? EINVAL : 0); /* variant 2? */ 369151059Smarcel} 370