kern_uuid.c revision 1.19 1 1.19 riastrad /* $NetBSD: kern_uuid.c,v 1.19 2014/10/04 11:15:44 riastradh Exp $ */
2 1.1 tsarna
3 1.1 tsarna /*
4 1.1 tsarna * Copyright (c) 2002 Marcel Moolenaar
5 1.1 tsarna * All rights reserved.
6 1.1 tsarna *
7 1.1 tsarna * Redistribution and use in source and binary forms, with or without
8 1.1 tsarna * modification, are permitted provided that the following conditions
9 1.1 tsarna * are met:
10 1.1 tsarna *
11 1.1 tsarna * 1. Redistributions of source code must retain the above copyright
12 1.1 tsarna * notice, this list of conditions and the following disclaimer.
13 1.1 tsarna * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 tsarna * notice, this list of conditions and the following disclaimer in the
15 1.1 tsarna * documentation and/or other materials provided with the distribution.
16 1.1 tsarna *
17 1.1 tsarna * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 1.1 tsarna * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 1.1 tsarna * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.1 tsarna * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 1.1 tsarna * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 1.1 tsarna * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 1.1 tsarna * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 1.1 tsarna * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 1.1 tsarna * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 1.1 tsarna * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.2 thorpej *
28 1.2 thorpej * $FreeBSD: /repoman/r/ncvs/src/sys/kern/kern_uuid.c,v 1.7 2004/01/12 13:34:11 rse Exp $
29 1.1 tsarna */
30 1.1 tsarna
31 1.1 tsarna #include <sys/cdefs.h>
32 1.19 riastrad __KERNEL_RCSID(0, "$NetBSD: kern_uuid.c,v 1.19 2014/10/04 11:15:44 riastradh Exp $");
33 1.1 tsarna
34 1.1 tsarna #include <sys/param.h>
35 1.19 riastrad #include <sys/cprng.h>
36 1.1 tsarna #include <sys/endian.h>
37 1.19 riastrad #include <sys/syscallargs.h>
38 1.1 tsarna #include <sys/systm.h>
39 1.1 tsarna #include <sys/uuid.h>
40 1.1 tsarna
41 1.1 tsarna /*
42 1.1 tsarna * See also:
43 1.1 tsarna * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
44 1.1 tsarna * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
45 1.1 tsarna */
46 1.1 tsarna
47 1.1 tsarna CTASSERT(sizeof(struct uuid) == 16);
48 1.1 tsarna
49 1.2 thorpej static void
50 1.19 riastrad uuid_generate(struct uuid *uuid)
51 1.2 thorpej {
52 1.2 thorpej
53 1.19 riastrad /* Randomly generate the content. */
54 1.19 riastrad cprng_fast(uuid, sizeof(*uuid));
55 1.2 thorpej
56 1.19 riastrad /* Set the version number to 4. */
57 1.19 riastrad uuid->time_hi_and_version &= ~(uint32_t)0xf000;
58 1.19 riastrad uuid->time_hi_and_version |= 0x4000;
59 1.2 thorpej
60 1.19 riastrad /* Fix the reserved bits. */
61 1.19 riastrad uuid->clock_seq_hi_and_reserved &= ~(uint8_t)0x40;
62 1.19 riastrad uuid->clock_seq_hi_and_reserved |= 0x80;
63 1.16 joerg }
64 1.16 joerg
65 1.16 joerg int
66 1.16 joerg sys_uuidgen(struct lwp *l, const struct sys_uuidgen_args *uap, register_t *retval)
67 1.16 joerg {
68 1.19 riastrad struct uuid *store, tmp;
69 1.19 riastrad unsigned count;
70 1.19 riastrad int error;
71 1.19 riastrad
72 1.16 joerg /*
73 1.16 joerg * Limit the number of UUIDs that can be created at the same time
74 1.16 joerg * to some arbitrary number. This isn't really necessary, but I
75 1.16 joerg * like to have some sort of upper-bound that's less than 2G :-)
76 1.16 joerg * XXX needs to be tunable.
77 1.16 joerg */
78 1.16 joerg if (SCARG(uap,count) < 1 || SCARG(uap,count) > 2048)
79 1.16 joerg return (EINVAL);
80 1.16 joerg
81 1.19 riastrad for (store = SCARG(uap,store), count = SCARG(uap,count);
82 1.19 riastrad count > 0;
83 1.19 riastrad store++, count--) {
84 1.19 riastrad uuid_generate(&tmp);
85 1.19 riastrad error = copyout(store, &tmp, sizeof tmp);
86 1.19 riastrad if (error)
87 1.19 riastrad return error;
88 1.19 riastrad }
89 1.19 riastrad
90 1.19 riastrad return 0;
91 1.16 joerg }
92 1.16 joerg
93 1.16 joerg int
94 1.16 joerg uuidgen(struct uuid *store, int count)
95 1.16 joerg {
96 1.19 riastrad
97 1.19 riastrad while (--count > 0)
98 1.19 riastrad uuid_generate(store++);
99 1.19 riastrad return 0;
100 1.1 tsarna }
101 1.1 tsarna
102 1.1 tsarna int
103 1.2 thorpej uuid_snprintf(char *buf, size_t sz, const struct uuid *uuid)
104 1.1 tsarna {
105 1.1 tsarna
106 1.19 riastrad return snprintf(buf, sz,
107 1.19 riastrad "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
108 1.19 riastrad uuid->time_low, uuid->time_mid, uuid->time_hi_and_version,
109 1.19 riastrad uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low,
110 1.19 riastrad uuid->node[0], uuid->node[1], uuid->node[2], uuid->node[3],
111 1.19 riastrad uuid->node[4], uuid->node[5]);
112 1.1 tsarna }
113 1.1 tsarna
114 1.1 tsarna int
115 1.2 thorpej uuid_printf(const struct uuid *uuid)
116 1.1 tsarna {
117 1.2 thorpej char buf[UUID_STR_LEN];
118 1.1 tsarna
119 1.2 thorpej (void) uuid_snprintf(buf, sizeof(buf), uuid);
120 1.1 tsarna printf("%s", buf);
121 1.2 thorpej return (0);
122 1.1 tsarna }
123 1.1 tsarna
124 1.1 tsarna /*
125 1.2 thorpej * Encode/Decode UUID into octet-stream.
126 1.1 tsarna * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
127 1.1 tsarna *
128 1.1 tsarna * 0 1 2 3
129 1.1 tsarna * 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
130 1.1 tsarna * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 1.1 tsarna * | time_low |
132 1.1 tsarna * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 1.1 tsarna * | time_mid | time_hi_and_version |
134 1.1 tsarna * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 1.1 tsarna * |clk_seq_hi_res | clk_seq_low | node (0-1) |
136 1.1 tsarna * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137 1.1 tsarna * | node (2-5) |
138 1.1 tsarna * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139 1.1 tsarna */
140 1.1 tsarna
141 1.1 tsarna void
142 1.2 thorpej uuid_enc_le(void *buf, const struct uuid *uuid)
143 1.1 tsarna {
144 1.2 thorpej uint8_t *p = buf;
145 1.1 tsarna int i;
146 1.1 tsarna
147 1.1 tsarna le32enc(p, uuid->time_low);
148 1.1 tsarna le16enc(p + 4, uuid->time_mid);
149 1.1 tsarna le16enc(p + 6, uuid->time_hi_and_version);
150 1.1 tsarna p[8] = uuid->clock_seq_hi_and_reserved;
151 1.1 tsarna p[9] = uuid->clock_seq_low;
152 1.1 tsarna for (i = 0; i < _UUID_NODE_LEN; i++)
153 1.1 tsarna p[10 + i] = uuid->node[i];
154 1.1 tsarna }
155 1.1 tsarna
156 1.1 tsarna void
157 1.2 thorpej uuid_dec_le(void const *buf, struct uuid *uuid)
158 1.1 tsarna {
159 1.2 thorpej const uint8_t *p = buf;
160 1.1 tsarna int i;
161 1.1 tsarna
162 1.1 tsarna uuid->time_low = le32dec(p);
163 1.1 tsarna uuid->time_mid = le16dec(p + 4);
164 1.1 tsarna uuid->time_hi_and_version = le16dec(p + 6);
165 1.1 tsarna uuid->clock_seq_hi_and_reserved = p[8];
166 1.1 tsarna uuid->clock_seq_low = p[9];
167 1.1 tsarna for (i = 0; i < _UUID_NODE_LEN; i++)
168 1.1 tsarna uuid->node[i] = p[10 + i];
169 1.1 tsarna }
170 1.2 thorpej
171 1.1 tsarna void
172 1.2 thorpej uuid_enc_be(void *buf, const struct uuid *uuid)
173 1.1 tsarna {
174 1.2 thorpej uint8_t *p = buf;
175 1.1 tsarna int i;
176 1.1 tsarna
177 1.1 tsarna be32enc(p, uuid->time_low);
178 1.1 tsarna be16enc(p + 4, uuid->time_mid);
179 1.1 tsarna be16enc(p + 6, uuid->time_hi_and_version);
180 1.1 tsarna p[8] = uuid->clock_seq_hi_and_reserved;
181 1.1 tsarna p[9] = uuid->clock_seq_low;
182 1.1 tsarna for (i = 0; i < _UUID_NODE_LEN; i++)
183 1.1 tsarna p[10 + i] = uuid->node[i];
184 1.1 tsarna }
185 1.1 tsarna
186 1.1 tsarna void
187 1.2 thorpej uuid_dec_be(void const *buf, struct uuid *uuid)
188 1.1 tsarna {
189 1.2 thorpej const uint8_t *p = buf;
190 1.1 tsarna int i;
191 1.1 tsarna
192 1.1 tsarna uuid->time_low = be32dec(p);
193 1.14 plunky uuid->time_mid = be16dec(p + 4);
194 1.1 tsarna uuid->time_hi_and_version = be16dec(p + 6);
195 1.1 tsarna uuid->clock_seq_hi_and_reserved = p[8];
196 1.1 tsarna uuid->clock_seq_low = p[9];
197 1.1 tsarna for (i = 0; i < _UUID_NODE_LEN; i++)
198 1.1 tsarna uuid->node[i] = p[10 + i];
199 1.1 tsarna }
200