|
-
- Network Working Group Paul J. Leach, Microsoft
- INTERNET-DRAFT Rich Salz, Open Group
- <draft-leach-uuids-guids-00.txt>
- Category: Informational
- Expires August 24, 1997 February 24, 1997
-
-
-
- UUIDs and GUIDs
-
- STATUS OF THIS MEMO
-
- This document is an Internet-Draft. Internet-Drafts are working
- documents of the Internet Engineering Task Force (IETF), its areas,
- and its working groups. Note that other groups may also distribute
- working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress".
-
- To learn the current status of any Internet-Draft, please check the
- "1id-abstracts.txt" listing contained in the Internet-Drafts Shadow
- Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
- munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
- ftp.isi.edu (US West Coast).
-
- Distribution of this document is unlimited. Please send comments to
- the authors or the CIFS mailing list at <cifs@listserv.msn.com>.
- Discussions of the mailing list are archived at
- <URL:http://microsoft.ease.lsoft.com/archives/CIFS.html>.
-
-
- ABSTRACT
-
- This specification defines the format of UUIDs (Universally Unique
- IDentifier), also known as GUIDs (Globally Unique IDentifier). A UUID
- is 128 bits long, and if generated according to the one of the
- mechanisms in this document, is either guaranteed to be different
- from all other UUIDs/GUIDs generated until 3400 A.D. or extremely
- likely to be different (depending on the mechanism chosen). UUIDs
- were originally used in the Network Computing System (NCS) [1] and
- later in the Open Software Foundation's (OSF) Distributed Computing
- Environment [2].
-
- This specification is derived from the latter specification with the
- kind permission of the OSF.
-
-
- Table of Contents
-
- 1. Introduction......................................................2
-
-
- [Page 1]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- 2. Motivation........................................................2
-
- 3. Specification.....................................................3
-
- 3.1 Format ..........................................................3
-
- 3.2 Algorithms for Creating a UUID ..................................5
-
- 3.2.1 Clock Sequence...............................................5
-
- 3.2.2 System Reboot................................................6
-
- 3.2.3 Clock Adjustment.............................................7
-
- 3.2.4 Clock Overrun................................................7
-
- 3.2.5 UUID Generation..............................................7
-
- 3.3 String Representation of UUIDs ..................................8
-
- 3.4 Comparing UUIDs .................................................9
-
- 3.5 Byte order of UUIDs .............................................9
-
- 4. Node IDs when no IEEE 802 network card is available...............9
-
- 5. Obtaining IEEE 802 addresses.....................................11
-
- 6. Security Considerations..........................................12
-
- 7. Acknowledgements.................................................12
-
- 8. References.......................................................12
-
- 9. Authors' addresses...............................................12
-
-
-
-
- 1. Introduction
-
- This specification defines the format of UUIDs (Universally Unique
- IDentifiers), also known as GUIDs (Globally Unique IDentifiers). A
- UUID is 128 bits long, and if generated according to the one of the
- mechanisms in this document, is either guaranteed to be different
- from all other UUIDs/GUIDs generated until 3400 A.D. or extremely
- likely to be different (depending on the mechanism chosen).
-
-
- 2. Motivation
-
- One of the main reasons for using UUIDs is that no centralized
- authority is required to administer them (beyond the one that
- allocates IEEE 802.1 node identifiers). As a result, generation on
-
- Leach, Salz expires July 1997 [Page 2]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- demand can be completely automated, and they can be used for a wide
- variety of purposes. The UUID generation algorithm described here
- supports very high allocation rates: 10 million per second per
- machine if you need it, so that they could even be used as
- transaction IDs.
-
- UUIDs are fixed-size (128-bits) which is reasonably small relative to
- other alternatives. This fixed, relatively small size lends itself
- well to sorting, ordering, and hashing of all sorts, storing in
- databases, simple allocation, and ease of programming in general.
-
-
- 3. Specification
-
- A UUID is an identifier that is unique across both space and time,
- with respect to the space of all UUIDs. To be precise, the UUID
- consists of a finite bit space. Thus the time value used for
- constructing a UUID is limited and will roll over in the future
- (approximately at A.D. 3400, based on the specified algorithm). A
- UUID can be used for multiple purposes, from tagging objects with an
- extremely short lifetime, to reliably identifying very persistent
- objects across a network.
-
- The generation of UUIDs does not require that a registration
- authority be contacted for each identifier. Instead, it requires a
- unique value over space for each UUID generator. This spatially
- unique value is specified as an IEEE 802 address, which is usually
- already available to network-connected systems. This 48-bit address
- can be assigned based on an address block obtained through the IEEE
- registration authority. This section of the UUID specification
- assumes the availability of an IEEE 802 address to a system desiring
- to generate a UUID, but if one is not available section 4 specifies a
- way to generate a probabilistically unique one that can not conflict
- with any properly assigned IEEE 802 address.
-
-
- 3.1 Format
-
- The following table gives the format of a UUID. The UUID consists of
- a record of 16 octets. The fields are in order of significance for
- comparison purposes, with "time_low" the most significant, and "node"
- the least significant.
-
- Field Data Octet Note
- Type #
-
- time_low unsigned 0-3 The low field of the
- 32 bit timestamp.
- integer
-
- time_mid unsigned 4-5 The middle field of the
- 16 bit timestamp.
- integer
-
-
- Leach, Salz expires July 1997 [Page 3]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- time_hi_and_version unsigned 6-7 The high field of the
- 16 bit timestamp multiplexed
- integer with the version number.
-
- clock_seq_hi_and_reserved unsigned The high field of the
- 8 bit clock sequence 8
- integer multiplexed with the
- variant.
-
- clock_seq_low unsigned 9 The low field of the
- 8 bit clock sequence.
- integer
-
- node unsigned The spatially unique
- 48 bit node identifier. 10-15
- integer
-
-
-
- To minimize confusion about bit assignments within octets, the UUID
- record definition is defined only in terms of fields that are
- integral numbers of octets. The version number is in the most
- significant 4 bits of the time stamp (time_hi), and the variant field
- is in the most significant 3 bits of the clock sequence
- (clock_seq_high).
-
- The timestamp is a 60 bit value. For UUID version 1, this is
- represented by Coordinated Universal Time (UTC) as a count of 100-
- nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
- Gregorian reform to the Christian calendar).
-
- The following table lists currently defined versions of the UUID.
-
- Msb0 Msb1 Msb2 Msb3 Version Description
-
- 0 0 0 1 1 The version specified
- in this document.
-
- 0 0 1 0 2 Reserved for DCE
- Security version, with
- embedded POSIX UIDs.
-
- The variant field determines the layout of the UUID. The structure of
- UUIDs is fixed across different versions within a variant, but not
- across variants; hence, other UUID variants may not interoperate with
- the UUID variant specified in this document. Interoperability of
- UUIDs is defined as the applicability of operations such as string
- conversion, comparison, and lexical ordering across different
- systems. The variant field consists of a variable number of the msbs
- of the clock_seq_hi_and_reserved field.
-
- The following table lists the contents of the variant field.
-
-
-
- Leach, Salz expires July 1997 [Page 4]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- Msb0 Msb1 Msb2 Description
-
- 0 - - Reserved, NCS backward compatibility.
-
- 1 0 - The variant specified in this document.
-
- 1 1 0 Reserved, Microsoft Corporation GUID.
-
- 1 1 1 Reserved for future definition.
-
- The clock sequence is required to detect potential losses of
- monotonicity of the clock. Thus, this value marks discontinuities and
- prevents duplicates. An algorithm for generating this value is
- outlined in the _Clock Sequence_ section below.
-
- The clock sequence is encoded in the 6 least significant bits of the
- clock_seq_hi_and_reserved field and in the clock_seq_low field.
-
- The node field consists of the IEEE address, usually the host
- address. For systems with multiple IEEE 802 nodes, any available node
- address can be used. The lowest addressed octet (octet number 10)
- contains the global/local bit and the unicast/multicast bit, and is
- the first octet of the address transmitted on an 802.3 LAN.
-
- Depending on the network data representation, the multi-octet
- unsigned integer fields are subject to byte swapping when
- communicated between different endian machines.
-
- The nil UUID is special form of UUID that is specified to have all
- 128 bits set to 0 (zero).
-
-
- 3.2 Algorithms for Creating a UUID
-
- Various aspects of the algorithm for creating a UUID are discussed in
- the following sections. UUID generation requires a guarantee of
- uniqueness within the node ID for a given variant and version.
- Interoperability is provided by complying with the specified data
- structure. To prevent possible UUID collisions, which could be caused
- by different implementations on the same node, compliance with the
- algorithm specified here is required.
-
-
- 3.2.1 Clock Sequence
- The clock sequence value must be changed whenever:
-
- - the UUID generator detects that the local value of UTC has gone
- backward.
-
- - the UUID generator has lost its state of the last value of UTC
- used, indicating that time may have gone backward; this is typically
- the case on reboot.
-
-
-
- Leach, Salz expires July 1997 [Page 5]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- While a node is operational, the UUID service always saves the last
- UTC used to create a UUID. Each time a new UUID is created, the
- current UTC is compared to the saved value and if either the current
- value is less (the non-monotonic clock case) or the saved value was
- lost, then the clock sequence is incremented modulo 16,384, thus
- avoiding production of duplicate UUIDs.
-
- The clock sequence must be initialized to a random number to minimize
- the correlation across systems. This provides maximum protection
- against node identifiers that may move or switch from system to
- system rapidly. The initial value MUST NOT be correlated to the node
- identifier.
-
- The rule of initializing the clock sequence to a random value is
- waived if, and only if all of the following are true:
-
- - The clock sequence value is stored in non-volatile storage.
-
- - The system is manufactured such that the IEEE address ROM is
- designed to be inseparable from the system by either the user or
- field service, so that it cannot be moved to another system.
-
- - The manufacturing process guarantees that only new IEEE address
- ROMs are used.
-
- - Any field service, remanufacturing or rebuilding process that could
- change the value of the clock sequence must reinitialise it to a
- random value.
-
- In other words, the system constraints prevent duplicates caused by
- possible migration of the IEEE address, while the operational system
- itself can protect against non-monotonic clocks, except in the case
- of field service intervention. At manufacturing time, such a system
- may initialise the clock sequence to any convenient value.
-
-
- 3.2.2 System Reboot
- There are two possibilities when rebooting a system:
-
- - the UUID generator state - the last UTC, adjustment, and clock
- sequence - of the UUID service has been restored from non-volatile
- store
-
- - the state of the last UTC or adjustment has been lost.
-
- If the state variables have been restored, the UUID generator just
- continues as normal. Alternatively, if the state variables cannot be
- restored, they are reinitialised, and the clock sequence is changed.
-
- If the clock sequence is stored in non-volatile store, it is
- incremented; otherwise, it is reinitialised to a new random value.
-
-
-
-
- Leach, Salz expires July 1997 [Page 6]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- 3.2.3 Clock Adjustment
- UUIDs may be created at a rate greater than the system clock
- resolution. Therefore, the system must also maintain an adjustment
- value to be added to the lower-order bits of the time. Logically,
- each time the system clock ticks, the adjustment value is cleared.
- Every time a UUID is generated, the current adjustment value is read
- and incremented atomically, then added to the UTC time field of the
- UUID.
-
-
- 3.2.4 Clock Overrun
- The 100 nanosecond granularity of time should prove sufficient even
- for bursts of UUID creation in high-performance multiprocessors. If a
- system overruns the clock adjustment by requesting too many UUIDs
- within a single system clock tick, the UUID service may raise an
- exception, handled in a system or process-dependent manner either by:
-
- - terminating the requester
-
- - reissuing the request until it succeeds
-
- - stalling the UUID generator until the system clock catches up.
-
- If the processors overrun the UUID generation frequently, additional
- node identifiers and clocks may need to be added.
-
-
- 3.2.5 UUID Generation
- UUIDs are generated according to the following algorithm:
-
- - Determine the values for the UTC-based timestamp and clock sequence
- to be used in the UUID, as described above.
-
- - For the purposes of this algorithm, consider the timestamp to be a
- 60-bit unsigned integer and the clock sequence to be a 14-bit
- unsigned integer. Sequentially number the bits in a field, starting
- from 0 (zero) for the least significant bit.
-
- - Set the time_low field equal to the least significant 32-bits (bits
- numbered 0 to 31 inclusive) of the time stamp in the same order of
- significance.
-
- - Set the time_mid field equal to the bits numbered 32 to 47
- inclusive of the time stamp in the same order of significance.
-
- - Set the 12 least significant bits (bits numbered 0 to 11 inclusive)
- of the time_hi_and_version field equal to the bits numbered 48 to 59
- inclusive of the time stamp in the same order of significance.
-
- - Set the 4 most significant bits (bits numbered 12 to 15 inclusive)
- of the time_hi_and_version field to the 4-bit version number
- corresponding to the UUID version being created, as shown in the
- table above.
-
-
- Leach, Salz expires July 1997 [Page 7]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- - Set the clock_seq_low field to the 8 least significant bits (bits
- numbered 0 to 7 inclusive) of the clock sequence in the same order of
- significance.
-
- - Set the 6 least significant bits (bits numbered 0 to 5 inclusive)
- of the clock_seq_hi_and_reserved field to the 6 most significant bits
- (bits numbered 8 to 13 inclusive) of the clock sequence in the same
- order of significance.
-
- - Set the 2 most significant bits (bits numbered 6 and 7) of the
- clock_seq_hi_and_reserved to 0 and 1, respectively.
-
- - Set the node field to the 48-bit IEEE address in the same order of
- significance as the address.
-
-
- 3.3 String Representation of UUIDs
-
- For use in human readable text, a UUID string representation is
- specified as a sequence of fields, some of which are separated by
- single dashes.
-
- Each field is treated as an integer and has its value printed as a
- zero-filled hexadecimal digit string with the most significant digit
- first. The hexadecimal values a to f inclusive are output as lower
- case characters, and are case insensitive on input. The sequence is
- the same as the UUID constructed type.
-
- The formal definition of the UUID string representation is provided
- by the following extended BNF:
-
- UUID = <time_low> "-" <time_mid> "-"
- <time_high_and_version> "-"
- <clock_seq_and_reserved>
- <clock_seq_low> "-" <node>
- time_low = 4*<hexOctet>
- time_mid = 2*<hexOctet>
- time_high_and_version = 2*<hexOctet>
- clock_seq_and_reserved = <hexOctet>
- clock_seq_low = <hexOctet>
- node = 6*<hexOctet
- hexOctet = <hexDigit> <hexDigit>
- hexDigit =
- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
- | "a" | "b" | "c" | "d" | "e" | "f"
- | "A" | "B" | "C" | "D" | "E" | "F"
-
- The following is an example of the string representation of a UUID:
-
- f81d4fae-7dec-11d0-a765-00a0c91e6bf6
-
-
-
-
-
- Leach, Salz expires July 1997 [Page 8]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- 3.4 Comparing UUIDs
-
- Consider each field of the UUID to be an unsigned integer as shown in
- the table in section 3.1. Then, to compare a pair of UUIDs,
- arithmetically compare the corresponding fields from each UUID in
- order of significance and according to their data type. Two UUIDs are
- equal if and only if all the corresponding fields are equal. The
- first of two UUIDs follows the second if the most significant field
- in which the UUIDs differ is greater for the first UUID. The first of
- a pair of UUIDs precedes the second if the most significant field in
- which the UUIDs differ is greater for the second UUID.
-
-
- 3.5 Byte order of UUIDs
-
- UUIDs may be transmitted in many different forms, some of which may
- be dependent on the presentation or application protocol where the
- UUID may be used. In such cases, the order, sizes and byte orders of
- the UUIDs fields on the wire will depend on the relevant presentation
- or application protocol. However, it is strongly RECOMMENDED that
- the order of the fields conform with ordering set out in section 3.1
- above. Furthermore, the payload size of each field in the application
- or presentation protocol MUST be large enough that no information
- lost in the process of encoding them for transmission.
-
- In the absence of explicit application or presentation protocol
- specification to the contrary, a UUID is encoded as a 128-bit object,
- as follows: the fields are encoded as 16 octets, with the sizes and
- order of the fields defined in section 3.1, and with each field
- encoded with the Most Significant Byte first (also known as network
- byte order).
-
- 0 1 2 3
- 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
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | time_high |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | time_mid | time_hi_and_version |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |clk_seq_hi_res | clk_seq_low | node (0-1) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | node (2-5) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
-
- 4. Node IDs when no IEEE 802 network card is available
-
- If a system wants to generate UUIDs but has no IEE 802 compliant
- network card or other source of IEEE 802 addresses, then this section
- describes how to generate one.
-
- The ideal solution is to obtain a 47 bit cryptographic quality random
- number, and use it as the low 47 bits of the node ID, with the most
-
- Leach, Salz expires July 1997 [Page 9]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- significant bit of the first octet of the node ID set to 1. This bit
- is the unicast/multicast bit, which will never be set in IEEE 802
- addresses obtained from network cards; hence, there can never be a
- conflict between UUIDs generated by machines with and without network
- cards.
-
- If a system does not have a primitive to generate cryptographic
- quality random numbers, then in most systems there are usually a
- fairly large number of sources of randomness available from which one
- can be generated. Such sources are system specific, but often
- include:
-
- - the percent of memory in use
-
- - the size of main memory in bytes
-
- - the amount of free main memory in bytes
-
- - the size of the paging or swap file in bytes
-
- - free bytes of paging or swap file
-
- - the total size of user virtual address space in bytes
-
- - the total available user address space bytes
-
- - the size of boot disk drive in bytes
-
- - the free disk space on boot drive in bytes
-
- - the current time
-
- - the amount of time since the system booted
-
- - the individual sizes of files in various system directories
-
- - the creation, last read, and modification times of files in various
- system directories
-
- - the utilization factors of various system resources (heap, etc.)
-
- - current mouse cursor position
-
- - current caret position
-
- - current number of running processes, threads
-
- - handles or IDs of the desktop window and the active window
-
- - the value of stack pointer of the caller
-
- - the process and thread ID of caller
-
-
-
- Leach, Salz expires July 1997 [Page 10]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- - various processor architecture specific performance counters
- (instructions executed, cache misses, TLB misses)
-
- (Note that it precisely the above kinds of sources of randomness that
- are used to seed cryptographic quality random number generators on
- systems without special hardware for their construction.)
-
- In addition, items such as the computer's name and the name of the
- operating system, while not strictly speaking random, will help
- differentiate the results from those obtained by other systems.
-
- The exact algorithm to generate a node ID using these data is system
- specific, because both the data available and the functions to obtain
- them are often very system specific. However, assuming that one can
- concatenate all the values from the randomness sources into a buffer,
- and that a cryptographic hash function such as MD5 [3] is available,
- the following code will compute a node ID:
-
- #include <md5.h>
- #define HASHLEN 16
-
- void GenNodeID(
- unsigned char * pDataBuf, // concatenated "randomness values"
- long cData, // size of randomness values
- unsigned char NodeID[6] // node ID
- )
- {
- int i, j, k;
- unsigned char Hash[HASHLEN];
- MD_CTX context;
-
- MDInit (&context);
- MDUpdate (&context, pDataBuf, cData);
- MDFinal (Hash, &context);
-
- for (j = 0; j<6; j++) NodeId[j]=0;
- for (i = 0,j = 0; i < HASHLEN; i++) {
- NodeID[j++] ^= Hash[i];
- if (j == 6) j = 0;
- };
- NodeID[0] |= 0x80; // set the multicast bit
- };
-
- Other hash functions, such as SHA-1 [4], can also be used (in which
- case HASHLEN will be 20). The only requirement is that the result be
- suitably random _ in the sense that the outputs from a set uniformly
- distributed inputs are themselves uniformly distributed, and that a
- single bit change in the input can be expected to cause half of the
- output bits to change.
-
-
- 5. Obtaining IEEE 802 addresses
-
- The following URL
-
- Leach, Salz expires July 1997 [Page 11]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
-
-
-
- http://stdsbbs.ieee.org/products/oui/forms/index.html
-
- contains information on how to obtain an IEEE 802 address block. Cost
- is $1000 US.
-
-
- 6. Security Considerations
-
- It should not be assumed that UUIDs are hard to guess; they should
- not be used as capabilities.
-
-
- 7. Acknowledgements
-
- This document draws heavily on the OSF DCE specification for UUIDs.
- Ted Ts'o provided helpful comments, especially on the byte ordering
- section which we mostly plagiarized from a proposed wording he
- supplied (all errors in that section are our responsibility,
- however).
-
-
- 8. References
-
- [1] Lisa Zahn, et. al., Network Computing Architecture, Prentice
- Hall, Englewood Cliffs, NJ, 1990
-
- [2] DCE: Remote Procedure Call, Open Group CAE Specification C309
- ISBN 1-85912-041-5 28cm. 674p. pbk. 1,655g. 8/94
-
- [3] R. Rivest, RFC 1321, "The MD5 Message-Digest Algorithm",
- 04/16/1992.
-
- [4] SHA Spec - TBD
-
-
- 9. Authors' addresses
-
- Paul J. Leach
- Microsoft
- 1 Microsoft Way
- Redmond, WA, 98052, U.S.A.
- Email:
-
- paulle@microsoft.com
-
- Rich Salz
- The Open Group
- 11 Cambridge Center
- Cambridge, MA 02142, U.S.A.
- Email r.salz@opengroup.org
-
-
-
-
- Appendix A _ UUID Reference Implementation
-
- /*
- ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
-
- Leach, Salz expires July 1997 [Page 12]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
- ** Digital Equipment Corporation, Maynard, Mass.
- ** To anyone who acknowledges that this file is provided "AS IS"
- ** without any express or implied warranty: permission to use, copy,
- ** modify, and distribute this file for any purpose is hereby
- ** granted without fee, provided that the above copyright notices and
- ** this notice appears in all source code copies, and that none of
- ** the names of Open Software Foundation, Inc., Hewlett-Packard
- ** Company, or Digital Equipment Corporation be used in advertising
- ** or publicity pertaining to distribution of the software without
- ** specific, written prior permission. Neither Open Software
- ** Foundation, Inc., Hewlett-Packard Company, nor Digital Equipment
- ** Corporation makes any representations about the suitability of
- ** this software for any purpose.
- */
- #include <sys/types.h>
- #include <sys/time.h>
-
- typedef unsigned long unsigned32;
- typedef unsigned short unsigned16;
- typedef unsigned char unsigned8;
- typedef unsigned char byte;
-
- #define CLOCK_SEQ_LAST 0x3FFF
- #define RAND_MASK CLOCK_SEQ_LAST
-
- typedef struct _uuid_t {
- unsigned32 time_low;
- unsigned16 time_mid;
- unsigned16 time_hi_and_version;
- unsigned8 clock_seq_hi_and_reserved;
- unsigned8 clock_seq_low;
- byte node[6];
- } uuid_t;
-
- typedef struct _unsigned64_t {
- unsigned32 lo;
- unsigned32 hi;
- } unsigned64_t;
-
- /*
- ** Add two unsigned 64-bit long integers.
- */
- #define ADD_64b_2_64b(A, B, sum) \
- { \
- if (!(((A)->lo & 0x80000000UL) ^ ((B)->lo & 0x80000000UL))) {
- \
- if (((A)->lo&0x80000000UL)) { \
- (sum)->lo = (A)->lo + (B)->lo; \
- (sum)->hi = (A)->hi + (B)->hi + 1; \
- } \
- else { \
- (sum)->lo = (A)->lo + (B)->lo; \
- (sum)->hi = (A)->hi + (B)->hi; \
-
- Leach, Salz expires July 1997 [Page 13]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- } \
- } \
- else { \
- (sum)->lo = (A)->lo + (B)->lo; \
- (sum)->hi = (A)->hi + (B)->hi; \
- if (!((sum)->lo&0x80000000UL)) (sum)->hi++; \
- } \
- }
-
- /*
- ** Add a 16-bit unsigned integer to a 64-bit unsigned integer.
- */
- #define ADD_16b_2_64b(A, B, sum) \
- { \
- (sum)->hi = (B)->hi; \
- if ((B)->lo & 0x80000000UL) { \
- (sum)->lo = (*A) + (B)->lo; \
- if (!((sum)->lo & 0x80000000UL)) (sum)->hi++; \
- } \
- else \
- (sum)->lo = (*A) + (B)->lo; \
- }
-
- /*
- ** Global variables.
- */
- static unsigned64_t time_last;
- static unsigned16 clock_seq;
-
- static void
- mult32(unsigned32 u, unsigned32 v, unsigned64_t *result)
- {
- /* Following the notation in Knuth, Vol. 2. */
- unsigned32 uuid1, uuid2, v1, v2, temp;
-
- uuid1 = u >> 16;
- uuid2 = u & 0xFFFF;
- v1 = v >> 16;
- v2 = v & 0xFFFF;
- temp = uuid2 * v2;
- result->lo = temp & 0xFFFF;
- temp = uuid1 * v2 + (temp >> 16);
- result->hi = temp >> 16;
- temp = uuid2 * v1 + (temp & 0xFFFF);
- result->lo += (temp & 0xFFFF) << 16;
- result->hi += uuid1 * v1 + (temp >> 16);
- }
-
- static void
- get_system_time(unsigned64_t *uuid_time)
- {
- struct timeval tp;
- unsigned64_t utc, usecs, os_basetime_diff;
-
-
- Leach, Salz expires July 1997 [Page 14]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- gettimeofday(&tp, (struct timezone *)0);
- mult32((long)tp.tv_sec, 10000000, &utc);
- mult32((long)tp.tv_usec, 10, &usecs);
- ADD_64b_2_64b(&usecs, &utc, &utc);
-
- /* Offset between UUID formatted times and Unix formatted times.
- * UUID UTC base time is October 15, 1582.
- * Unix base time is January 1, 1970. */
- os_basetime_diff.lo = 0x13814000;
- os_basetime_diff.hi = 0x01B21DD2;
- ADD_64b_2_64b(&utc, &os_basetime_diff, uuid_time);
- }
-
- /*
- ** See "The Multiple Prime Random Number Generator" by Alexander
- ** Hass pp. 368-381, ACM Transactions on Mathematical Software,
- ** 12/87.
- */
- static unsigned32 rand_m;
- static unsigned32 rand_ia;
- static unsigned32 rand_ib;
- static unsigned32 rand_irand;
-
- static void
- true_random_init(void)
- {
- unsigned64_t t;
- unsigned16 seed;
-
- /* Generating our 'seed' value Start with the current time, but,
- * since the resolution of clocks is system hardware dependent and
- * most likely coarser than our resolution (10 usec) we 'mixup' the
- * bits by xor'ing all the bits together. This will have the effect
- * of involving all of the bits in the determination of the seed
- * value while remaining system independent. Then for good measure
- * to ensure a unique seed when there are multiple processes
- * creating UUIDs on a system, we add in the PID.
- */
- rand_m = 971;
- rand_ia = 11113;
- rand_ib = 104322;
- rand_irand = 4181;
- get_system_time(&t);
- seed = t.lo & 0xFFFF;
- seed ^= (t.lo >> 16) & 0xFFFF;
- seed ^= t.hi & 0xFFFF;
- seed ^= (t.hi >> 16) & 0xFFFF;
- rand_irand += seed + getpid();
- }
-
- static unsigned16
- true_random(void)
- {
- if ((rand_m += 7) >= 9973)
-
- Leach, Salz expires July 1997 [Page 15]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- rand_m -= 9871;
- if ((rand_ia += 1907) >= 99991)
- rand_ia -= 89989;
- if ((rand_ib += 73939) >= 224729)
- rand_ib -= 96233;
- rand_irand = (rand_irand * rand_m) + rand_ia + rand_ib;
- return (rand_irand >> 16) ^ (rand_irand & RAND_MASK);
- }
-
- /*
- ** Startup initialization routine for the UUID module.
- */
- void
- uuid_init(void)
- {
- true_random_init();
- get_system_time(&time_last);
- #ifdef NONVOLATILE_CLOCK
- clock_seq = read_clock();
- #else
- clock_seq = true_random();
- #endif
- }
-
- static int
- time_cmp(unsigned64_t *time1, unsigned64_t *time2)
- {
- if (time1->hi < time2->hi) return -1;
- if (time1->hi > time2->hi) return 1;
- if (time1->lo < time2->lo) return -1;
- if (time1->lo > time2->lo) return 1;
- return 0;
- }
-
- static void new_clock_seq(void)
- {
- clock_seq = (clock_seq + 1) % (CLOCK_SEQ_LAST + 1);
- if (clock_seq == 0) clock_seq = 1;
- #ifdef NONVOLATILE_CLOCK
- write_clock(clock_seq);
- #endif
- }
-
- void uuid_create(uuid_t *uuid)
- {
- static unsigned64_t time_now;
- static unsigned16 time_adjust;
- byte eaddr[6];
- int got_no_time = 0;
-
- get_ieee_node_identifier(&eaddr); /* TO BE PROVIDED */
-
- do {
- get_system_time(&time_now);
-
- Leach, Salz expires July 1997 [Page 16]
-
-
- Internet-Draft UUIDs and GUIDs (DRAFT) 02/24/97
-
-
- switch (time_cmp(&time_now, &time_last)) {
- case -1:
- /* Time went backwards. */
- new_clock_seq();
- time_adjust = 0;
- break;
- case 1:
- time_adjust = 0;
- break;
- default:
- if (time_adjust == 0x7FFF)
- /* We're going too fast for our clock; spin. */
- got_no_time = 1;
- else
- time_adjust++;
- break;
- }
- } while (got_no_time);
-
- time_last.lo = time_now.lo;
- time_last.hi = time_now.hi;
-
- if (time_adjust != 0) {
- ADD_16b_2_64b(&time_adjust, &time_now, &time_now);
- }
-
- /* Construct a uuid with the information we've gathered
- * plus a few constants. */
- uuid->time_low = time_now.lo;
- uuid->time_mid = time_now.hi & 0x0000FFFF;
- uuid->time_hi_and_version = (time_now.hi & 0x0FFF0000) >> 16;
- uuid->time_hi_and_version |= (1 << 12);
- uuid->clock_seq_low = clock_seq & 0xFF;
- uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8;
- uuid->clock_seq_hi_and_reserved |= 0x80;
- memcpy(uuid->node, &eaddr, sizeof uuid->node);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Leach, Salz expires July 1997 [Page 17]
|