kern_uuid.c revision 168975
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: head/sys/kern/kern_uuid.c 168975 2007-04-23 12:53:00Z pjd $"); 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> 3997372Smarcel#include <sys/uuid.h> 4097372Smarcel 4197372Smarcel#include <net/if.h> 4297372Smarcel#include <net/if_dl.h> 4397372Smarcel#include <net/if_types.h> 4497372Smarcel 4597372Smarcel/* 4697372Smarcel * See also: 4797372Smarcel * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 4897372Smarcel * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm 4997372Smarcel * 5097372Smarcel * Note that the generator state is itself an UUID, but the time and clock 5197372Smarcel * sequence fields are written in the native byte order. 5297372Smarcel */ 5397372Smarcel 5497372SmarcelCTASSERT(sizeof(struct uuid) == 16); 5597372Smarcel 5697372Smarcel/* We use an alternative, more convenient representation in the generator. */ 5797372Smarcelstruct uuid_private { 5897372Smarcel union { 5997372Smarcel uint64_t ll; /* internal. */ 6097372Smarcel struct { 6197372Smarcel uint32_t low; 6297372Smarcel uint16_t mid; 6397372Smarcel uint16_t hi; 6497372Smarcel } x; 6597372Smarcel } time; 6697372Smarcel uint16_t seq; /* Big-endian. */ 6797372Smarcel uint16_t node[UUID_NODE_LEN>>1]; 6897372Smarcel}; 6997372Smarcel 7097372SmarcelCTASSERT(sizeof(struct uuid_private) == 16); 7197372Smarcel 7297372Smarcelstatic struct uuid_private uuid_last; 7397372Smarcel 7497372Smarcelstatic struct mtx uuid_mutex; 7597372SmarcelMTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF); 7697372Smarcel 7797372Smarcel/* 7897372Smarcel * Return the first MAC address we encounter or, if none was found, 7997372Smarcel * construct a sufficiently random multicast address. We don't try 8097372Smarcel * to return the same MAC address as previously returned. We always 8197372Smarcel * generate a new multicast address if no MAC address exists in the 8297372Smarcel * system. 8397372Smarcel * It would be nice to know if 'ifnet' or any of its sub-structures 8497372Smarcel * has been changed in any way. If not, we could simply skip the 8597372Smarcel * scan and safely return the MAC address we returned before. 8697372Smarcel */ 8797372Smarcelstatic void 8897372Smarceluuid_node(uint16_t *node) 8997372Smarcel{ 9097372Smarcel struct ifnet *ifp; 9197372Smarcel struct ifaddr *ifa; 9297372Smarcel struct sockaddr_dl *sdl; 9397372Smarcel int i; 9497372Smarcel 95108172Shsu IFNET_RLOCK(); 9697372Smarcel TAILQ_FOREACH(ifp, &ifnet, if_link) { 9797372Smarcel /* Walk the address list */ 9897372Smarcel TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 9997372Smarcel sdl = (struct sockaddr_dl*)ifa->ifa_addr; 10097372Smarcel if (sdl != NULL && sdl->sdl_family == AF_LINK && 10197372Smarcel sdl->sdl_type == IFT_ETHER) { 10297372Smarcel /* Got a MAC address. */ 10397372Smarcel bcopy(LLADDR(sdl), node, UUID_NODE_LEN); 104108172Shsu IFNET_RUNLOCK(); 10597372Smarcel return; 10697372Smarcel } 10797372Smarcel } 10897372Smarcel } 109108172Shsu IFNET_RUNLOCK(); 11097372Smarcel 11197372Smarcel for (i = 0; i < (UUID_NODE_LEN>>1); i++) 11297372Smarcel node[i] = (uint16_t)arc4random(); 113124835Srse *((uint8_t*)node) |= 0x01; 11497372Smarcel} 11597372Smarcel 11697372Smarcel/* 11797372Smarcel * Get the current time as a 60 bit count of 100-nanosecond intervals 11897372Smarcel * since 00:00:00.00, October 15,1582. We apply a magic offset to convert 119168975Spjd * the Unix time since 00:00:00.00, January 1, 1970 to the date of the 12097372Smarcel * Gregorian reform to the Christian calendar. 12197372Smarcel */ 12297372Smarcelstatic uint64_t 12397372Smarceluuid_time(void) 12497372Smarcel{ 12597372Smarcel struct bintime bt; 12697372Smarcel uint64_t time = 0x01B21DD213814000LL; 12797372Smarcel 12897372Smarcel bintime(&bt); 12997372Smarcel time += (uint64_t)bt.sec * 10000000LL; 13097372Smarcel time += (10000000LL * (uint32_t)(bt.frac >> 32)) >> 32; 13197372Smarcel return (time & ((1LL << 60) - 1LL)); 13297372Smarcel} 13397372Smarcel 134150303Smarcelstruct uuid * 135150303Smarcelkern_uuidgen(struct uuid *store, size_t count) 13697372Smarcel{ 13797372Smarcel struct uuid_private uuid; 13897372Smarcel uint64_t time; 139150303Smarcel size_t n; 14097372Smarcel 14197372Smarcel mtx_lock(&uuid_mutex); 14297372Smarcel 14397372Smarcel uuid_node(uuid.node); 14497372Smarcel time = uuid_time(); 14597372Smarcel 14697372Smarcel if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] || 14797372Smarcel uuid_last.node[1] != uuid.node[1] || 14897372Smarcel uuid_last.node[2] != uuid.node[2]) 14997372Smarcel uuid.seq = (uint16_t)arc4random() & 0x3fff; 15097372Smarcel else if (uuid_last.time.ll >= time) 15197372Smarcel uuid.seq = (uuid_last.seq + 1) & 0x3fff; 15297372Smarcel else 15397372Smarcel uuid.seq = uuid_last.seq; 15497372Smarcel 15597372Smarcel uuid_last = uuid; 156150303Smarcel uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL); 15797372Smarcel 15897372Smarcel mtx_unlock(&uuid_mutex); 15997372Smarcel 16097372Smarcel /* Set sequence and variant and deal with byte order. */ 16197372Smarcel uuid.seq = htobe16(uuid.seq | 0x8000); 16297372Smarcel 163150303Smarcel for (n = 0; n < count; n++) { 164150303Smarcel /* Set time and version (=1). */ 16597372Smarcel uuid.time.x.low = (uint32_t)time; 16697372Smarcel uuid.time.x.mid = (uint16_t)(time >> 32); 16797372Smarcel uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12); 168150303Smarcel store[n] = *(struct uuid *)&uuid; 16997372Smarcel time++; 170150303Smarcel } 17197372Smarcel 172150303Smarcel return (store); 173150303Smarcel} 174150303Smarcel 175150303Smarcel#ifndef _SYS_SYSPROTO_H_ 176150303Smarcelstruct uuidgen_args { 177150303Smarcel struct uuid *store; 178150303Smarcel int count; 179150303Smarcel}; 180150303Smarcel#endif 181150303Smarcelint 182150303Smarceluuidgen(struct thread *td, struct uuidgen_args *uap) 183150303Smarcel{ 184150303Smarcel struct uuid *store; 185150303Smarcel size_t count; 186150303Smarcel int error; 187150303Smarcel 188150303Smarcel /* 189150303Smarcel * Limit the number of UUIDs that can be created at the same time 190150303Smarcel * to some arbitrary number. This isn't really necessary, but I 191150303Smarcel * like to have some sort of upper-bound that's less than 2G :-) 192150303Smarcel * XXX probably needs to be tunable. 193150303Smarcel */ 194150303Smarcel if (uap->count < 1 || uap->count > 2048) 195150303Smarcel return (EINVAL); 196150303Smarcel 197150303Smarcel count = uap->count; 198150303Smarcel store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK); 199150303Smarcel kern_uuidgen(store, count); 200150303Smarcel error = copyout(store, uap->store, count * sizeof(struct uuid)); 201150303Smarcel free(store, M_TEMP); 20297372Smarcel return (error); 20397372Smarcel} 20497372Smarcel 20597372Smarcelint 20697372Smarcelsnprintf_uuid(char *buf, size_t sz, struct uuid *uuid) 20797372Smarcel{ 20897372Smarcel struct uuid_private *id; 20997372Smarcel int cnt; 21097372Smarcel 21197372Smarcel id = (struct uuid_private *)uuid; 21297372Smarcel cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x", 21397372Smarcel id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq), 21497372Smarcel be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2])); 21597372Smarcel return (cnt); 21697372Smarcel} 21797372Smarcel 21897372Smarcelint 21997372Smarcelprintf_uuid(struct uuid *uuid) 22097372Smarcel{ 22197372Smarcel char buf[38]; 22297372Smarcel 22397372Smarcel snprintf_uuid(buf, sizeof(buf), uuid); 22497372Smarcel return (printf("%s", buf)); 22597372Smarcel} 22697372Smarcel 22797372Smarcelint 22897372Smarcelsbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid) 22997372Smarcel{ 23097372Smarcel char buf[38]; 23197372Smarcel 23297372Smarcel snprintf_uuid(buf, sizeof(buf), uuid); 23397372Smarcel return (sbuf_printf(sb, "%s", buf)); 23497372Smarcel} 235115459Sphk 236115459Sphk/* 237115459Sphk * Encode/Decode UUID into byte-stream. 238115459Sphk * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 239115459Sphk * 240115459Sphk * 0 1 2 3 241115459Sphk * 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 242115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 243115459Sphk * | time_low | 244115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 245115459Sphk * | time_mid | time_hi_and_version | 246115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 247115459Sphk * |clk_seq_hi_res | clk_seq_low | node (0-1) | 248115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 249115459Sphk * | node (2-5) | 250115459Sphk * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 251115459Sphk */ 252115459Sphk 253115459Sphkvoid 254115459Sphkle_uuid_enc(void *buf, struct uuid const *uuid) 255115459Sphk{ 256115459Sphk u_char *p; 257115459Sphk int i; 258115459Sphk 259115459Sphk p = buf; 260115459Sphk le32enc(p, uuid->time_low); 261115459Sphk le16enc(p + 4, uuid->time_mid); 262115459Sphk le16enc(p + 6, uuid->time_hi_and_version); 263115459Sphk p[8] = uuid->clock_seq_hi_and_reserved; 264115459Sphk p[9] = uuid->clock_seq_low; 265115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 266115459Sphk p[10 + i] = uuid->node[i]; 267115459Sphk} 268115459Sphk 269115459Sphkvoid 270115459Sphkle_uuid_dec(void const *buf, struct uuid *uuid) 271115459Sphk{ 272115459Sphk u_char const *p; 273115459Sphk int i; 274115459Sphk 275115459Sphk p = buf; 276115459Sphk uuid->time_low = le32dec(p); 277115459Sphk uuid->time_mid = le16dec(p + 4); 278115459Sphk uuid->time_hi_and_version = le16dec(p + 6); 279115459Sphk uuid->clock_seq_hi_and_reserved = p[8]; 280115459Sphk uuid->clock_seq_low = p[9]; 281115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 282115459Sphk uuid->node[i] = p[10 + i]; 283115459Sphk} 284160448Sstefanf 285115459Sphkvoid 286115459Sphkbe_uuid_enc(void *buf, struct uuid const *uuid) 287115459Sphk{ 288115459Sphk u_char *p; 289115459Sphk int i; 290115459Sphk 291115459Sphk p = buf; 292115459Sphk be32enc(p, uuid->time_low); 293115459Sphk be16enc(p + 4, uuid->time_mid); 294115459Sphk be16enc(p + 6, uuid->time_hi_and_version); 295115459Sphk p[8] = uuid->clock_seq_hi_and_reserved; 296115459Sphk p[9] = uuid->clock_seq_low; 297115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 298115459Sphk p[10 + i] = uuid->node[i]; 299115459Sphk} 300115459Sphk 301115459Sphkvoid 302115459Sphkbe_uuid_dec(void const *buf, struct uuid *uuid) 303115459Sphk{ 304115459Sphk u_char const *p; 305115459Sphk int i; 306115459Sphk 307115459Sphk p = buf; 308115459Sphk uuid->time_low = be32dec(p); 309115459Sphk uuid->time_mid = le16dec(p + 4); 310115459Sphk uuid->time_hi_and_version = be16dec(p + 6); 311115459Sphk uuid->clock_seq_hi_and_reserved = p[8]; 312115459Sphk uuid->clock_seq_low = p[9]; 313115459Sphk for (i = 0; i < _UUID_NODE_LEN; i++) 314115459Sphk uuid->node[i] = p[10 + i]; 315115459Sphk} 316151059Smarcel 317151059Smarcelint 318151059Smarcelparse_uuid(const char *str, struct uuid *uuid) 319151059Smarcel{ 320151059Smarcel u_int c[11]; 321151059Smarcel int n; 322151059Smarcel 323151059Smarcel /* An empty string represents a nil UUID. */ 324151059Smarcel if (*str == '\0') { 325151059Smarcel bzero(uuid, sizeof(*uuid)); 326151059Smarcel return (0); 327151059Smarcel } 328151059Smarcel 329151059Smarcel /* The UUID string representation has a fixed length. */ 330151059Smarcel if (strlen(str) != 36) 331151059Smarcel return (EINVAL); 332151059Smarcel 333151059Smarcel /* 334151059Smarcel * We only work with "new" UUIDs. New UUIDs have the form: 335151059Smarcel * 01234567-89ab-cdef-0123-456789abcdef 336151059Smarcel * The so called "old" UUIDs, which we don't support, have the form: 337151059Smarcel * 0123456789ab.cd.ef.01.23.45.67.89.ab 338151059Smarcel */ 339151059Smarcel if (str[8] != '-') 340151059Smarcel return (EINVAL); 341151059Smarcel 342151059Smarcel n = sscanf(str, "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", c + 0, c + 1, 343151059Smarcel c + 2, c + 3, c + 4, c + 5, c + 6, c + 7, c + 8, c + 9, c + 10); 344151059Smarcel /* Make sure we have all conversions. */ 345151059Smarcel if (n != 11) 346151059Smarcel return (EINVAL); 347151059Smarcel 348151059Smarcel /* Successful scan. Build the UUID. */ 349151059Smarcel uuid->time_low = c[0]; 350151059Smarcel uuid->time_mid = c[1]; 351151059Smarcel uuid->time_hi_and_version = c[2]; 352151059Smarcel uuid->clock_seq_hi_and_reserved = c[3]; 353151059Smarcel uuid->clock_seq_low = c[4]; 354151059Smarcel for (n = 0; n < 6; n++) 355151059Smarcel uuid->node[n] = c[n + 5]; 356151059Smarcel 357151059Smarcel /* Check semantics... */ 358151059Smarcel return (((c[3] & 0x80) != 0x00 && /* variant 0? */ 359151059Smarcel (c[3] & 0xc0) != 0x80 && /* variant 1? */ 360151059Smarcel (c[3] & 0xe0) != 0xc0) ? EINVAL : 0); /* variant 2? */ 361151059Smarcel} 362