kern_uuid.c revision 150303
1169689Skan/*- 2169689Skan * Copyright (c) 2002 Marcel Moolenaar 390075Sobrien * All rights reserved. 490075Sobrien * 590075Sobrien * Redistribution and use in source and binary forms, with or without 690075Sobrien * modification, are permitted provided that the following conditions 790075Sobrien * are met: 890075Sobrien * 990075Sobrien * 1. Redistributions of source code must retain the above copyright 1090075Sobrien * notice, this list of conditions and the following disclaimer. 1190075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1290075Sobrien * notice, this list of conditions and the following disclaimer in the 1390075Sobrien * documentation and/or other materials provided with the distribution. 1490075Sobrien * 1590075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1690075Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1790075Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1890075Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1990075Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2090075Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2190075Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2290075Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2390075Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2490075Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2590075Sobrien */ 2690075Sobrien 27132718Skan#include <sys/cdefs.h> 2890075Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_uuid.c 150303 2005-09-18 21:40:15Z marcel $"); 2990075Sobrien 3090075Sobrien#include <sys/param.h> 3190075Sobrien#include <sys/endian.h> 3290075Sobrien#include <sys/kernel.h> 3390075Sobrien#include <sys/lock.h> 3490075Sobrien#include <sys/mutex.h> 3590075Sobrien#include <sys/sbuf.h> 3690075Sobrien#include <sys/socket.h> 3790075Sobrien#include <sys/sysproto.h> 3890075Sobrien#include <sys/systm.h> 3990075Sobrien#include <sys/uuid.h> 4090075Sobrien 4190075Sobrien#include <net/if.h> 4290075Sobrien#include <net/if_dl.h> 4390075Sobrien#include <net/if_types.h> 4490075Sobrien 4590075Sobrien/* 4690075Sobrien * See also: 4790075Sobrien * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 4890075Sobrien * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm 4990075Sobrien * 5090075Sobrien * Note that the generator state is itself an UUID, but the time and clock 5190075Sobrien * sequence fields are written in the native byte order. 5290075Sobrien */ 5390075Sobrien 5490075SobrienCTASSERT(sizeof(struct uuid) == 16); 5590075Sobrien 5690075Sobrien/* We use an alternative, more convenient representation in the generator. */ 5790075Sobrienstruct uuid_private { 5890075Sobrien union { 5990075Sobrien uint64_t ll; /* internal. */ 6090075Sobrien struct { 6190075Sobrien uint32_t low; 6290075Sobrien uint16_t mid; 6390075Sobrien uint16_t hi; 6490075Sobrien } x; 6590075Sobrien } time; 6690075Sobrien uint16_t seq; /* Big-endian. */ 6790075Sobrien uint16_t node[UUID_NODE_LEN>>1]; 6890075Sobrien}; 6990075Sobrien 7090075SobrienCTASSERT(sizeof(struct uuid_private) == 16); 7190075Sobrien 7290075Sobrienstatic struct uuid_private uuid_last; 7390075Sobrien 7490075Sobrienstatic struct mtx uuid_mutex; 7590075SobrienMTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF); 76169689Skan 7790075Sobrien/* 78169689Skan * Return the first MAC address we encounter or, if none was found, 7990075Sobrien * construct a sufficiently random multicast address. We don't try 8090075Sobrien * to return the same MAC address as previously returned. We always 8190075Sobrien * generate a new multicast address if no MAC address exists in the 8290075Sobrien * system. 8390075Sobrien * It would be nice to know if 'ifnet' or any of its sub-structures 8490075Sobrien * has been changed in any way. If not, we could simply skip the 8590075Sobrien * scan and safely return the MAC address we returned before. 8690075Sobrien */ 8790075Sobrienstatic void 8890075Sobrienuuid_node(uint16_t *node) 8990075Sobrien{ 9090075Sobrien struct ifnet *ifp; 9190075Sobrien struct ifaddr *ifa; 9290075Sobrien struct sockaddr_dl *sdl; 9390075Sobrien int i; 9490075Sobrien 9590075Sobrien IFNET_RLOCK(); 9690075Sobrien TAILQ_FOREACH(ifp, &ifnet, if_link) { 9790075Sobrien /* Walk the address list */ 9890075Sobrien TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 9990075Sobrien sdl = (struct sockaddr_dl*)ifa->ifa_addr; 10090075Sobrien if (sdl != NULL && sdl->sdl_family == AF_LINK && 10190075Sobrien sdl->sdl_type == IFT_ETHER) { 10290075Sobrien /* Got a MAC address. */ 103132718Skan bcopy(LLADDR(sdl), node, UUID_NODE_LEN); 10490075Sobrien IFNET_RUNLOCK(); 10590075Sobrien return; 10690075Sobrien } 10790075Sobrien } 10890075Sobrien } 10990075Sobrien IFNET_RUNLOCK(); 11090075Sobrien 11190075Sobrien for (i = 0; i < (UUID_NODE_LEN>>1); i++) 11290075Sobrien node[i] = (uint16_t)arc4random(); 11390075Sobrien *((uint8_t*)node) |= 0x01; 11490075Sobrien} 11590075Sobrien 11690075Sobrien/* 11790075Sobrien * Get the current time as a 60 bit count of 100-nanosecond intervals 11890075Sobrien * since 00:00:00.00, October 15,1582. We apply a magic offset to convert 11990075Sobrien * the Unix time since 00:00:00.00, Januari 1, 1970 to the date of the 12090075Sobrien * Gregorian reform to the Christian calendar. 12190075Sobrien */ 122132718Skanstatic uint64_t 123132718Skanuuid_time(void) 12490075Sobrien{ 12590075Sobrien struct bintime bt; 12690075Sobrien uint64_t time = 0x01B21DD213814000LL; 12790075Sobrien 12890075Sobrien bintime(&bt); 12990075Sobrien time += (uint64_t)bt.sec * 10000000LL; 13090075Sobrien time += (10000000LL * (uint32_t)(bt.frac >> 32)) >> 32; 13190075Sobrien return (time & ((1LL << 60) - 1LL)); 13290075Sobrien} 13390075Sobrien 13490075Sobrienstruct uuid * 13590075Sobrienkern_uuidgen(struct uuid *store, size_t count) 13690075Sobrien{ 13790075Sobrien struct uuid_private uuid; 13890075Sobrien uint64_t time; 13990075Sobrien size_t n; 14090075Sobrien 141169689Skan mtx_lock(&uuid_mutex); 14290075Sobrien 14390075Sobrien uuid_node(uuid.node); 144169689Skan time = uuid_time(); 14590075Sobrien 14690075Sobrien if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] || 147169689Skan uuid_last.node[1] != uuid.node[1] || 148169689Skan uuid_last.node[2] != uuid.node[2]) 14990075Sobrien uuid.seq = (uint16_t)arc4random() & 0x3fff; 150169689Skan else if (uuid_last.time.ll >= time) 151169689Skan uuid.seq = (uuid_last.seq + 1) & 0x3fff; 152169689Skan else 15390075Sobrien uuid.seq = uuid_last.seq; 154169689Skan 155169689Skan uuid_last = uuid; 156169689Skan uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL); 157169689Skan 158169689Skan mtx_unlock(&uuid_mutex); 159169689Skan 160169689Skan /* Set sequence and variant and deal with byte order. */ 161169689Skan uuid.seq = htobe16(uuid.seq | 0x8000); 162169689Skan 16390075Sobrien for (n = 0; n < count; n++) { 16490075Sobrien /* Set time and version (=1). */ 16590075Sobrien uuid.time.x.low = (uint32_t)time; 16690075Sobrien uuid.time.x.mid = (uint16_t)(time >> 32); 167169689Skan uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12); 16890075Sobrien store[n] = *(struct uuid *)&uuid; 16990075Sobrien time++; 17090075Sobrien } 17190075Sobrien 172169689Skan return (store); 17390075Sobrien} 17490075Sobrien 17590075Sobrien#ifndef _SYS_SYSPROTO_H_ 176169689Skanstruct uuidgen_args { 17790075Sobrien struct uuid *store; 17890075Sobrien int count; 17990075Sobrien}; 18090075Sobrien#endif 18190075Sobrien 182169689Skanint 18390075Sobrienuuidgen(struct thread *td, struct uuidgen_args *uap) 184169689Skan{ 18590075Sobrien struct uuid *store; 186169689Skan size_t count; 18790075Sobrien int error; 18890075Sobrien 18990075Sobrien /* 190169689Skan * Limit the number of UUIDs that can be created at the same time 19190075Sobrien * to some arbitrary number. This isn't really necessary, but I 19290075Sobrien * like to have some sort of upper-bound that's less than 2G :-) 19390075Sobrien * XXX probably needs to be tunable. 194169689Skan */ 19590075Sobrien if (uap->count < 1 || uap->count > 2048) 19690075Sobrien return (EINVAL); 19790075Sobrien 198169689Skan count = uap->count; 19990075Sobrien store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK); 20090075Sobrien kern_uuidgen(store, count); 20190075Sobrien error = copyout(store, uap->store, count * sizeof(struct uuid)); 20290075Sobrien free(store, M_TEMP); 20390075Sobrien return (error); 204169689Skan} 20590075Sobrien 20690075Sobrienint 20790075Sobriensnprintf_uuid(char *buf, size_t sz, struct uuid *uuid) 20890075Sobrien{ 20990075Sobrien struct uuid_private *id; 21090075Sobrien int cnt; 21190075Sobrien 21290075Sobrien id = (struct uuid_private *)uuid; 21390075Sobrien cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x", 21490075Sobrien id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq), 21590075Sobrien be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2])); 21690075Sobrien return (cnt); 21790075Sobrien} 21890075Sobrien 21990075Sobrienint 22090075Sobrienprintf_uuid(struct uuid *uuid) 22190075Sobrien{ 22290075Sobrien char buf[38]; 22390075Sobrien 22490075Sobrien snprintf_uuid(buf, sizeof(buf), uuid); 22590075Sobrien return (printf("%s", buf)); 22690075Sobrien} 22790075Sobrien 22890075Sobrienint 22990075Sobriensbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid) 23090075Sobrien{ 23190075Sobrien char buf[38]; 23290075Sobrien 23390075Sobrien snprintf_uuid(buf, sizeof(buf), uuid); 23490075Sobrien return (sbuf_printf(sb, "%s", buf)); 23590075Sobrien} 23690075Sobrien 23790075Sobrien/* 23890075Sobrien * Encode/Decode UUID into byte-stream. 23990075Sobrien * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt 24090075Sobrien * 24190075Sobrien * 0 1 2 3 24290075Sobrien * 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 24390075Sobrien * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24490075Sobrien * | time_low | 24590075Sobrien * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24690075Sobrien * | time_mid | time_hi_and_version | 24790075Sobrien * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24890075Sobrien * |clk_seq_hi_res | clk_seq_low | node (0-1) | 24990075Sobrien * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25090075Sobrien * | node (2-5) | 25190075Sobrien * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25290075Sobrien */ 25390075Sobrien 25490075Sobrienvoid 25590075Sobrienle_uuid_enc(void *buf, struct uuid const *uuid) 25690075Sobrien{ 257117395Skan u_char *p; 258117395Skan int i; 259117395Skan 26090075Sobrien p = buf; 26190075Sobrien le32enc(p, uuid->time_low); 26290075Sobrien le16enc(p + 4, uuid->time_mid); 26390075Sobrien le16enc(p + 6, uuid->time_hi_and_version); 26490075Sobrien p[8] = uuid->clock_seq_hi_and_reserved; 26590075Sobrien p[9] = uuid->clock_seq_low; 26690075Sobrien for (i = 0; i < _UUID_NODE_LEN; i++) 26790075Sobrien p[10 + i] = uuid->node[i]; 26890075Sobrien} 26990075Sobrien 27090075Sobrienvoid 27190075Sobrienle_uuid_dec(void const *buf, struct uuid *uuid) 27290075Sobrien{ 27390075Sobrien u_char const *p; 27490075Sobrien int i; 27590075Sobrien 27690075Sobrien p = buf; 27790075Sobrien uuid->time_low = le32dec(p); 27890075Sobrien uuid->time_mid = le16dec(p + 4); 27990075Sobrien uuid->time_hi_and_version = le16dec(p + 6); 28090075Sobrien uuid->clock_seq_hi_and_reserved = p[8]; 28190075Sobrien uuid->clock_seq_low = p[9]; 28290075Sobrien for (i = 0; i < _UUID_NODE_LEN; i++) 28390075Sobrien uuid->node[i] = p[10 + i]; 28490075Sobrien} 28590075Sobrienvoid 28690075Sobrienbe_uuid_enc(void *buf, struct uuid const *uuid) 28790075Sobrien{ 28890075Sobrien u_char *p; 28990075Sobrien int i; 29090075Sobrien 29190075Sobrien p = buf; 29290075Sobrien be32enc(p, uuid->time_low); 29390075Sobrien be16enc(p + 4, uuid->time_mid); 29490075Sobrien be16enc(p + 6, uuid->time_hi_and_version); 29590075Sobrien p[8] = uuid->clock_seq_hi_and_reserved; 29690075Sobrien p[9] = uuid->clock_seq_low; 29790075Sobrien for (i = 0; i < _UUID_NODE_LEN; i++) 29890075Sobrien p[10 + i] = uuid->node[i]; 29990075Sobrien} 30090075Sobrien 30190075Sobrienvoid 30290075Sobrienbe_uuid_dec(void const *buf, struct uuid *uuid) 30390075Sobrien{ 30490075Sobrien u_char const *p; 30590075Sobrien int i; 30690075Sobrien 30790075Sobrien p = buf; 30890075Sobrien uuid->time_low = be32dec(p); 30990075Sobrien uuid->time_mid = le16dec(p + 4); 31090075Sobrien uuid->time_hi_and_version = be16dec(p + 6); 31190075Sobrien uuid->clock_seq_hi_and_reserved = p[8]; 31290075Sobrien uuid->clock_seq_low = p[9]; 31390075Sobrien for (i = 0; i < _UUID_NODE_LEN; i++) 31490075Sobrien uuid->node[i] = p[10 + i]; 31590075Sobrien} 31690075Sobrien