< draft-mealling-uuid-urn-01.txt   draft-mealling-uuid-urn-02.txt >
Network Working Group P. Leach Network Working Group P. Leach
Internet-Draft Microsoft Internet-Draft Microsoft
Expires: April 2, 2004 M. Mealling Expires: July 28, 2004 M. Mealling
VeriSign, Inc. VeriSign, Inc.
R. Salz R. Salz
DataPower Technology, Inc. DataPower Technology, Inc.
October 3, 2003 January 28, 2004
A UUID URN Namespace A UUID URN Namespace
draft-mealling-uuid-urn-01.txt draft-mealling-uuid-urn-02.txt
Status of this Memo Status of this Memo
This document is an Internet-Draft and is in full conformance with This document is an Internet-Draft and is in full conformance with
all provisions of Section 10 of RFC2026. all provisions of Section 10 of RFC2026.
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that other Task Force (IETF), its areas, and its working groups. Note that other
groups may also distribute working documents as Internet-Drafts. groups may also distribute working documents as Internet-Drafts.
skipping to change at page 1, line 34 skipping to change at page 1, line 34
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at http:// The list of current Internet-Drafts can be accessed at http://
www.ietf.org/ietf/1id-abstracts.txt. www.ietf.org/ietf/1id-abstracts.txt.
The list of Internet-Draft Shadow Directories can be accessed at The list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html. http://www.ietf.org/shadow.html.
This Internet-Draft will expire on April 2, 2004. This Internet-Draft will expire on July 28, 2004.
Copyright Notice Copyright Notice
Copyright (C) The Internet Society (2003). All Rights Reserved. Copyright (C) The Internet Society (2004). All Rights Reserved.
Abstract Abstract
This specification defines a Uniform Resource Name namespace for This specification defines a Uniform Resource Name namespace for
UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally
Unique IDentifier). A UUID is 128 bits long, and can provide a Unique IDentifier). A UUID is 128 bits long, and can provide a
guarantee of uniqueness across space and time. UUIDs were originally guarantee of uniqueness across space and time. UUIDs were originally
used in the Network Computing System (NCS) [1] and later in the Open used in the Network Computing System (NCS) [1] and later in the Open
Software Foundation's (OSF) Distributed Computing Environment [2]. Software Foundation's (OSF) Distributed Computing Environment [2].
This specification is derived from the latter specification with the This specification is derived from the latter specification with the
kind permission of the OSF (now known as The Open Group). Earlier kind permission of the OSF (now known as The Open Group). Earlier
versions of this document never left draft stage; this document versions of this document never left draft stage; this document
incorporates that information here. incorporates that information here.
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 3
3. Namespace Registration Template . . . . . . . . . . . . . . 3 3. Namespace Registration Template . . . . . . . . . . . . . . 3
4. Specification . . . . . . . . . . . . . . . . . . . . . . . 6 4. Specification . . . . . . . . . . . . . . . . . . . . . . . 5
4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . . . . 6 4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4.1.2 Layout and byte order . . . . . . . . . . . . . . . . . . . 6 4.1.2 Layout and byte order . . . . . . . . . . . . . . . . . . . 6
4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . . . . 7
4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . . . . 8 4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . . . . 8 4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . . . . 8
4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . . . . 10 4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2 Algorithms for creating a time-based UUID . . . . . . . . . 10 4.2 Algorithms for creating a time-based UUID . . . . . . . . . 10
4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . . . . 10 4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . . . . 10
4.2.2 Generation details . . . . . . . . . . . . . . . . . . . . . 12 4.2.2 Generation details . . . . . . . . . . . . . . . . . . . . . 12
4.3 Algorithm for creating a name-based UUID . . . . . . . . . . 13 4.3 Algorithm for creating a name-based UUID . . . . . . . . . . 12
4.4 Algorithms for creating a UUID from truly random or 4.4 Algorithms for creating a UUID from truly random or
pseudo-random numbers . . . . . . . . . . . . . . . . . . . 14 pseudo-random numbers . . . . . . . . . . . . . . . . . . . 13
4.5 Node IDs that do not identify the host . . . . . . . . . . . 15 4.5 Node IDs that do not identify the host . . . . . . . . . . . 14
5. Community Considerations . . . . . . . . . . . . . . . . . . 16 5. Community Considerations . . . . . . . . . . . . . . . . . . 15
6. Security Considerations . . . . . . . . . . . . . . . . . . 17 6. Security Considerations . . . . . . . . . . . . . . . . . . 15
7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 17 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 16
Normative References . . . . . . . . . . . . . . . . . . . . 17 Normative References . . . . . . . . . . . . . . . . . . . . 16
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 18 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 16
A. Appendix A - Sample Implementation . . . . . . . . . . . . . 18 A. Appendix A - Sample Implementation . . . . . . . . . . . . . 17
B. Appendix B - Sample output of utest . . . . . . . . . . . . 29 B. Appendix B - Sample output of utest . . . . . . . . . . . . 28
C. Appendix C - Some name space IDs . . . . . . . . . . . . . . 29 C. Appendix C - Some name space IDs . . . . . . . . . . . . . . 28
Intellectual Property and Copyright Statements . . . . . . . 31 Intellectual Property and Copyright Statements . . . . . . . 30
1. Introduction 1. Introduction
This specification defines a Uniform Resource Name namespace for This specification defines a Uniform Resource Name namespace for
UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally
Unique IDentifier). A UUID is 128 bits long, and requires no central Unique IDentifier). A UUID is 128 bits long, and requires no central
registration process. registration process.
The information here is meant to be a concise guide for those wishing The information here is meant to be a concise guide for those wishing
to implement services using UUIDs as URNs. Nothing in this document to implement services using UUIDs as URNs. Nothing in this document
skipping to change at page 3, line 28 skipping to change at page 3, line 28
One of the main reasons for using UUIDs is that no centralized One of the main reasons for using UUIDs is that no centralized
authority is required to administer them (although one format uses authority is required to administer them (although one format uses
IEEE 802.1 node identifiers, others do not). As a result, generation IEEE 802.1 node identifiers, others do not). As a result, generation
on demand can be completely automated, and they can be used for a on demand can be completely automated, and they can be used for a
wide variety of purposes. The UUID generation algorithm described wide variety of purposes. The UUID generation algorithm described
here supports very high allocation rates: 10 million per second per here supports very high allocation rates: 10 million per second per
machine if necessary, so that they could even be used as transaction machine if necessary, so that they could even be used as transaction
IDs. IDs.
UUIDs are of a fixed size (128-bits) which is reasonably small UUIDs are of a fixed size (128 bits) which is reasonably small
relative to other alternatives. This lends itself well to sorting, relative to other alternatives. This lends itself well to sorting,
ordering, and hashing of all sorts, storing in databases, simple ordering, and hashing of all sorts, storing in databases, simple
allocation, and ease of programming in general. allocation, and ease of programming in general.
Since UUIDs are unique and persistent, they make excellent Uniform Since UUIDs are unique and persistent, they make excellent Uniform
Resource Names. The unique ability to generate a new UUID without a Resource Names. The unique ability to generate a new UUID without a
registration process allows for UUIDs to be one of the URNs with the registration process allows for UUIDs to be one of the URNs with the
lowest minting cost. lowest minting cost.
3. Namespace Registration Template 3. Namespace Registration Template
skipping to change at page 7, line 38 skipping to change at page 7, line 34
bit integer clock sequence bit integer clock sequence
node unsigned 48 10-15 The spatially unique node unsigned 48 10-15 The spatially unique
bit integer node identifier bit integer node identifier
In the absence of explicit application or presentation protocol In the absence of explicit application or presentation protocol
specification to the contrary, a UUID is encoded as a 128-bit object, 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 as follows: the fields are encoded as 16 octets, with the sizes and
order of the fields defined above, and with each field encoded with order of the fields defined above, and with each field encoded with
the Most Significant Byte first (this is known as network byte the Most Significant Byte first (this is known as network byte
order). order). Note that the field names, particularly for multiplexed
fields, follow historical practice.
0 1 2 3 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 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_low | | time_low |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_mid | time_hi_and_version | | time_mid | time_hi_and_version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|clk_seq_hi_res | clk_seq_low | node (0-1) | |clk_seq_hi_res | clk_seq_low | node (0-1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| node (2-5) | | node (2-5) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4.1.3 Version 4.1.3 Version
The version number is in the most significant four bits of the time The version number is in the most significant four bits of the time
stamp (time_hi_and_version). stamp (bits four through seven of the time_hi_and_version field).
The following table lists the currently-defined versions for this The following table lists the currently-defined versions for this
UUID variant. UUID variant.
Msb0 Msb1 Msb2 Msb3 Version Description Msb0 Msb1 Msb2 Msb3 Version Description
0 0 0 1 1 The time-based version 0 0 0 1 1 The time-based version
specified in this document. specified in this document.
0 0 1 0 2 DCE Security version, with 0 0 1 0 2 DCE Security version, with
skipping to change at page 9, line 36 skipping to change at page 9, line 34
The initial value MUST NOT be correlated to the node identifier. The initial value MUST NOT be correlated to the node identifier.
For UUID version 3, it is a 14-bit value constructed from a name as For UUID version 3, it is a 14-bit value constructed from a name as
described in Section 4.3. described in Section 4.3.
For UUID version 4, it is a randomly or pseudo-randomly generated For UUID version 4, it is a randomly or pseudo-randomly generated
14-bit value as described in Section 4.4. 14-bit value as described in Section 4.4.
4.1.6 Node 4.1.6 Node
For UUID version 1, the node field consists of the IEEE address, For UUID version 1, the node field consists of an IEEE address,
usually the host address. For systems with multiple IEEE 802 usually the host address. For systems with multiple IEEE 802
addresses, any available address can be used. The lowest addressed addresses, any available address can be used. The lowest addressed
octet (octet number 10) contains the global/local bit and the octet (octet number 10) contains the global/local bit and the
unicast/multicast bit, and is the first octet of the address unicast/multicast bit, and is the first octet of the address
transmitted on an 802.3 LAN. transmitted on an 802.3 LAN.
For systems with no IEEE address, a randomly or pseudo-randomly For systems with no IEEE address, a randomly or pseudo-randomly
generated value may be used; see Section 4.5. The multicast bit must generated value may be used; see Section 4.5. The multicast bit must
be set in such addresses, in order that they will never conflict with be set in such addresses, in order that they will never conflict with
addresses obtained from network cards. addresses obtained from network cards.
skipping to change at page 13, line 35 skipping to change at page 13, line 9
The version 3 UUID is meant for generating UUIDs from "names" that The version 3 UUID is meant for generating UUIDs from "names" that
are drawn from, and unique within, some "name space." The concept of are drawn from, and unique within, some "name space." The concept of
name and name space should be broadly construed, and not limited to name and name space should be broadly construed, and not limited to
textual names. For example, some name spaces are the domain name textual names. For example, some name spaces are the domain name
system, URLs, ISO Object IDs (OIDs), X.500 Distinguished Names (DNs), system, URLs, ISO Object IDs (OIDs), X.500 Distinguished Names (DNs),
and reserved words in a programming language. The mechanisms or and reserved words in a programming language. The mechanisms or
conventions for allocating names from, and ensuring their uniqueness conventions for allocating names from, and ensuring their uniqueness
within, their name spaces are beyond the scope of this specification. within, their name spaces are beyond the scope of this specification.
The requirements for version 3 UUIDs are as follows: The requirements for version 3 UUIDs are as follows:
o The UUIDs generated at different times from the same name in the o The UUIDs generated at different times from the same name in the
same namespace MUST be equal same namespace MUST be equal
o The UUIDs generated from two different names in the same namespace o The UUIDs generated from two different names in the same namespace
should be different (with very high probability) should be different (with very high probability)
o The UUIDs generated from the same name in two different namespaces o The UUIDs generated from the same name in two different namespaces
should be different with (very high probability) should be different with (very high probability)
o If two UUIDs that were generated from names are equal, then they o If two UUIDs that were generated from names are equal, then they
were generated from the same name in the same namespace (with very were generated from the same name in the same namespace (with very
high probability). high probability).
The algorithm for generating the a UUID from a name and a name space The algorithm for generating the a UUID from a name and a name space
are as follows: are as follows:
o Allocate a UUID to use as a "name space ID" for all UUIDs o Allocate a UUID to use as a "name space ID" for all UUIDs
generated from names in that name space; see Appendix C for some generated from names in that name space; see Appendix C for some
pre-defined values pre-defined values
o Convert the name to a canonical sequence of octets (as defined by o Convert the name to a canonical sequence of octets (as defined by
the standards or conventions of its name space); put the name the standards or conventions of its name space); put the name
space ID in network byte order space ID in network byte order
o Compute the MD5 [3] hash of the name space ID concatenated with o Compute the MD5 [3] hash of the name space ID concatenated with
the name the name
o Set octets zero through three of the time_low field to octets zero o Set octets zero through three of the time_low field to octets zero
through three of the MD5 hash through three of the MD5 hash
o Set octets zero and one of the time_mid field to octets four and o Set octets zero and one of the time_mid field to octets four and
five of the MD5 hash five of the MD5 hash
o Set octets zero and one of the time_hi_and_version field to octets o Set octets zero and one of the time_hi_and_version field to octets
six and seven of the MD5 hash six and seven of the MD5 hash
o Set the four most significant bits (bits 12 through 15) of the o Set the four most significant bits (bits 12 through 15) of the
time_hi_and_version field to the four-bit version number from time_hi_and_version field to the four-bit version number from
Section 4.1.3. Section 4.1.3.
o Set the clock_seq_hi_and_reserved field to octet eight of the MD5 o Set the clock_seq_hi_and_reserved field to octet eight of the MD5
hash hash
o Set the two most significant bits (bits six and seven) of the
o Set the two most significant bits (bits 6 and 7) of the
clock_seq_hi_and_reserved to zero and one, respectively. clock_seq_hi_and_reserved to zero and one, respectively.
o Set the clock_seq_low field to octet nine of the MD5 hash o Set the clock_seq_low field to octet nine of the MD5 hash
o Set octets zero through five of the node field to octets then o Set octets zero through five of the node field to octets then
through fifteen of the MD5 hash through fifteen of the MD5 hash
o Convert the resulting UUID to local byte order. o Convert the resulting UUID to local byte order.
4.4 Algorithms for creating a UUID from truly random or pseudo-random 4.4 Algorithms for creating a UUID from truly random or pseudo-random
numbers numbers
The version 4 UUID is meant for generating UUIDs from truly-random or The version 4 UUID is meant for generating UUIDs from truly-random or
pseudo-random numbers. pseudo-random numbers.
The algorithm is as follows: The algorithm is as follows:
o Set the two most significant bits (bits six and seven) of the o Set the two most significant bits (bits six and seven) of the
clock_seq_hi_and_reserved to zero and one, respectively. clock_seq_hi_and_reserved to zero and one, respectively.
o Set the four most significant bits (bits 12 through 15) of the o Set the four most significant bits (bits 12 through 15) of the
time_hi_and_version field to the four-bit version number from time_hi_and_version field to the four-bit version number from
Section 4.1.3. Section 4.1.3.
o Set all the other bits to randomly (or pseudo-randomly) chosen o Set all the other bits to randomly (or pseudo-randomly) chosen
values. values.
See Section 4.5 for a discussion on random numbers. See Section 4.5 for a discussion on random numbers.
4.5 Node IDs that do not identify the host 4.5 Node IDs that do not identify the host
This section describes how to generate a version 1 UUID if an IEEE This section describes how to generate a version 1 UUID if an IEEE
802 address is not available, or its use is not desired. 802 address is not available, or its use is not desired.
skipping to change at page 18, line 15 skipping to change at page 17, line 4
Authors' Addresses Authors' Addresses
Paul J. Leach Paul J. Leach
Microsoft Microsoft
1 Microsoft Way 1 Microsoft Way
Redmond, WA 98052 Redmond, WA 98052
US US
Phone: +1 425-882-8080 Phone: +1 425-882-8080
EMail: paulle@microsoft.com EMail: paulle@microsoft.com
Michael Mealling Michael Mealling
VeriSign, Inc. VeriSign, Inc.
21345 Ridgetop Circle 21345 Ridgetop Circle
Dulles, VA 21345 Dulles, VA 21345
US US
Phone: +1 678-581-9656 Phone: +1 770-717-0732
EMail: michael@neonym.net
URI: http://www.verisignlabs.com URI: http://www.verisignlabs.com
Rich Salz Rich Salz
DataPower Technology, Inc. DataPower Technology, Inc.
1 Alewife Center 1 Alewife Center
Cambridge, MA 02142 Cambridge, MA 02142
US US
Phone: +1 617-864-0455 Phone: +1 617-864-0455
EMail: rsalz@datapower.com EMail: rsalz@datapower.com
skipping to change at page 19, line 18 skipping to change at page 18, line 7
** To anyone who acknowledges that this file is provided "AS IS" ** To anyone who acknowledges that this file is provided "AS IS"
** without any express or implied warranty: permission to use, copy, ** without any express or implied warranty: permission to use, copy,
** modify, and distribute this file for any purpose is hereby ** modify, and distribute this file for any purpose is hereby
** granted without fee, provided that the above copyright notices and ** granted without fee, provided that the above copyright notices and
** this notice appears in all source code copies, and that none of ** this notice appears in all source code copies, and that none of
** the names of Open Software Foundation, Inc., Hewlett-Packard ** the names of Open Software Foundation, Inc., Hewlett-Packard
** Company, or Digital Equipment Corporation be used in advertising ** Company, or Digital Equipment Corporation be used in advertising
** or publicity pertaining to distribution of the software without ** or publicity pertaining to distribution of the software without
** specific, written prior permission. Neither Open Software ** specific, written prior permission. Neither Open Software
** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital
** Equipment Corporation makes any representations about the ** Equipment Corporation makes any representations about the suitability
suitability
** of this software for any purpose. ** of this software for any purpose.
*/ */
uuid.h uuid.h
#include "copyrt.h" #include "copyrt.h"
#undef uuid_t #undef uuid_t
typedef struct { typedef struct {
unsigned32 time_low; unsigned32 time_low;
unsigned16 time_mid; unsigned16 time_mid;
skipping to change at page 19, line 44 skipping to change at page 18, line 32
} uuid_t; } uuid_t;
/* uuid_create -- generate a UUID */ /* uuid_create -- generate a UUID */
int uuid_create(uuid_t * uuid); int uuid_create(uuid_t * uuid);
/* uuid_create_from_name -- create a UUID using a "name" /* uuid_create_from_name -- create a UUID using a "name"
from a "name space" */ from a "name space" */
void uuid_create_from_name( void uuid_create_from_name(
uuid_t *uuid, /* resulting UUID */ uuid_t *uuid, /* resulting UUID */
uuid_t nsid, /* UUID of the namespace */ uuid_t nsid, /* UUID of the namespace */
void *name, /* the name from which to generate a UUID void *name, /* the name from which to generate a UUID */
*/
int namelen /* the length of the name */ int namelen /* the length of the name */
); );
/* uuid_compare -- Compare two UUID's "lexically" and return /* uuid_compare -- Compare two UUID's "lexically" and return
-1 u1 is lexically before u2 -1 u1 is lexically before u2
0 u1 is equal to u2 0 u1 is equal to u2
1 u1 is lexically after u2 1 u1 is lexically after u2
Note that lexical ordering is not temporal ordering! Note that lexical ordering is not temporal ordering!
*/ */
int uuid_compare(uuid_t *u1, uuid_t *u2); int uuid_compare(uuid_t *u1, uuid_t *u2);
uuid.c uuid.c
#include "copyrt.h" #include "copyrt.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
skipping to change at page 20, line 47 skipping to change at page 19, line 36
int f; int f;
/* acquire system-wide lock so we're alone */ /* acquire system-wide lock so we're alone */
LOCK; LOCK;
/* get time, node ID, saved state from non-volatile storage */ /* get time, node ID, saved state from non-volatile storage */
get_current_time(&timestamp); get_current_time(&timestamp);
get_ieee_node_identifier(&node); get_ieee_node_identifier(&node);
f = read_state(&clockseq, &last_time, &last_node); f = read_state(&clockseq, &last_time, &last_node);
/* if no NV state, or if clock went backwards, or node ID /* if no NV state, or if clock went backwards, or node ID changed
changed
(e.g., new network card) change clockseq */ (e.g., new network card) change clockseq */
if (!f || memcmp(&node, &last_node, sizeof node)) if (!f || memcmp(&node, &last_node, sizeof node))
clockseq = true_random(); clockseq = true_random();
else if (timestamp < last_time) else if (timestamp < last_time)
clockseq++; clockseq++;
/* save the state for next time */ /* save the state for next time */
write_state(clockseq, timestamp, node); write_state(clockseq, timestamp, node);
UNLOCK; UNLOCK;
skipping to change at page 22, line 16 skipping to change at page 21, line 4
return 0; return 0;
fread(&st, sizeof st, 1, fp); fread(&st, sizeof st, 1, fp);
fclose(fp); fclose(fp);
inited = 1; inited = 1;
} }
*clockseq = st.cs; *clockseq = st.cs;
*timestamp = st.ts; *timestamp = st.ts;
*node = st.node; *node = st.node;
return 1; return 1;
} }
/* write_state -- save UUID generator state back to non-volatile storage */
/* write_state -- save UUID generator state back to non-volatile
storage */
void write_state(unsigned16 clockseq, uuid_time_t timestamp, void write_state(unsigned16 clockseq, uuid_time_t timestamp,
uuid_node_t node) uuid_node_t node)
{ {
static int inited = 0; static int inited = 0;
static uuid_time_t next_save; static uuid_time_t next_save;
FILE* fp; FILE* fp;
if (!inited) { if (!inited) {
next_save = timestamp; next_save = timestamp;
inited = 1; inited = 1;
skipping to change at page 22, line 44 skipping to change at page 21, line 30
st.node = node; st.node = node;
if (timestamp >= next_save) { if (timestamp >= next_save) {
fp = fopen("state", "wb"); fp = fopen("state", "wb");
fwrite(&st, sizeof st, 1, fp); fwrite(&st, sizeof st, 1, fp);
fclose(fp); fclose(fp);
/* schedule next save for 10 seconds from now */ /* schedule next save for 10 seconds from now */
next_save = timestamp + (10 * 10 * 1000 * 1000); next_save = timestamp + (10 * 10 * 1000 * 1000);
} }
} }
/* get-current_time -- get time as 60-bit 100ns ticks since UUID /* get-current_time -- get time as 60-bit 100ns ticks since UUID epoch.
epoch.
Compensate for the fact that real clock resolution is Compensate for the fact that real clock resolution is
less than 100ns. */ less than 100ns. */
void get_current_time(uuid_time_t *timestamp) void get_current_time(uuid_time_t *timestamp)
{ {
static int inited = 0; static int inited = 0;
static uuid_time_t time_last; static uuid_time_t time_last;
static unsigned16 uuids_this_tick; static unsigned16 uuids_this_tick;
uuid_time_t time_now; uuid_time_t time_now;
if (!inited) { if (!inited) {
get_system_time(&time_now); get_system_time(&time_now);
uuids_this_tick = UUIDS_PER_TICK; uuids_this_tick = UUIDS_PER_TICK;
inited = 1; inited = 1;
} }
for ( ; ; ) { for ( ; ; ) {
get_system_time(&time_now); get_system_time(&time_now);
/* if clock reading changed since last UUID generated, */ /* if clock reading changed since last UUID generated, */
skipping to change at page 23, line 25 skipping to change at page 22, line 13
/* reset count of uuids gen'd with this clock reading */ /* reset count of uuids gen'd with this clock reading */
uuids_this_tick = 0; uuids_this_tick = 0;
break; break;
} }
if (uuids_this_tick < UUIDS_PER_TICK) { if (uuids_this_tick < UUIDS_PER_TICK) {
uuids_this_tick++; uuids_this_tick++;
break; break;
} }
/* going too fast for our clock; spin */ /* going too fast for our clock; spin */
} }
/* add the count of uuids to low order bits of the clock reading /* add the count of uuids to low order bits of the clock reading */
*/
*timestamp = time_now + uuids_this_tick; *timestamp = time_now + uuids_this_tick;
} }
/* true_random -- generate a crypto-quality random number. /* true_random -- generate a crypto-quality random number.
**This sample doesn't do that.** */ **This sample doesn't do that.** */
static unsigned16 true_random(void) static unsigned16 true_random(void)
{ {
static int inited = 0; static int inited = 0;
uuid_time_t time_now; uuid_time_t time_now;
if (!inited) { if (!inited) {
get_system_time(&time_now); get_system_time(&time_now);
time_now = time_now / UUIDS_PER_TICK; time_now = time_now / UUIDS_PER_TICK;
srand((unsigned int)(((time_now >> 32) ^ time_now) & srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));
0xffffffff));
inited = 1; inited = 1;
} }
return rand(); return rand();
} }
/* uuid_create_from_name -- create a UUID using a "name" from a "name /* uuid_create_from_name -- create a UUID using a "name" from a "name
space" */ space" */
void uuid_create_from_name(uuid_t *uuid, uuid_t nsid, void *name, void uuid_create_from_name(uuid_t *uuid, uuid_t nsid, void *name,
int namelen) int namelen)
skipping to change at page 24, line 23 skipping to change at page 23, line 11
MD5Init(&c); MD5Init(&c);
MD5Update(&c, &net_nsid, sizeof net_nsid); MD5Update(&c, &net_nsid, sizeof net_nsid);
MD5Update(&c, name, namelen); MD5Update(&c, name, namelen);
MD5Final(hash, &c); MD5Final(hash, &c);
/* the hash is in network byte order at this point */ /* the hash is in network byte order at this point */
format_uuid_v3(uuid, hash); format_uuid_v3(uuid, hash);
} }
/* format_uuid_v3 -- make a UUID from a (pseudo)random 128-bit number /* format_uuid_v3 -- make a UUID from a (pseudo)random 128-bit number */
*/
void format_uuid_v3(uuid_t *uuid, unsigned char hash[16]) void format_uuid_v3(uuid_t *uuid, unsigned char hash[16])
{ {
/* convert UUID to local byte order */ /* convert UUID to local byte order */
memcpy(uuid, hash, sizeof *uuid); memcpy(uuid, hash, sizeof *uuid);
ntohl(uuid->time_low); ntohl(uuid->time_low);
ntohs(uuid->time_mid); ntohs(uuid->time_mid);
ntohs(uuid->time_hi_and_version); ntohs(uuid->time_hi_and_version);
/* put in the variant and version bits */ /* put in the variant and version bits */
uuid->time_hi_and_version &= 0x0FFF; uuid->time_hi_and_version &= 0x0FFF;
skipping to change at page 24, line 49 skipping to change at page 23, line 36
/* uuid_compare -- Compare two UUID's "lexically" and return */ /* uuid_compare -- Compare two UUID's "lexically" and return */
#define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
int uuid_compare(uuid_t *u1, uuid_t *u2) int uuid_compare(uuid_t *u1, uuid_t *u2)
{ {
int i; int i;
CHECK(u1->time_low, u2->time_low); CHECK(u1->time_low, u2->time_low);
CHECK(u1->time_mid, u2->time_mid); CHECK(u1->time_mid, u2->time_mid);
CHECK(u1->time_hi_and_version, u2->time_hi_and_version); CHECK(u1->time_hi_and_version, u2->time_hi_and_version);
CHECK(u1->clock_seq_hi_and_reserved, CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved);
u2->clock_seq_hi_and_reserved);
CHECK(u1->clock_seq_low, u2->clock_seq_low) CHECK(u1->clock_seq_low, u2->clock_seq_low)
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
if (u1->node[i] < u2->node[i]) if (u1->node[i] < u2->node[i])
return -1; return -1;
if (u1->node[i] > u2->node[i]) if (u1->node[i] > u2->node[i])
return 1; return 1;
} }
return 0; return 0;
} }
#undef CHECK #undef CHECK
skipping to change at page 27, line 4 skipping to change at page 25, line 40
if (fp) { if (fp) {
fwrite(&saved_node, sizeof saved_node, 1, fp); fwrite(&saved_node, sizeof saved_node, 1, fp);
fclose(fp); fclose(fp);
} }
} }
inited = 1; inited = 1;
} }
*node = saved_node; *node = saved_node;
} }
/* system dependent call to get the current system time. Returned as /* system dependent call to get the current system time. Returned as
100ns ticks since UUID epoch, but resolution may be less than 100ns ticks since UUID epoch, but resolution may be less than 100ns. */
100ns. */
#ifdef _WINDOWS_ #ifdef _WINDOWS_
void get_system_time(uuid_time_t *uuid_time) void get_system_time(uuid_time_t *uuid_time)
{ {
ULARGE_INTEGER time; ULARGE_INTEGER time;
/* NT keeps time in FILETIME format which is 100ns ticks since /* NT keeps time in FILETIME format which is 100ns ticks since
Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
+ 18 years and 5 leap days. */ + 18 years and 5 leap days. */
skipping to change at page 28, line 12 skipping to change at page 26, line 49
void get_system_time(uuid_time_t *uuid_time) void get_system_time(uuid_time_t *uuid_time)
{ {
struct timeval tp; struct timeval tp;
gettimeofday(&tp, (struct timezone *)0); gettimeofday(&tp, (struct timezone *)0);
/* Offset between UUID formatted times and Unix formatted times. /* Offset between UUID formatted times and Unix formatted times.
UUID UTC base time is October 15, 1582. UUID UTC base time is October 15, 1582.
Unix base time is January 1, 1970.*/ Unix base time is January 1, 1970.*/
*uuid_time = (tp.tv_sec * 10000000) + (tp.tv_usec * 10) *uuid_time = ((unsigned64)tp.tv_sec * 10000000)
+ ((unsigned64)tp.tv_usec * 10)
+ I64(0x01B21DD213814000); + I64(0x01B21DD213814000);
} }
void get_random_info(char seed[16]) void get_random_info(char seed[16])
{ {
MD5_CTX c; MD5_CTX c;
struct { struct {
struct sysinfo s; struct sysinfo s;
struct timeval t; struct timeval t;
char hostname[257]; char hostname[257];
} r; } r;
skipping to change at page 31, line 29 skipping to change at page 30, line 29
be obtained from the IETF Secretariat. be obtained from the IETF Secretariat.
The IETF invites any interested party to bring to its attention any The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary copyrights, patents or patent applications, or other proprietary
rights which may cover technology that may be required to practice rights which may cover technology that may be required to practice
this standard. Please address the information to the IETF Executive this standard. Please address the information to the IETF Executive
Director. Director.
Full Copyright Statement Full Copyright Statement
Copyright (C) The Internet Society (2003). All Rights Reserved. Copyright (C) The Internet Society (2004). All Rights Reserved.
This document and translations of it may be copied and furnished to This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of Internet organizations, except as needed for the purpose of
skipping to change at page 32, line 7 skipping to change at page 31, line 7
The limited permissions granted above are perpetual and will not be The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assignees. revoked by the Internet Society or its successors or assignees.
This document and the information contained herein is provided on an This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement Acknowledgment
Funding for the RFC Editor function is currently provided by the Funding for the RFC Editor function is currently provided by the
Internet Society. Internet Society.
 End of changes. 51 change blocks. 
70 lines changed or deleted 44 lines changed or added

This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/