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