]> git.saurik.com Git - apple/cf.git/blob - Base.subproj/uuid.c
CF-368.18.tar.gz
[apple/cf.git] / Base.subproj / uuid.c
1 /*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* uuid.c
24 Copyright 1999-2002, Apple, Inc. All rights reserved.
25 Responsibility: Doug Davidson
26 */
27
28 #include <CoreFoundation/CFBase.h>
29 #include <CoreFoundation/CFDate.h>
30 #include "CFInternal.h"
31 #include "CFUtilitiesPriv.h"
32 #include <string.h>
33
34 typedef struct
35 {
36 unsigned char eaddr[6]; /* 6 bytes of ethernet hardware address */
37 } uuid_address_t;
38
39 #if defined(__WIN32__)
40
41 static OSErr GetEthernetAddr(uuid_address_t *addr) {
42 return -1;
43 }
44
45 #else
46
47 #include <unistd.h>
48 #include <stdio.h>
49 #include <sys/socket.h>
50 #include <sys/ioctl.h>
51 #include <sys/sockio.h>
52 #include <sys/uio.h>
53 #include <sys/errno.h>
54
55 #include <netinet/in.h>
56 #include <net/if.h>
57 #include <net/if_dl.h>
58 #include <net/if_types.h>
59
60 #if !defined(MAX)
61 #define MAX(a, b) ((a) < (b) ? (b) : (a))
62 #endif
63
64 #define IFR_NEXT(ifr) \
65 ((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
66 MAX(0, (int) (ifr)->ifr_addr.sa_len - (int) sizeof((ifr)->ifr_addr))))
67
68 static OSErr GetEthernetAddr(uuid_address_t *addr) {
69 struct ifconf ifc;
70 struct ifreq ifrbuf[30], *ifr;
71 register int s, i;
72 Boolean foundIt = false;
73
74 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
75 return -1;
76 }
77
78 ifc.ifc_buf = (caddr_t)ifrbuf;
79 ifc.ifc_len = sizeof (ifrbuf);
80 if (ioctl(s, SIOCGIFCONF, &ifc) == -1) {
81 close(s);
82 return -1;
83 }
84
85 for (ifr = (struct ifreq *)ifc.ifc_buf, i=0; (char *)ifr < &ifc.ifc_buf[ifc.ifc_len]; ifr = IFR_NEXT(ifr), i++) {
86 unsigned char *p, c;
87
88 if (*ifr->ifr_name == '\0') {
89 continue;
90 }
91 /*
92 * Adapt to buggy kernel implementation (> 9 of a type)
93 */
94
95 p = &ifr->ifr_name[strlen(ifr->ifr_name)-1];
96 if ((c = *p) > '0'+9) {
97 snprintf(p, 2, "%d", c-'0'); // at least 3 bytes available here, we hope!
98 }
99
100 if (strcmp(ifr->ifr_name, "en0") == 0) {
101 if (ifr->ifr_addr.sa_family == AF_LINK) {
102 struct sockaddr_dl *sa = ((struct sockaddr_dl *)&ifr->ifr_addr);
103 if (sa->sdl_type == IFT_ETHER || sa->sdl_type == IFT_FDDI || sa->sdl_type == IFT_ISO88023 || sa->sdl_type == IFT_ISO88024 || sa->sdl_type == IFT_ISO88025) {
104 for (i=0, p=&sa->sdl_data[sa->sdl_nlen] ; i++ < sa->sdl_alen; p++) {
105 addr->eaddr[i-1] = *p;
106 }
107 foundIt = true;
108 break;
109 }
110 }
111 }
112 }
113 close(s);
114 return (foundIt ? 0 : -1);
115 }
116
117 #undef IFR_NEXT
118
119 #endif // __WIN32__
120
121 __private_extern__ CFStringRef __CFCopyRegularEthernetAddrString(void) {
122 uuid_address_t addr;
123 static CFStringRef string = NULL;
124 static Boolean lookedUpAddr = false;
125
126 if (!lookedUpAddr) {
127 if (GetEthernetAddr(&addr) == 0) {
128 string = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), addr.eaddr[0], addr.eaddr[1], addr.eaddr[2], addr.eaddr[3], addr.eaddr[4], addr.eaddr[5]);
129 }
130 lookedUpAddr = true;
131 }
132 return (string ? CFRetain(string) : NULL);
133 }
134
135 __private_extern__ CFStringRef __CFCopyEthernetAddrString(void) {
136 uuid_address_t addr;
137 static CFStringRef string = NULL;
138 static Boolean lookedUpAddr = false;
139
140 if (!lookedUpAddr) {
141 if (GetEthernetAddr(&addr) == 0) {
142 string = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x%02x%02x%02x%02x%02x"), addr.eaddr[0], addr.eaddr[1], addr.eaddr[2], addr.eaddr[3], addr.eaddr[4], addr.eaddr[5]);
143 }
144 lookedUpAddr = true;
145 }
146 return (string ? CFRetain(string) : NULL);
147 }
148
149 #if defined(__WIN32__)
150 /* _CFGenerateUUID function just calls the COM library's UUID generator
151 * (Aleksey Dukhnyakov)
152 */
153 #include <windows.h>
154 #include <ole2.h>
155 #include <objbase.h>
156
157 LONG _CFGenerateUUID(uint8_t *uuid_bytes) {
158 RPC_STATUS rStatus;
159
160 /* call GetScode() function to get RPC_STATUS, because
161 * CoCreateGuid(uuid) function return HRESULT type
162 */
163 rStatus = GetScode(CoCreateGuid((uuid_t *)uuid_bytes));
164
165 /* We accept only following results RPC_S_OK, RPC_S_UUID_LOCAL_ONLY
166 */
167 if ( rStatus == RPC_S_UUID_NO_ADDRESS)
168 return rStatus;
169
170 return 0;
171 };
172
173 #else
174
175 /* uuid.c
176 *
177 * Modifications made by William Woody to make this thing
178 * work on the Macintosh.
179 */
180
181 /*
182 *
183 * (c) Copyright 1989 OPEN SOFTWARE FOUNDATION, INC.
184 * (c) Copyright 1989 HEWLETT-PACKARD COMPANY
185 * (c) Copyright 1989 DIGITAL EQUIPMENT CORPORATION
186 * To anyone who acknowledges that this file is provided "AS IS"
187 * without any express or implied warranty:
188 * permission to use, copy, modify, and distribute this
189 * file for any purpose is hereby granted without fee, provided that
190 * the above copyright notices and this notice appears in all source
191 * code copies, and that none of the names of Open Software
192 * Foundation, Inc., Hewlett-Packard Company, or Digital Equipment
193 * Corporation be used in advertising or publicity pertaining to
194 * distribution of the software without specific, written prior
195 * permission. Neither Open Software Foundation, Inc., Hewlett-
196 * Packard Company, nor Digital Equipment Corporation makes any
197 * representations about the suitability of this software for any
198 * purpose.
199 *
200 */
201 /*
202 */
203 /*
204 **
205 ** NAME:
206 **
207 ** uuid.c
208 **
209 ** FACILITY:
210 **
211 ** UUID
212 **
213 ** ABSTRACT:
214 **
215 ** UUID - routines that manipulate uuid's
216 **
217 **
218 */
219
220
221 /* uuid
222 *
223 * Universal Unique ID. Note this definition will result is a 16-byte
224 * structure regardless what platform it is on.
225 */
226
227 struct uuid_v1_t {
228 uint32_t time_low;
229 uint16_t time_mid;
230 uint16_t time_hi_and_version;
231 unsigned char clock_seq_hi_and_reserved;
232 unsigned char clock_seq_low;
233 unsigned char node[6];
234 };
235
236 typedef struct uuid_v1_t uuid_v1_t;
237
238 enum {
239 kUUIDInternalError = -21001,
240 kUUIDInvalidString = -21002
241 };
242
243 typedef struct {
244 uint32_t lo;
245 uint32_t hi;
246 } uuid_time_t;
247
248 static OSErr GenRandomEthernet(uuid_address_t *addr);
249 static OSErr ReadPrefData(void);
250
251 /*
252 * Preferences file management
253 */
254
255 static uuid_address_t GSavedENetAddr = {{0, 0, 0, 0, 0, 0}};
256 static uuid_time_t GLastTime = {0, 0}; /* Clock state info */
257 static uint16_t GTimeAdjust = 0;
258 static uint16_t GClockSeq = 0;
259
260
261 /*
262 * Internal structure of universal unique IDs (UUIDs).
263 *
264 * There are three "variants" of UUIDs that this code knows about. The
265 * variant #0 is what was defined in the 1989 HP/Apollo Network Computing
266 * Architecture (NCA) specification and implemented in NCS 1.x and DECrpc
267 * v1. Variant #1 is what was defined for the joint HP/DEC specification
268 * for the OSF (in DEC's "UID Architecture Functional Specification Version
269 * X1.0.4") and implemented in NCS 2.0, DECrpc v2, and OSF 1.0 DCE RPC.
270 * Variant #2 is defined by Microsoft.
271 *
272 * This code creates only variant #1 UUIDs.
273 *
274 * The three UUID variants can exist on the same wire because they have
275 * distinct values in the 3 MSB bits of octet 8 (see table below). Do
276 * NOT confuse the version number with these 3 bits. (Note the distinct
277 * use of the terms "version" and "variant".) Variant #0 had no version
278 * field in it. Changes to variant #1 (should any ever need to be made)
279 * can be accomodated using the current form's 4 bit version field.
280 *
281 * The UUID record structure MUST NOT contain padding between fields.
282 * The total size = 128 bits.
283 *
284 * To minimize confusion about bit assignment within octets, the UUID
285 * record definition is defined only in terms of fields that are integral
286 * numbers of octets.
287 *
288 * Depending on the network data representation, the multi-octet unsigned
289 * integer fields are subject to byte swapping when communicated between
290 * dissimilar endian machines. Note that all three UUID variants have
291 * the same record structure; this allows this byte swapping to occur.
292 * (The ways in which the contents of the fields are generated can and
293 * do vary.)
294 *
295 * The following information applies to variant #1 UUIDs:
296 *
297 * The lowest addressed octet contains the global/local bit and the
298 * unicast/multicast bit, and is the first octet of the address transmitted
299 * on an 802.3 LAN.
300 *
301 * The adjusted time stamp is split into three fields, and the clockSeq
302 * is split into two fields.
303 *
304 * |<------------------------- 32 bits -------------------------->|
305 *
306 * +--------------------------------------------------------------+
307 * | low 32 bits of time | 0-3 .time_low
308 * +-------------------------------+-------------------------------
309 * | mid 16 bits of time | 4-5 .time_mid
310 * +-------+-----------------------+
311 * | vers. | hi 12 bits of time | 6-7 .time_hi_and_version
312 * +-------+-------+---------------+
313 * |Res| clkSeqHi | 8 .clock_seq_hi_and_reserved
314 * +---------------+
315 * | clkSeqLow | 9 .clock_seq_low
316 * +---------------+----------...-----+
317 * | node ID | 8-16 .node
318 * +--------------------------...-----+
319 *
320 * --------------------------------------------------------------------------
321 *
322 * The structure layout of all three UUID variants is fixed for all time.
323 * I.e., the layout consists of a 32 bit int, 2 16 bit ints, and 8 8
324 * bit ints. The current form version field does NOT determine/affect
325 * the layout. This enables us to do certain operations safely on the
326 * variants of UUIDs without regard to variant; this increases the utility
327 * of this code even as the version number changes (i.e., this code does
328 * NOT need to check the version field).
329 *
330 * The "Res" field in the octet #8 is the so-called "reserved" bit-field
331 * and determines whether or not the uuid is a old, current or other
332 * UUID as follows:
333 *
334 * MS-bit 2MS-bit 3MS-bit Variant
335 * ---------------------------------------------
336 * 0 x x 0 (NCS 1.5)
337 * 1 0 x 1 (DCE 1.0 RPC)
338 * 1 1 0 2 (Microsoft)
339 * 1 1 1 unspecified
340 *
341 * --------------------------------------------------------------------------
342 *
343 * Internal structure of variant #0 UUIDs
344 *
345 * The first 6 octets are the number of 4 usec units of time that have
346 * passed since 1/1/80 0000 GMT. The next 2 octets are reserved for
347 * future use. The next octet is an address family. The next 7 octets
348 * are a host ID in the form allowed by the specified address family.
349 *
350 * Note that while the family field (octet 8) was originally conceived
351 * of as being able to hold values in the range [0..255], only [0..13]
352 * were ever used. Thus, the 2 MSB of this field are always 0 and are
353 * used to distinguish old and current UUID forms.
354 *
355 * +--------------------------------------------------------------+
356 * | high 32 bits of time | 0-3 .time_high
357 * +-------------------------------+-------------------------------
358 * | low 16 bits of time | 4-5 .time_low
359 * +-------+-----------------------+
360 * | reserved | 6-7 .reserved
361 * +---------------+---------------+
362 * | family | 8 .family
363 * +---------------+----------...-----+
364 * | node ID | 9-16 .node
365 * +--------------------------...-----+
366 *
367 */
368
369 /***************************************************************************
370 *
371 * Local definitions
372 *
373 **************************************************************************/
374
375 static const long uuid_c_version = 1;
376
377 /*
378 * local defines used in uuid bit-diddling
379 */
380 #define HI_WORD(w) ((w) >> 16)
381 #define RAND_MASK 0x3fff /* same as CLOCK_SEQ_LAST */
382
383 #define TIME_MID_MASK 0x0000ffff
384 #define TIME_HIGH_MASK 0x0fff0000
385 #define TIME_HIGH_SHIFT_COUNT 16
386
387 /*
388 * The following was modified in order to prevent overlap because
389 * our clock is (theoretically) accurate to 1us (or 1s in CarbonLib)
390 */
391
392
393 #define MAX_TIME_ADJUST 9 /* Max adjust before tick */
394
395 #define CLOCK_SEQ_LOW_MASK 0xff
396 #define CLOCK_SEQ_HIGH_MASK 0x3f00
397 #define CLOCK_SEQ_HIGH_SHIFT_COUNT 8
398 #define CLOCK_SEQ_FIRST 1
399 #define CLOCK_SEQ_LAST 0x3fff /* same as RAND_MASK */
400
401 /*
402 * Note: If CLOCK_SEQ_BIT_BANG == true, then we can avoid the modulo
403 * operation. This should save us a divide instruction and speed
404 * things up.
405 */
406
407 #ifndef CLOCK_SEQ_BIT_BANG
408 #define CLOCK_SEQ_BIT_BANG 1
409 #endif
410
411 #if CLOCK_SEQ_BIT_BANG
412 #define CLOCK_SEQ_BUMP(seq) ((*seq) = ((*seq) + 1) & CLOCK_SEQ_LAST)
413 #else
414 #define CLOCK_SEQ_BUMP(seq) ((*seq) = ((*seq) + 1) % (CLOCK_SEQ_LAST+1))
415 #endif
416
417 #define UUID_VERSION_BITS (uuid_c_version << 12)
418 #define UUID_RESERVED_BITS 0x80
419
420 #define IS_OLD_UUID(uuid) (((uuid)->clock_seq_hi_and_reserved & 0xc0) != 0x80)
421
422 /****************************************************************************
423 *
424 * local data declarations
425 *
426 ****************************************************************************/
427
428 typedef struct {
429 uint32_t lo;
430 uint32_t hi;
431 } unsigned64_t;
432
433 /*
434 * declarations used in UTC time calculations
435 */
436
437 static uuid_time_t time_now = {0, 0}; /* utc time as of last query */
438 //static uuid_time_t time_last; /* utc time last time I looked */
439 //static uint16_t time_adjust; /* 'adjustment' to ensure uniqness */
440 //static uint16_t clock_seq; /* 'adjustment' for backwards clocks*/
441
442 /*
443 * true_random variables
444 */
445
446 static uint32_t rand_m = 0; /* multiplier */
447 static uint32_t rand_ia = 0; /* adder #1 */
448 static uint32_t rand_ib = 0; /* adder #2 */
449 static uint32_t rand_irand = 0; /* random value */
450
451 typedef enum
452 {
453 uuid_e_less_than, uuid_e_equal_to, uuid_e_greater_than
454 } uuid_compval_t;
455
456
457
458
459 /****************************************************************************
460 *
461 * local function declarations
462 *
463 ****************************************************************************/
464
465 /*
466 * I N I T
467 *
468 * Startup initialization routine for UUID module.
469 */
470
471 static OSErr init (void);
472
473 /*
474 * T R U E _ R A N D O M _ I N I T
475 */
476
477 static void true_random_init (void);
478
479 /*
480 * T R U E _ R A N D O M
481 */
482 static uint16_t true_random (void);
483
484
485 /*
486 * N E W _ C L O C K _ S E Q
487 *
488 * Ensure clock_seq is up-to-date
489 *
490 * Note: clock_seq is architected to be 14-bits (unsigned) but
491 * I've put it in here as 16-bits since there isn't a
492 * 14-bit unsigned integer type (yet)
493 */
494 static void new_clock_seq ( uint16_t * /*clock_seq*/);
495
496
497 /*
498 * T I M E _ C M P
499 *
500 * Compares two UUID times (64-bit DEC UID UTC values)
501 */
502 static uuid_compval_t time_cmp (
503 uuid_time_t * /*time1*/,
504 uuid_time_t * /*time2*/
505 );
506
507
508 /************************************************************************/
509 /* */
510 /* New Routines */
511 /* */
512 /************************************************************************/
513
514 /*
515 * saved copy of our IEEE 802 address for quick reference
516 */
517
518 static uuid_address_t saved_addr = {{0, 0, 0, 0, 0, 0}};
519 static int got_address = false;
520 static int last_addr_result = false;
521
522 static OSErr GenRandomEthernet(uuid_address_t *addr) {
523 unsigned int i;
524 for (i = 0; i < 6; i++) {
525 addr->eaddr[i] = (unsigned char)(true_random() & 0xff);
526 }
527 return 0;
528 }
529
530 /*
531 **++
532 **
533 ** ROUTINE NAME: uuid_get_address
534 **
535 ** SCOPE: PUBLIC
536 **
537 ** DESCRIPTION:
538 **
539 ** Return our IEEE 802 address.
540 **
541 ** This function is not really "public", but more like the SPI functions
542 ** -- available but not part of the official API. We've done this so
543 ** that other subsystems (of which there are hopefully few or none)
544 ** that need the IEEE 802 address can use this function rather than
545 ** duplicating the gore it does (or more specifically, the gore that
546 ** "uuid__get_os_address" does).
547 **
548 ** INPUTS: none
549 **
550 ** INPUTS/OUTPUTS: none
551 **
552 ** OUTPUTS:
553 **
554 ** addr IEEE 802 address
555 **
556 ** status return status value
557 **
558 ** IMPLICIT INPUTS: none
559 **
560 ** IMPLICIT OUTPUTS: none
561 **
562 ** FUNCTION VALUE: none
563 **
564 ** SIDE EFFECTS: none
565 **
566 **--
567 **/
568
569 static int uuid_get_address(uuid_address_t *addr)
570 {
571
572 /*
573 * just return address we determined previously if we've
574 * already got one
575 */
576
577 if (got_address) {
578 memmove (addr, &saved_addr, sizeof (uuid_address_t));
579 return last_addr_result;
580 }
581
582 /*
583 * Otherwise, call the system specific routine.
584 */
585
586 last_addr_result = GetEthernetAddr(addr);
587
588 /*
589 * Was this an error? If so, I need to generate a random
590 * sequence to use in place of an Ethernet address.
591 */
592 if (last_addr_result) {
593 last_addr_result = GenRandomEthernet(addr);
594 }
595
596 got_address = true;
597 if (last_addr_result == 0) {
598 /* On no error copy */
599 memmove (&saved_addr, addr, sizeof (uuid_address_t));
600 }
601 return last_addr_result;
602 }
603
604 /*****************************************************************************
605 *
606 * Macro definitions
607 *
608 ****************************************************************************/
609
610 /*
611 * ensure we've been initialized
612 */
613 static int uuid_init_done = false;
614
615 #define EmptyArg
616 #define UUID_VERIFY_INIT(Arg) \
617 if (! uuid_init_done) \
618 { \
619 init (status); \
620 if (*status != uuid_s_ok) \
621 { \
622 return Arg; \
623 } \
624 }
625
626 /*
627 * Check the reserved bits to make sure the UUID is of the known structure.
628 */
629
630 #define CHECK_STRUCTURE(uuid) \
631 ( \
632 (((uuid)->clock_seq_hi_and_reserved & 0x80) == 0x00) || /* var #0 */ \
633 (((uuid)->clock_seq_hi_and_reserved & 0xc0) == 0x80) || /* var #1 */ \
634 (((uuid)->clock_seq_hi_and_reserved & 0xe0) == 0xc0) /* var #2 */ \
635 )
636
637 /*
638 * The following macros invoke CHECK_STRUCTURE(), check that the return
639 * value is okay and if not, they set the status variable appropriately
640 * and return either a boolean false, nothing (for void procedures),
641 * or a value passed to the macro. This has been done so that checking
642 * can be done more simply and values are returned where appropriate
643 * to keep compilers happy.
644 *
645 * bCHECK_STRUCTURE - returns boolean false
646 * vCHECK_STRUCTURE - returns nothing (void)
647 * rCHECK_STRUCTURE - returns 'r' macro parameter
648 */
649
650 #define bCHECK_STRUCTURE(uuid, status) \
651 { \
652 if (!CHECK_STRUCTURE (uuid)) \
653 { \
654 *(status) = uuid_s_bad_version; \
655 return (false); \
656 } \
657 }
658
659 #define vCHECK_STRUCTURE(uuid, status) \
660 { \
661 if (!CHECK_STRUCTURE (uuid)) \
662 { \
663 *(status) = uuid_s_bad_version; \
664 return; \
665 } \
666 }
667
668 #define rCHECK_STRUCTURE(uuid, status, result) \
669 { \
670 if (!CHECK_STRUCTURE (uuid)) \
671 { \
672 *(status) = uuid_s_bad_version; \
673 return (result); \
674 } \
675 }
676
677
678 /*
679 * Define constant designation difference in Unix and DTSS base times:
680 * DTSS UTC base time is October 15, 1582.
681 * Unix base time is January 1, 1970.
682 */
683 #define uuid_c_os_base_time_diff_lo 0x13814000
684 #define uuid_c_os_base_time_diff_hi 0x01B21DD2
685
686 #ifndef UUID_C_100NS_PER_SEC
687 #define UUID_C_100NS_PER_SEC 10000000
688 #endif
689
690 #ifndef UUID_C_100NS_PER_USEC
691 #define UUID_C_100NS_PER_USEC 10
692 #endif
693
694
695
696
697
698 /*
699 * UADD_UVLW_2_UVLW - macro to add two unsigned 64-bit long integers
700 * (ie. add two unsigned 'very' long words)
701 *
702 * Important note: It is important that this macro accommodate (and it does)
703 * invocations where one of the addends is also the sum.
704 *
705 * This macro was snarfed from the DTSS group and was originally:
706 *
707 * UTCadd - macro to add two UTC times
708 *
709 * add lo and high order longword separately, using sign bits of the low-order
710 * longwords to determine carry. sign bits are tested before addition in two
711 * cases - where sign bits match. when the addend sign bits differ the sign of
712 * the result is also tested:
713 *
714 * sign sign
715 * addend 1 addend 2 carry?
716 *
717 * 1 1 true
718 * 1 0 true if sign of sum clear
719 * 0 1 true if sign of sum clear
720 * 0 0 false
721 */
722 #define UADD_UVLW_2_UVLW(add1, add2, sum) \
723 if (!(((add1)->lo&0x80000000UL) ^ ((add2)->lo&0x80000000UL))) \
724 { \
725 if (((add1)->lo&0x80000000UL)) \
726 { \
727 (sum)->lo = (add1)->lo + (add2)->lo ; \
728 (sum)->hi = (add1)->hi + (add2)->hi+1 ; \
729 } \
730 else \
731 { \
732 (sum)->lo = (add1)->lo + (add2)->lo ; \
733 (sum)->hi = (add1)->hi + (add2)->hi ; \
734 } \
735 } \
736 else \
737 { \
738 (sum)->lo = (add1)->lo + (add2)->lo ; \
739 (sum)->hi = (add1)->hi + (add2)->hi ; \
740 if (!((sum)->lo&0x80000000UL)) \
741 (sum)->hi++ ; \
742 }
743
744 /*
745 * UADD_UW_2_UVLW - macro to add a 16-bit unsigned integer to
746 * a 64-bit unsigned integer
747 *
748 * Note: see the UADD_UVLW_2_UVLW() macro
749 *
750 */
751 #define UADD_UW_2_UVLW(add1, add2, sum) \
752 { \
753 (sum)->hi = (add2)->hi; \
754 if ((add2)->lo & 0x80000000UL) \
755 { \
756 (sum)->lo = (*add1) + (add2)->lo; \
757 if (!((sum)->lo & 0x80000000UL)) \
758 { \
759 (sum)->hi++; \
760 } \
761 } \
762 else \
763 { \
764 (sum)->lo = (*add1) + (add2)->lo; \
765 } \
766 }
767
768 /*
769 * U U I D _ _ G E T _ O S _ T I M E
770 *
771 * Get OS time - contains platform-specific code.
772 */
773
774 static const double utc_conversion_factor = 429.4967296; // 2^32 / 10^7
775
776 static void uuid__get_os_time (uuid_time_t * uuid_time)
777 {
778 unsigned64_t utc,
779 os_basetime_diff;
780 CFAbsoluteTime at = CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
781 double utc_at = at / utc_conversion_factor;
782
783 /* Convert 'at' in double seconds to 100ns units in utc */
784 utc.hi = (uint32_t)utc_at;
785 utc_at -= (double)utc.hi;
786 utc_at *= utc_conversion_factor;
787 utc_at *= 10000000.0;
788 utc.lo = (uint32_t)utc_at;
789
790 /*
791 * Offset between DTSS formatted times and Unix formatted times.
792 */
793 os_basetime_diff.lo = uuid_c_os_base_time_diff_lo;
794 os_basetime_diff.hi = uuid_c_os_base_time_diff_hi;
795 UADD_UVLW_2_UVLW (&utc, &os_basetime_diff, uuid_time);
796
797 }
798
799 /*
800 **++
801 **
802 ** ROUTINE NAME: init
803 **
804 ** SCOPE: INTERNAL - declared locally
805 **
806 ** DESCRIPTION:
807 **
808 ** Startup initialization routine for the UUID module.
809 **
810 ** INPUTS: none
811 **
812 ** INPUTS/OUTPUTS: none
813 **
814 ** OUTPUTS:
815 **
816 ** status return status value
817 **
818 ** uuid_s_ok
819 ** uuid_s_coding_error
820 **
821 ** IMPLICIT INPUTS: none
822 **
823 ** IMPLICIT OUTPUTS: none
824 **
825 ** FUNCTION VALUE: void
826 **
827 ** SIDE EFFECTS: sets uuid_init_done so this won't be done again
828 **
829 **--
830 **/
831
832 static OSErr init()
833 {
834 /*
835 * init the random number generator
836 */
837
838 true_random_init();
839
840 /*
841 * Read the preferences data from the Macintosh pref file
842 */
843
844 ReadPrefData();
845
846 /*
847 * Get the time. Note that I renamed 'time_last' to
848 * GLastTime to indicate that I'm using it elsewhere as
849 * a shared library global.
850 */
851
852 if ((GLastTime.hi == 0) && (GLastTime.lo == 0)) {
853 uuid__get_os_time (&GLastTime);
854 GClockSeq = true_random();
855 }
856 uuid_init_done = true;
857 return 0;
858 }
859
860 static uint32_t _CFGenerateV1UUID(uint8_t *uuid_bytes)
861 {
862 uuid_v1_t *uuid = (uuid_v1_t *)uuid_bytes;
863 OSErr err;
864 uuid_address_t eaddr;
865 int got_no_time = false;
866
867 if (!uuid_init_done) {
868 err = init();
869 if (err) return err;
870 }
871 /*
872 * get our hardware network address
873 */
874
875 if (0 != (err = uuid_get_address(&eaddr))) return err;
876
877 do
878 {
879 /*
880 * get the current time
881 */
882 uuid__get_os_time (&time_now);
883
884 /*
885 * do stuff like:
886 *
887 * o check that our clock hasn't gone backwards and handle it
888 * accordingly with clock_seq
889 * o check that we're not generating uuid's faster than we
890 * can accommodate with our time_adjust fudge factor
891 */
892 switch (time_cmp (&time_now, &GLastTime))
893 {
894 case uuid_e_less_than:
895 new_clock_seq (&GClockSeq);
896 GTimeAdjust = 0;
897 break;
898 case uuid_e_greater_than:
899 GTimeAdjust = 0;
900 break;
901 case uuid_e_equal_to:
902 if (GTimeAdjust == MAX_TIME_ADJUST)
903 {
904 /*
905 * spin your wheels while we wait for the clock to tick
906 */
907 got_no_time = true;
908 }
909 else
910 {
911 GTimeAdjust++;
912 }
913 break;
914 default:
915 return kUUIDInternalError;
916 }
917 } while (got_no_time);
918
919 GLastTime.lo = time_now.lo;
920 GLastTime.hi = time_now.hi;
921
922 if (GTimeAdjust != 0)
923 {
924 UADD_UW_2_UVLW (&GTimeAdjust, &time_now, &time_now);
925 }
926
927 /*
928 * now construct a uuid with the information we've gathered
929 * plus a few constants
930 */
931 uuid->time_low = time_now.lo;
932 uuid->time_mid = time_now.hi & TIME_MID_MASK;
933
934 uuid->time_hi_and_version =
935 (time_now.hi & TIME_HIGH_MASK) >> TIME_HIGH_SHIFT_COUNT;
936 uuid->time_hi_and_version |= UUID_VERSION_BITS;
937
938 uuid->clock_seq_low = GClockSeq & CLOCK_SEQ_LOW_MASK;
939 uuid->clock_seq_hi_and_reserved =
940 (GClockSeq & CLOCK_SEQ_HIGH_MASK) >> CLOCK_SEQ_HIGH_SHIFT_COUNT;
941
942 uuid->clock_seq_hi_and_reserved |= UUID_RESERVED_BITS;
943
944 memmove (uuid->node, &eaddr, sizeof (uuid_address_t));
945
946 return 0;
947 }
948
949 #if defined(__MACH__)
950
951 #include <uuid/uuid.h>
952
953 __private_extern__ uint32_t _CFGenerateUUID(uuid_t *uuid_bytes) {
954 static Boolean useV1UUIDs = false, checked = false;
955 uuid_t uuid;
956 if (!checked) {
957 const char *value = getenv("CFUUIDVersionNumber");
958 if (value) {
959 if (1 == strtoul(value, NULL, 0)) useV1UUIDs = true;
960 } else {
961 if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionTiger)) useV1UUIDs = true;
962 }
963 checked = true;
964 }
965 if (useV1UUIDs) return _CFGenerateV1UUID(uuid_bytes);
966 uuid_generate_random(uuid);
967 memcpy(uuid_bytes, uuid, sizeof(uuid));
968 return 0;
969 }
970
971 #else
972
973 __private_extern__ uint32_t _CFGenerateUUID(uuid_t *uuid_bytes) {
974 return _CFGenerateV1UUID(uuid_bytes);
975 }
976
977 #endif // __MACH__
978
979
980 /*****************************************************************************
981 *
982 * LOCAL MATH PROCEDURES - math procedures used internally by the UUID module
983 *
984 ****************************************************************************/
985
986 /*
987 ** T I M E _ C M P
988 **
989 ** Compares two UUID times (64-bit UTC values)
990 **/
991
992 static uuid_compval_t time_cmp(uuid_time_t *time1,uuid_time_t *time2)
993 {
994 /*
995 * first check the hi parts
996 */
997 if (time1->hi < time2->hi) return (uuid_e_less_than);
998 if (time1->hi > time2->hi) return (uuid_e_greater_than);
999
1000 /*
1001 * hi parts are equal, check the lo parts
1002 */
1003 if (time1->lo < time2->lo) return (uuid_e_less_than);
1004 if (time1->lo > time2->lo) return (uuid_e_greater_than);
1005
1006 return (uuid_e_equal_to);
1007 }
1008
1009
1010
1011 /****************************************************************************
1012 **
1013 ** U U I D T R U E R A N D O M N U M B E R G E N E R A T O R
1014 **
1015 *****************************************************************************
1016 **
1017 ** This random number generator (RNG) was found in the ALGORITHMS Notesfile.
1018 **
1019 ** (Note 16.7, July 7, 1989 by Robert (RDVAX::)Gries, Cambridge Research Lab,
1020 ** Computational Quality Group)
1021 **
1022 ** It is really a "Multiple Prime Random Number Generator" (MPRNG) and is
1023 ** completely discussed in reference #1 (see below).
1024 **
1025 ** References:
1026 ** 1) "The Multiple Prime Random Number Generator" by Alexander Hass
1027 ** pp. 368 to 381 in ACM Transactions on Mathematical Software,
1028 ** December, 1987
1029 ** 2) "The Art of Computer Programming: Seminumerical Algorithms
1030 ** (vol 2)" by Donald E. Knuth, pp. 39 to 113.
1031 **
1032 ** A summary of the notesfile entry follows:
1033 **
1034 ** Gries discusses the two RNG's available for ULTRIX-C. The default RNG
1035 ** uses a Linear Congruential Method (very popular) and the second RNG uses
1036 ** a technique known as a linear feedback shift register.
1037 **
1038 ** The first (default) RNG suffers from bit-cycles (patterns/repetition),
1039 ** ie. it's "not that random."
1040 **
1041 ** While the second RNG passes all the emperical tests, there are "states"
1042 ** that become "stable", albeit contrived.
1043 **
1044 ** Gries then presents the MPRNG and says that it passes all emperical
1045 ** tests listed in reference #2. In addition, the number of calls to the
1046 ** MPRNG before a sequence of bit position repeats appears to have a normal
1047 ** distribution.
1048 **
1049 ** Note (mbs): I have coded the Gries's MPRNG with the same constants that
1050 ** he used in his paper. I have no way of knowing whether they are "ideal"
1051 ** for the range of numbers we are dealing with.
1052 **
1053 ****************************************************************************/
1054
1055 /*
1056 ** T R U E _ R A N D O M _ I N I T
1057 **
1058 ** Note: we "seed" the RNG with the bits from the clock and the PID
1059 **
1060 **/
1061
1062 static void true_random_init (void)
1063 {
1064 uuid_time_t t;
1065 uint16_t *seedp, seed=0;
1066
1067
1068 /*
1069 * optimal/recommended starting values according to the reference
1070 */
1071 static uint32_t rand_m_init = 971;
1072 static uint32_t rand_ia_init = 11113;
1073 static uint32_t rand_ib_init = 104322;
1074 static uint32_t rand_irand_init = 4181;
1075
1076 rand_m = rand_m_init;
1077 rand_ia = rand_ia_init;
1078 rand_ib = rand_ib_init;
1079 rand_irand = rand_irand_init;
1080
1081 /*
1082 * Generating our 'seed' value
1083 *
1084 * We start with the current time, but, since the resolution of clocks is
1085 * system hardware dependent (eg. Ultrix is 10 msec.) and most likely
1086 * coarser than our resolution (10 usec) we 'mixup' the bits by xor'ing
1087 * all the bits together. This will have the effect of involving all of
1088 * the bits in the determination of the seed value while remaining system
1089 * independent. Then for good measure to ensure a unique seed when there
1090 * are multiple processes creating UUID's on a system, we add in the PID.
1091 */
1092 uuid__get_os_time(&t);
1093 seedp = (uint16_t *)(&t);
1094 seed ^= *seedp++;
1095 seed ^= *seedp++;
1096 seed ^= *seedp++;
1097 seed ^= *seedp++;
1098 rand_irand += seed;
1099 }
1100
1101 /*
1102 ** T R U E _ R A N D O M
1103 **
1104 ** Note: we return a value which is 'tuned' to our purposes. Anyone
1105 ** using this routine should modify the return value accordingly.
1106 **/
1107
1108 static uint16_t true_random (void)
1109 {
1110 rand_m += 7;
1111 rand_ia += 1907;
1112 rand_ib += 73939;
1113
1114 if (rand_m >= 9973) rand_m -= 9871;
1115 if (rand_ia >= 99991) rand_ia -= 89989;
1116 if (rand_ib >= 224729) rand_ib -= 96233;
1117
1118 rand_irand = (rand_irand * rand_m) + rand_ia + rand_ib;
1119
1120 return (HI_WORD (rand_irand) ^ (rand_irand & RAND_MASK));
1121 }
1122
1123 /*****************************************************************************
1124 *
1125 * LOCAL PROCEDURES - procedures used staticly by the UUID module
1126 *
1127 ****************************************************************************/
1128
1129 /*
1130 ** N E W _ C L O C K _ S E Q
1131 **
1132 ** Ensure *clkseq is up-to-date
1133 **
1134 ** Note: clock_seq is architected to be 14-bits (unsigned) but
1135 ** I've put it in here as 16-bits since there isn't a
1136 ** 14-bit unsigned integer type (yet)
1137 **/
1138
1139 static void new_clock_seq
1140 #ifdef _DCE_PROTO_
1141 (
1142 uint16_t *clkseq
1143 )
1144 #else
1145 (clkseq)
1146 uint16_t *clkseq;
1147 #endif
1148 {
1149 /*
1150 * A clkseq value of 0 indicates that it hasn't been initialized.
1151 */
1152 if (*clkseq == 0)
1153 {
1154 #ifdef UUID_NONVOLATILE_CLOCK
1155 *clkseq = uuid__read_clock(); /* read nonvolatile clock */
1156 if (*clkseq == 0) /* still not init'd ??? */
1157 {
1158 *clkseq = true_random(); /* yes, set random */
1159 }
1160 #else
1161 /*
1162 * with a volatile clock, we always init to a random number
1163 */
1164 *clkseq = true_random();
1165 #endif
1166 }
1167
1168 CLOCK_SEQ_BUMP (clkseq);
1169 if (*clkseq == 0)
1170 {
1171 *clkseq = *clkseq + 1;
1172 }
1173
1174 #ifdef UUID_NONVOLATILE_CLOCK
1175 uuid_write_clock (clkseq);
1176 #endif
1177 }
1178
1179
1180
1181 /* ReadPrefData
1182 *
1183 * Read the preferences data into my global variables
1184 */
1185
1186 static OSErr ReadPrefData(void)
1187 {
1188 /*
1189 * Zero out the saved preferences information
1190 */
1191
1192 memset((void *)&GSavedENetAddr, 0, sizeof(GSavedENetAddr));
1193 memset((void *)&GLastTime, 0, sizeof(GLastTime));
1194 GTimeAdjust = 0;
1195 GClockSeq = 0;
1196
1197
1198 return 0;
1199 }
1200
1201 #if 0
1202 // currently unused
1203
1204 /* WritePrefData
1205 *
1206 * Write the preferences data back out to my global variables.
1207 * This gets called a couple of times. First, this is called by
1208 * my GetRandomEthernet routine if I generated a psudorandom MAC
1209 * address. Second, this is called when the library is being
1210 * terminated through the __terminate() CFM call.
1211 *
1212 * Note this does it's best attempt at writing the data out,
1213 * and relies on ReadPrefData to check for integrety of the actual
1214 * saved file.
1215 */
1216
1217 static void WritePrefData(void)
1218 {
1219 }
1220
1221 #endif // 0
1222
1223 #undef HI_WORD
1224 #undef RAND_MASK
1225 #undef TIME_MID_MASK
1226 #undef TIME_HIGH_MASK
1227 #undef TIME_HIGH_SHIFT_COUNT
1228 #undef MAX_TIME_ADJUST
1229 #undef CLOCK_SEQ_LOW_MASK
1230 #undef CLOCK_SEQ_HIGH_MASK
1231 #undef CLOCK_SEQ_HIGH_SHIFT_COUNT
1232 #undef CLOCK_SEQ_FIRST
1233 #undef CLOCK_SEQ_LAST
1234 #undef CLOCK_SEQ_BIT_BANG
1235 #undef CLOCK_SEQ_BUMP
1236 #undef UUID_VERSION_BITS
1237 #undef UUID_RESERVED_BITS
1238 #undef IS_OLD_UUID
1239 #undef EmptyArg
1240 #undef UUID_VERIFY_INIT
1241 #undef CHECK_STRUCTURE
1242 #undef bCHECK_STRUCTURE
1243 #undef vCHECK_STRUCTURE
1244 #undef rCHECK_STRUCTURE
1245 #undef uuid_c_os_base_time_diff_lo
1246 #undef uuid_c_os_base_time_diff_hi
1247 #undef UUID_C_100NS_PER_SEC
1248 #undef UUID_C_100NS_PER_USEC
1249 #undef UADD_UVLW_2_UVLW
1250 #undef UADD_UW_2_UVLW
1251
1252 #endif // __WIN32__