1 1.20 riastrad /* $NetBSD: kern_uuid.c,v 1.20 2014/10/05 10:00:03 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.20 riastrad __KERNEL_RCSID(0, "$NetBSD: kern_uuid.c,v 1.20 2014/10/05 10:00:03 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.20 riastrad error = copyout(&tmp, store, 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