2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
12 #include "../afs/param.h"
14 #include <afs/param.h>
20 #include "../afs/sysincludes.h"
21 #include "../afs/afsincludes.h"
22 #define uuid_memcmp(A,B,C) memcmp(A, B, C)
23 #define uuid_memcpy(A,B,C) memcpy(A, B, C)
32 #include <netinet/in.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
38 #endif /* ITIMER_REAL */
54 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV)
55 #include <netinet/if_ether.h>
59 #define uuid_memcmp(A,B,C) memcmp(A,B,C)
60 #define uuid_memcpy(A,B,C) memcpy(A,B,C)
65 char eaddr[6]; /* 6 bytes of ethernet hardware address */
66 } uuid_address_t, *uuid_address_p_t;
72 } uuid_time_t, *uuid_time_p_t;
74 static int uuid_get_address (uuid_address_p_t addr);
75 void uuid__get_os_time (uuid_time_t *os_time);
78 * |<------------------------- 32 bits -------------------------->|
80 * +--------------------------------------------------------------+
81 * | low 32 bits of time | 0-3 .time_low
82 * +-------------------------------+-------------------------------
83 * | mid 16 bits of time | 4-5 .time_mid
84 * +-------+-----------------------+
85 * | vers. | hi 12 bits of time | 6-7 .time_hi_and_version
86 * +-------+-------+---------------+
87 * |Res| clkSeqHi | 8 .clock_seq_hi_and_reserved
89 * | clkSeqLow | 9 .clock_seq_low
90 * +---------------+----------...-----+
91 * | node ID | 8-16 .node
92 * +--------------------------...-----+
95 afsUUID afs_uuid_g_nil_uuid = { 0 };
96 static uuid_time_t time_now, time_last;
97 static u_short uuid_time_adjust, clock_seq;
98 static afs_uint32 rand_m, rand_ia, rand_ib, rand_irand, uuid_init_done = 0;
100 #define uuid_create_nil(uuid) memset(uuid, 0, sizeof(afsUUID))
101 afs_int32 afs_uuid_equal(u1, u2) afsUUID *u1, *u2; { return(uuid_memcmp((void *)u1, (void *)u2, sizeof (afsUUID)) == 0); }
102 afs_int32 afs_uuid_is_nil(u1) afsUUID *u1; {
104 return(uuid_memcmp((void *)u1, (void *)&afs_uuid_g_nil_uuid, sizeof (afsUUID)) == 0);
108 void afs_htonuuid(uuidp)
110 uuidp->time_low = htonl(uuidp->time_low);
111 uuidp->time_mid = htons(uuidp->time_mid);
112 uuidp->time_hi_and_version = htons(uuidp->time_hi_and_version);
115 void afs_ntohuuid(uuidp)
117 uuidp->time_low = ntohl(uuidp->time_low);
118 uuidp->time_mid = ntohs(uuidp->time_mid);
119 uuidp->time_hi_and_version = ntohs(uuidp->time_hi_and_version);
122 static u_short true_random () {
126 if (rand_m >= 9973) rand_m -= 9871;
127 if (rand_ia >= 99991) rand_ia -= 89989;
128 if (rand_ib >= 224729) rand_ib -= 96233;
129 rand_irand = (rand_irand * rand_m) + rand_ia + rand_ib;
130 return (((rand_irand) >> 16) ^ (rand_irand & 0x3fff));
134 static afs_int32 time_cmp (time1, time2)
136 uuid_time_p_t time2; {
137 if (time1->hi < time2->hi) return (-1);
138 if (time1->hi > time2->hi) return (1);
139 if (time1->lo < time2->lo) return (-1);
140 if (time1->lo > time2->lo) return (1);
144 afs_int32 afs_uuid_create (uuid)
146 uuid_address_t eaddr;
147 afs_int32 got_no_time = 0, code;
149 if (!uuid_init_done) {
151 u_short *seedp, seed=0;
157 * Generating our 'seed' value
159 * We start with the current time, but, since the resolution of clocks is
160 * system hardware dependent (eg. Ultrix is 10 msec.) and most likely
161 * coarser than our resolution (10 usec) we 'mixup' the bits by xor'ing
162 * all the bits together. This will have the effect of involving all of
163 * the bits in the determination of the seed value while remaining system
164 * independent. Then for good measure to ensure a unique seed when there
165 * are multiple processes creating UUID's on a system, we add in the PID.
167 uuid__get_os_time(&t);
168 seedp = (u_short *)(&t);
173 rand_irand += seed + (afs_uint32)getpid();
174 uuid__get_os_time (&time_last);
175 clock_seq = true_random();
177 if (afs_winsockInit()<0) {
178 return WSAGetLastError();
183 if ((code = uuid_get_address (&eaddr))) return code; /* get our hardware network address */
185 /* get the current time */
186 uuid__get_os_time (&time_now);
188 * check that our clock hasn't gone backwards and handle it
189 * accordingly with clock_seq
190 * check that we're not generating uuid's faster than we
191 * can accommodate with our uuid_time_adjust fudge factor
193 if ((code = time_cmp (&time_now, &time_last)) == -1) {
194 /* A clock_seq value of 0 indicates that it hasn't been initialized. */
195 if (clock_seq == 0) {
196 clock_seq = true_random();
198 clock_seq = (clock_seq + 1) & 0x3fff;
199 if (clock_seq == 0) clock_seq = clock_seq + 1;
200 uuid_time_adjust = 0;
201 } else if (code == 1) {
202 uuid_time_adjust = 0;
204 if (uuid_time_adjust == 0x7fff) /* spin while we wait for the clock to tick */
209 } while (got_no_time);
210 time_last.lo = time_now.lo;
211 time_last.hi = time_now.hi;
212 if (uuid_time_adjust != 0) {
213 if (time_now.lo & 0x80000000) {
214 time_now.lo += uuid_time_adjust;
215 if (!(time_now.lo & 0x80000000)) time_now.hi++;
217 time_now.lo += uuid_time_adjust;
219 uuid->time_low = time_now.lo;
220 uuid->time_mid = time_now.hi & 0x0000ffff;
221 uuid->time_hi_and_version = (time_now.hi & 0x0fff0000) >> 16;
222 uuid->time_hi_and_version |= (1 << 12);
223 uuid->clock_seq_low = clock_seq & 0xff;
224 uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3f00) >> 8;
225 uuid->clock_seq_hi_and_reserved |= 0x80;
226 uuid_memcpy ((void *)uuid->node, (void *)&eaddr, sizeof (uuid_address_t));
230 u_short afs_uuid_hash (uuid)
232 short c0=0, c1=0, x, y;
233 char *next_uuid = (char *) uuid;
236 * For speed lets unroll the following loop:
238 * for (i = 0; i < UUID_K_LENGTH; i++)
240 * c0 = c0 + *next_uuid++;
244 c0 = c0 + *next_uuid++;
246 c0 = c0 + *next_uuid++;
248 c0 = c0 + *next_uuid++;
250 c0 = c0 + *next_uuid++;
252 c0 = c0 + *next_uuid++;
254 c0 = c0 + *next_uuid++;
256 c0 = c0 + *next_uuid++;
258 c0 = c0 + *next_uuid++;
260 c0 = c0 + *next_uuid++;
262 c0 = c0 + *next_uuid++;
264 c0 = c0 + *next_uuid++;
266 c0 = c0 + *next_uuid++;
268 c0 = c0 + *next_uuid++;
270 c0 = c0 + *next_uuid++;
272 c0 = c0 + *next_uuid++;
274 c0 = c0 + *next_uuid++;
276 /* Calculate the value for "First octet" of the hash */
281 /* Calculate the value for "second octet" of the hash */
286 return ((y * 256) + x);
291 extern struct interfaceAddr afs_cb_interface;
293 static int uuid_get_address (uuid_address_p_t addr)
295 uuid_memcpy((void *)addr->eaddr, (void *)&afs_cb_interface.addr_in[0], 4);
296 addr->eaddr[4] = 0xaa;
297 addr->eaddr[5] = 0x77;
301 void uuid__get_os_time (uuid_time_t *os_time)
306 os_time->hi = tp.tv_sec;
307 os_time->lo = tp.tv_usec*10;
312 char hostName1[128] = "localhost";
313 static int uuid_get_address (uuid_address_p_t addr)
319 code = gethostname(hostName1, 64);
321 printf("gethostname() failed\n");
328 he = gethostbyname(hostName1);
330 printf("Can't find address for '%s'\n", hostName1);
337 uuid_memcpy(&addr1, he->h_addr_list[0], 4);
338 addr1 = ntohl(addr1);
339 uuid_memcpy(addr->eaddr, &addr1, 4);
340 addr->eaddr[4] = 0xaa;
341 addr->eaddr[5] = 0x77;
343 printf ("uuid_get_address: %02x-%02x-%02x-%02x-%02x-%02x\n",
344 addr->eaddr[0], addr->eaddr[1], addr->eaddr[2],
345 addr->eaddr[3], addr->eaddr[4], addr->eaddr[5]);
351 void uuid__get_os_time (uuid_time_t *os_time)
355 if (gettimeofday (&tp, (struct timezone *) 0)) {
356 perror ("uuid__get_time");
359 os_time->hi = tp.tv_sec;
360 os_time->lo = tp.tv_usec*10;