xref: /freebsd/sys/kern/kern_uuid.c (revision 73130b2224f00c6e7e7d514abbe8808aa4d5f549)
19454b2d8SWarner Losh /*-
252183d01SMarcel Moolenaar  * Copyright (c) 2002 Marcel Moolenaar
352183d01SMarcel Moolenaar  * All rights reserved.
452183d01SMarcel Moolenaar  *
552183d01SMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
652183d01SMarcel Moolenaar  * modification, are permitted provided that the following conditions
752183d01SMarcel Moolenaar  * are met:
852183d01SMarcel Moolenaar  *
952183d01SMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
1052183d01SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
1152183d01SMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
1252183d01SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
1352183d01SMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
1452183d01SMarcel Moolenaar  *
1552183d01SMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1652183d01SMarcel Moolenaar  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1752183d01SMarcel Moolenaar  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1852183d01SMarcel Moolenaar  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1952183d01SMarcel Moolenaar  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2052183d01SMarcel Moolenaar  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2152183d01SMarcel Moolenaar  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2252183d01SMarcel Moolenaar  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2352183d01SMarcel Moolenaar  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2452183d01SMarcel Moolenaar  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2552183d01SMarcel Moolenaar  */
2652183d01SMarcel Moolenaar 
27677b542eSDavid E. O'Brien #include <sys/cdefs.h>
28677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
29677b542eSDavid E. O'Brien 
3052183d01SMarcel Moolenaar #include <sys/param.h>
3152183d01SMarcel Moolenaar #include <sys/endian.h>
3252183d01SMarcel Moolenaar #include <sys/kernel.h>
3352183d01SMarcel Moolenaar #include <sys/lock.h>
3452183d01SMarcel Moolenaar #include <sys/mutex.h>
3552183d01SMarcel Moolenaar #include <sys/sbuf.h>
3652183d01SMarcel Moolenaar #include <sys/socket.h>
3752183d01SMarcel Moolenaar #include <sys/sysproto.h>
385fd65482SBruce Evans #include <sys/systm.h>
3952183d01SMarcel Moolenaar #include <sys/uuid.h>
4052183d01SMarcel Moolenaar 
4152183d01SMarcel Moolenaar #include <net/if.h>
4252183d01SMarcel Moolenaar #include <net/if_dl.h>
4352183d01SMarcel Moolenaar #include <net/if_types.h>
4452183d01SMarcel Moolenaar 
4552183d01SMarcel Moolenaar /*
4652183d01SMarcel Moolenaar  * See also:
4752183d01SMarcel Moolenaar  *	http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
4852183d01SMarcel Moolenaar  *	http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
4952183d01SMarcel Moolenaar  *
5052183d01SMarcel Moolenaar  * Note that the generator state is itself an UUID, but the time and clock
5152183d01SMarcel Moolenaar  * sequence fields are written in the native byte order.
5252183d01SMarcel Moolenaar  */
5352183d01SMarcel Moolenaar 
5452183d01SMarcel Moolenaar CTASSERT(sizeof(struct uuid) == 16);
5552183d01SMarcel Moolenaar 
5652183d01SMarcel Moolenaar /* We use an alternative, more convenient representation in the generator. */
5752183d01SMarcel Moolenaar struct uuid_private {
5852183d01SMarcel Moolenaar 	union {
5952183d01SMarcel Moolenaar 		uint64_t	ll;		/* internal. */
6052183d01SMarcel Moolenaar 		struct {
6152183d01SMarcel Moolenaar 			uint32_t	low;
6252183d01SMarcel Moolenaar 			uint16_t	mid;
6352183d01SMarcel Moolenaar 			uint16_t	hi;
6452183d01SMarcel Moolenaar 		} x;
6552183d01SMarcel Moolenaar 	} time;
6652183d01SMarcel Moolenaar 	uint16_t	seq;			/* Big-endian. */
6752183d01SMarcel Moolenaar 	uint16_t	node[UUID_NODE_LEN>>1];
6852183d01SMarcel Moolenaar };
6952183d01SMarcel Moolenaar 
7052183d01SMarcel Moolenaar CTASSERT(sizeof(struct uuid_private) == 16);
7152183d01SMarcel Moolenaar 
7252183d01SMarcel Moolenaar static struct uuid_private uuid_last;
7352183d01SMarcel Moolenaar 
7452183d01SMarcel Moolenaar static struct mtx uuid_mutex;
7552183d01SMarcel Moolenaar MTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF);
7652183d01SMarcel Moolenaar 
7752183d01SMarcel Moolenaar /*
7852183d01SMarcel Moolenaar  * Return the first MAC address we encounter or, if none was found,
7952183d01SMarcel Moolenaar  * construct a sufficiently random multicast address. We don't try
8052183d01SMarcel Moolenaar  * to return the same MAC address as previously returned. We always
8152183d01SMarcel Moolenaar  * generate a new multicast address if no MAC address exists in the
8252183d01SMarcel Moolenaar  * system.
8352183d01SMarcel Moolenaar  * It would be nice to know if 'ifnet' or any of its sub-structures
8452183d01SMarcel Moolenaar  * has been changed in any way. If not, we could simply skip the
8552183d01SMarcel Moolenaar  * scan and safely return the MAC address we returned before.
8652183d01SMarcel Moolenaar  */
8752183d01SMarcel Moolenaar static void
8852183d01SMarcel Moolenaar uuid_node(uint16_t *node)
8952183d01SMarcel Moolenaar {
9052183d01SMarcel Moolenaar 	struct ifnet *ifp;
9152183d01SMarcel Moolenaar 	struct ifaddr *ifa;
9252183d01SMarcel Moolenaar 	struct sockaddr_dl *sdl;
9352183d01SMarcel Moolenaar 	int i;
9452183d01SMarcel Moolenaar 
95b30a244cSJeffrey Hsu 	IFNET_RLOCK();
9652183d01SMarcel Moolenaar 	TAILQ_FOREACH(ifp, &ifnet, if_link) {
9752183d01SMarcel Moolenaar 		/* Walk the address list */
9852183d01SMarcel Moolenaar 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
9952183d01SMarcel Moolenaar 			sdl = (struct sockaddr_dl*)ifa->ifa_addr;
10052183d01SMarcel Moolenaar 			if (sdl != NULL && sdl->sdl_family == AF_LINK &&
10152183d01SMarcel Moolenaar 			    sdl->sdl_type == IFT_ETHER) {
10252183d01SMarcel Moolenaar 				/* Got a MAC address. */
10352183d01SMarcel Moolenaar 				bcopy(LLADDR(sdl), node, UUID_NODE_LEN);
104b30a244cSJeffrey Hsu 				IFNET_RUNLOCK();
10552183d01SMarcel Moolenaar 				return;
10652183d01SMarcel Moolenaar 			}
10752183d01SMarcel Moolenaar 		}
10852183d01SMarcel Moolenaar 	}
109b30a244cSJeffrey Hsu 	IFNET_RUNLOCK();
11052183d01SMarcel Moolenaar 
11152183d01SMarcel Moolenaar 	for (i = 0; i < (UUID_NODE_LEN>>1); i++)
11252183d01SMarcel Moolenaar 		node[i] = (uint16_t)arc4random();
113446655acSRalf S. Engelschall 	*((uint8_t*)node) |= 0x01;
11452183d01SMarcel Moolenaar }
11552183d01SMarcel Moolenaar 
11652183d01SMarcel Moolenaar /*
11752183d01SMarcel Moolenaar  * Get the current time as a 60 bit count of 100-nanosecond intervals
11852183d01SMarcel Moolenaar  * since 00:00:00.00, October 15,1582. We apply a magic offset to convert
11952183d01SMarcel Moolenaar  * the Unix time since 00:00:00.00, Januari 1, 1970 to the date of the
12052183d01SMarcel Moolenaar  * Gregorian reform to the Christian calendar.
12152183d01SMarcel Moolenaar  */
12252183d01SMarcel Moolenaar static uint64_t
12352183d01SMarcel Moolenaar uuid_time(void)
12452183d01SMarcel Moolenaar {
12552183d01SMarcel Moolenaar 	struct bintime bt;
12652183d01SMarcel Moolenaar 	uint64_t time = 0x01B21DD213814000LL;
12752183d01SMarcel Moolenaar 
12852183d01SMarcel Moolenaar 	bintime(&bt);
12952183d01SMarcel Moolenaar 	time += (uint64_t)bt.sec * 10000000LL;
13052183d01SMarcel Moolenaar 	time += (10000000LL * (uint32_t)(bt.frac >> 32)) >> 32;
13152183d01SMarcel Moolenaar 	return (time & ((1LL << 60) - 1LL));
13252183d01SMarcel Moolenaar }
13352183d01SMarcel Moolenaar 
13473130b22SMarcel Moolenaar struct uuid *
13573130b22SMarcel Moolenaar kern_uuidgen(struct uuid *store, size_t count)
13652183d01SMarcel Moolenaar {
13752183d01SMarcel Moolenaar 	struct uuid_private uuid;
13852183d01SMarcel Moolenaar 	uint64_t time;
13973130b22SMarcel Moolenaar 	size_t n;
14052183d01SMarcel Moolenaar 
14152183d01SMarcel Moolenaar 	mtx_lock(&uuid_mutex);
14252183d01SMarcel Moolenaar 
14352183d01SMarcel Moolenaar 	uuid_node(uuid.node);
14452183d01SMarcel Moolenaar 	time = uuid_time();
14552183d01SMarcel Moolenaar 
14652183d01SMarcel Moolenaar 	if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] ||
14752183d01SMarcel Moolenaar 	    uuid_last.node[1] != uuid.node[1] ||
14852183d01SMarcel Moolenaar 	    uuid_last.node[2] != uuid.node[2])
14952183d01SMarcel Moolenaar 		uuid.seq = (uint16_t)arc4random() & 0x3fff;
15052183d01SMarcel Moolenaar 	else if (uuid_last.time.ll >= time)
15152183d01SMarcel Moolenaar 		uuid.seq = (uuid_last.seq + 1) & 0x3fff;
15252183d01SMarcel Moolenaar 	else
15352183d01SMarcel Moolenaar 		uuid.seq = uuid_last.seq;
15452183d01SMarcel Moolenaar 
15552183d01SMarcel Moolenaar 	uuid_last = uuid;
15673130b22SMarcel Moolenaar 	uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL);
15752183d01SMarcel Moolenaar 
15852183d01SMarcel Moolenaar 	mtx_unlock(&uuid_mutex);
15952183d01SMarcel Moolenaar 
16052183d01SMarcel Moolenaar 	/* Set sequence and variant and deal with byte order. */
16152183d01SMarcel Moolenaar 	uuid.seq = htobe16(uuid.seq | 0x8000);
16252183d01SMarcel Moolenaar 
16373130b22SMarcel Moolenaar 	for (n = 0; n < count; n++) {
16473130b22SMarcel Moolenaar 		/* Set time and version (=1). */
16552183d01SMarcel Moolenaar 		uuid.time.x.low = (uint32_t)time;
16652183d01SMarcel Moolenaar 		uuid.time.x.mid = (uint16_t)(time >> 32);
16752183d01SMarcel Moolenaar 		uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12);
16873130b22SMarcel Moolenaar 		store[n] = *(struct uuid *)&uuid;
16952183d01SMarcel Moolenaar 		time++;
17073130b22SMarcel Moolenaar 	}
17152183d01SMarcel Moolenaar 
17273130b22SMarcel Moolenaar 	return (store);
17373130b22SMarcel Moolenaar }
17473130b22SMarcel Moolenaar 
17573130b22SMarcel Moolenaar #ifndef _SYS_SYSPROTO_H_
17673130b22SMarcel Moolenaar struct uuidgen_args {
17773130b22SMarcel Moolenaar 	struct uuid *store;
17873130b22SMarcel Moolenaar 	int	count;
17973130b22SMarcel Moolenaar };
18073130b22SMarcel Moolenaar #endif
18173130b22SMarcel Moolenaar 
18273130b22SMarcel Moolenaar int
18373130b22SMarcel Moolenaar uuidgen(struct thread *td, struct uuidgen_args *uap)
18473130b22SMarcel Moolenaar {
18573130b22SMarcel Moolenaar 	struct uuid *store;
18673130b22SMarcel Moolenaar 	size_t count;
18773130b22SMarcel Moolenaar 	int error;
18873130b22SMarcel Moolenaar 
18973130b22SMarcel Moolenaar 	/*
19073130b22SMarcel Moolenaar 	 * Limit the number of UUIDs that can be created at the same time
19173130b22SMarcel Moolenaar 	 * to some arbitrary number. This isn't really necessary, but I
19273130b22SMarcel Moolenaar 	 * like to have some sort of upper-bound that's less than 2G :-)
19373130b22SMarcel Moolenaar 	 * XXX probably needs to be tunable.
19473130b22SMarcel Moolenaar 	 */
19573130b22SMarcel Moolenaar 	if (uap->count < 1 || uap->count > 2048)
19673130b22SMarcel Moolenaar 		return (EINVAL);
19773130b22SMarcel Moolenaar 
19873130b22SMarcel Moolenaar 	count = uap->count;
19973130b22SMarcel Moolenaar 	store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK);
20073130b22SMarcel Moolenaar 	kern_uuidgen(store, count);
20173130b22SMarcel Moolenaar 	error = copyout(store, uap->store, count * sizeof(struct uuid));
20273130b22SMarcel Moolenaar 	free(store, M_TEMP);
20352183d01SMarcel Moolenaar 	return (error);
20452183d01SMarcel Moolenaar }
20552183d01SMarcel Moolenaar 
20652183d01SMarcel Moolenaar int
20752183d01SMarcel Moolenaar snprintf_uuid(char *buf, size_t sz, struct uuid *uuid)
20852183d01SMarcel Moolenaar {
20952183d01SMarcel Moolenaar 	struct uuid_private *id;
21052183d01SMarcel Moolenaar 	int cnt;
21152183d01SMarcel Moolenaar 
21252183d01SMarcel Moolenaar 	id = (struct uuid_private *)uuid;
21352183d01SMarcel Moolenaar 	cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x",
21452183d01SMarcel Moolenaar 	    id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq),
21552183d01SMarcel Moolenaar 	    be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2]));
21652183d01SMarcel Moolenaar 	return (cnt);
21752183d01SMarcel Moolenaar }
21852183d01SMarcel Moolenaar 
21952183d01SMarcel Moolenaar int
22052183d01SMarcel Moolenaar printf_uuid(struct uuid *uuid)
22152183d01SMarcel Moolenaar {
22252183d01SMarcel Moolenaar 	char buf[38];
22352183d01SMarcel Moolenaar 
22452183d01SMarcel Moolenaar 	snprintf_uuid(buf, sizeof(buf), uuid);
22552183d01SMarcel Moolenaar 	return (printf("%s", buf));
22652183d01SMarcel Moolenaar }
22752183d01SMarcel Moolenaar 
22852183d01SMarcel Moolenaar int
22952183d01SMarcel Moolenaar sbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid)
23052183d01SMarcel Moolenaar {
23152183d01SMarcel Moolenaar 	char buf[38];
23252183d01SMarcel Moolenaar 
23352183d01SMarcel Moolenaar 	snprintf_uuid(buf, sizeof(buf), uuid);
23452183d01SMarcel Moolenaar 	return (sbuf_printf(sb, "%s", buf));
23552183d01SMarcel Moolenaar }
23683133286SPoul-Henning Kamp 
23783133286SPoul-Henning Kamp /*
23883133286SPoul-Henning Kamp  * Encode/Decode UUID into byte-stream.
23983133286SPoul-Henning Kamp  *   http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
24083133286SPoul-Henning Kamp  *
24183133286SPoul-Henning Kamp  * 0                   1                   2                   3
24283133286SPoul-Henning Kamp  *   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
24383133286SPoul-Henning Kamp  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24483133286SPoul-Henning Kamp  *  |                          time_low                             |
24583133286SPoul-Henning Kamp  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24683133286SPoul-Henning Kamp  *  |       time_mid                |         time_hi_and_version   |
24783133286SPoul-Henning Kamp  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24883133286SPoul-Henning Kamp  *  |clk_seq_hi_res |  clk_seq_low  |         node (0-1)            |
24983133286SPoul-Henning Kamp  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25083133286SPoul-Henning Kamp  *  |                         node (2-5)                            |
25183133286SPoul-Henning Kamp  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25283133286SPoul-Henning Kamp  */
25383133286SPoul-Henning Kamp 
25483133286SPoul-Henning Kamp void
25583133286SPoul-Henning Kamp le_uuid_enc(void *buf, struct uuid const *uuid)
25683133286SPoul-Henning Kamp {
25783133286SPoul-Henning Kamp 	u_char *p;
25883133286SPoul-Henning Kamp 	int i;
25983133286SPoul-Henning Kamp 
26083133286SPoul-Henning Kamp 	p = buf;
26183133286SPoul-Henning Kamp 	le32enc(p, uuid->time_low);
26283133286SPoul-Henning Kamp 	le16enc(p + 4, uuid->time_mid);
26383133286SPoul-Henning Kamp 	le16enc(p + 6, uuid->time_hi_and_version);
26483133286SPoul-Henning Kamp 	p[8] = uuid->clock_seq_hi_and_reserved;
26583133286SPoul-Henning Kamp 	p[9] = uuid->clock_seq_low;
26683133286SPoul-Henning Kamp 	for (i = 0; i < _UUID_NODE_LEN; i++)
26783133286SPoul-Henning Kamp 		p[10 + i] = uuid->node[i];
26883133286SPoul-Henning Kamp }
26983133286SPoul-Henning Kamp 
27083133286SPoul-Henning Kamp void
27183133286SPoul-Henning Kamp le_uuid_dec(void const *buf, struct uuid *uuid)
27283133286SPoul-Henning Kamp {
27383133286SPoul-Henning Kamp 	u_char const *p;
27483133286SPoul-Henning Kamp 	int i;
27583133286SPoul-Henning Kamp 
27683133286SPoul-Henning Kamp 	p = buf;
27783133286SPoul-Henning Kamp 	uuid->time_low = le32dec(p);
27883133286SPoul-Henning Kamp 	uuid->time_mid = le16dec(p + 4);
27983133286SPoul-Henning Kamp 	uuid->time_hi_and_version = le16dec(p + 6);
28083133286SPoul-Henning Kamp 	uuid->clock_seq_hi_and_reserved = p[8];
28183133286SPoul-Henning Kamp 	uuid->clock_seq_low = p[9];
28283133286SPoul-Henning Kamp 	for (i = 0; i < _UUID_NODE_LEN; i++)
28383133286SPoul-Henning Kamp 		uuid->node[i] = p[10 + i];
28483133286SPoul-Henning Kamp }
28583133286SPoul-Henning Kamp void
28683133286SPoul-Henning Kamp be_uuid_enc(void *buf, struct uuid const *uuid)
28783133286SPoul-Henning Kamp {
28883133286SPoul-Henning Kamp 	u_char *p;
28983133286SPoul-Henning Kamp 	int i;
29083133286SPoul-Henning Kamp 
29183133286SPoul-Henning Kamp 	p = buf;
29283133286SPoul-Henning Kamp 	be32enc(p, uuid->time_low);
29383133286SPoul-Henning Kamp 	be16enc(p + 4, uuid->time_mid);
29483133286SPoul-Henning Kamp 	be16enc(p + 6, uuid->time_hi_and_version);
29583133286SPoul-Henning Kamp 	p[8] = uuid->clock_seq_hi_and_reserved;
29683133286SPoul-Henning Kamp 	p[9] = uuid->clock_seq_low;
29783133286SPoul-Henning Kamp 	for (i = 0; i < _UUID_NODE_LEN; i++)
29883133286SPoul-Henning Kamp 		p[10 + i] = uuid->node[i];
29983133286SPoul-Henning Kamp }
30083133286SPoul-Henning Kamp 
30183133286SPoul-Henning Kamp void
30283133286SPoul-Henning Kamp be_uuid_dec(void const *buf, struct uuid *uuid)
30383133286SPoul-Henning Kamp {
30483133286SPoul-Henning Kamp 	u_char const *p;
30583133286SPoul-Henning Kamp 	int i;
30683133286SPoul-Henning Kamp 
30783133286SPoul-Henning Kamp 	p = buf;
30883133286SPoul-Henning Kamp 	uuid->time_low = be32dec(p);
30983133286SPoul-Henning Kamp 	uuid->time_mid = le16dec(p + 4);
31083133286SPoul-Henning Kamp 	uuid->time_hi_and_version = be16dec(p + 6);
31183133286SPoul-Henning Kamp 	uuid->clock_seq_hi_and_reserved = p[8];
31283133286SPoul-Henning Kamp 	uuid->clock_seq_low = p[9];
31383133286SPoul-Henning Kamp 	for (i = 0; i < _UUID_NODE_LEN; i++)
31483133286SPoul-Henning Kamp 		uuid->node[i] = p[10 + i];
31583133286SPoul-Henning Kamp }
316