Index: ossp-pkg/uuid/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/ChangeLog,v rcsdiff -q -kk '-r1.16' '-r1.17' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/ChangeLog,v' 2>/dev/null --- ChangeLog 2004/01/15 15:38:47 1.16 +++ ChangeLog 2004/01/15 16:22:09 1.17 @@ -13,6 +13,15 @@ Changes between 0.9.1 and 0.9.2 (13-Jan-2004 to xx-Jan-2004) + o Provide both incorrect RFC2518-based and correct IEEE 802 + multicast address generation. The default now is the correct + IEEE 802 multicast address generation but compile-time option + --with-rfc2518 selects the broken variant. + [Ralf S. Engelschall] + + o Decode also the IEEE 802 MAC address local/global bit. + [Ralf S. Engelschall] + o Added missing documentation for uuid_dump(). [Ralf S. Engelschall] Index: ossp-pkg/uuid/uuid.ac RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.ac,v rcsdiff -q -kk '-r1.7' '-r1.8' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.ac,v' 2>/dev/null --- uuid.ac 2004/01/15 12:43:52 1.7 +++ uuid.ac 2004/01/15 16:22:09 1.8 @@ -69,5 +69,13 @@ AC_CHECK_SIZEOF(unsigned long, 4) AC_CHECK_SIZEOF(long long, 8) AC_CHECK_SIZEOF(unsigned long long, 8) + + dnl # options + AC_ARG_WITH(rfc2518, + AC_HELP_STRING([--with-rfc2518], [use incorrect generation of IEEE 802 multicast addresses according to RFC2518]), + [ac_cv_with_rfc2518=$withval], [ac_cv_with_rfc2518=no]) + if test ".$ac_cv_with_rfc2518" == .yes; then + AC_DEFINE(WITH_RFC2518, 1, [whether to use incorrect generation of IEEE 802 multicast addresses according to RFC2518]) + fi ]) Index: ossp-pkg/uuid/uuid.c RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.c,v rcsdiff -q -kk '-r1.27' '-r1.28' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.c,v' 2>/dev/null --- uuid.c 2004/01/15 15:29:36 1.27 +++ uuid.c 2004/01/15 16:22:09 1.28 @@ -427,6 +427,65 @@ Unix UTC base time is January 1, 1970) */ #define UUID_TIMEOFFSET "01B21DD213814000" +/* + * ATTENTION: + * + * In case no real/physical IEEE 802 address is available, both + * "draft-leach-uuids-guids-01" (section "4. Node IDs when no IEEE 802 + * network card is available") and RFC 2518 (section "6.4.1 Node Field + * Generation Without the IEEE 802 Address") recommend (quoted from RFC + * 2518): + * + * "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 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." + * + * This clearly explains what the intention is. Unfortunately, it + * explains it incorrectly how to achieve this. Because (see also + * http://www.iana.org/assignments/ethernet-numbers and "Understanding + * Physical Addresses" in "Ethernet -- The Definitive Guide", p.43) it + * is the "LEAST significant bit of the first octet of the node ID" in a + * memory representation of a 48-bit MAC address. The reason is that it + * is the MOST significant bit only in IEEE 802.3 _transmission order_ + * of a MAC address. The memory order of an octet from a MAC address is + * always with the bits from left/MSB/bit-7 to right/LSB/bit-0! + * + * Unfortunately, even the reference code in + * "draft-leach-uuids-guids-01" incorrectly sets the multicast bit with + * an "OR 0x80" bit operation. This could be considered "standards + * compliant" (because the exact wording above is "with the most + * significant bit"), but from the remaining explanation it becomes 100% + * clear that the intention was different and the wording and code was + * incorrect because the authors were unaware of this difference in bit + * ordering between memory and wire transmission. + * + * So, OSSP uuid does it the intended/correct way and generates a real + * IEEE 802 multicast address, but with a compile-time option one can + * nevertheless enforce the generation of incorrect addresses according + * to the standards. For the decoding we always use the correct way, of + * course. + * + * Luckily, both DCE 1.1 and ISO/IEC 11578:1996 do not deal with the + * situation of not available IEEE 802 addresses at all and so have + * avoided to adopt this bug from the original draft and code ;-) + */ + +/* encoding */ +#ifdef WITH_RFC2518 +#define IEEE_MAC_MCBIT_ENC BM_OCTET(1,0,0,0,0,0,0,0) +#else +#define IEEE_MAC_MCBIT_ENC BM_OCTET(0,0,0,0,0,0,0,1) +#endif +#define IEEE_MAC_LOBIT_ENC BM_OCTET(0,0,0,0,0,0,1,0) + +/* decoding */ +#define IEEE_MAC_MCBIT_DEC BM_OCTET(0,0,0,0,0,0,0,1) +#define IEEE_MAC_LOBIT_DEC BM_OCTET(0,0,0,0,0,0,1,0) + /* INTERNAL: generate UUID version 1: time, clock and node based */ static uuid_rc_t uuid_generate_v1(uuid_t *uuid, unsigned int mode, va_list ap) { @@ -536,9 +595,10 @@ */ if ((mode & UUID_MCASTRND) || (uuid->mac[0] & BM_OCTET(1,0,0,0,0,0,0,0))) { - /* use random multi-cast MAC address */ + /* generate random IEEE 802 local multicast MAC address */ prng_data(uuid->prng, (void *)&(uuid->obj.node), sizeof(uuid->obj.node)); - uuid->obj.node[0] |= BM_OCTET(1,0,0,0,0,0,0,0); + uuid->obj.node[0] |= IEEE_MAC_MCBIT_ENC; + uuid->obj.node[0] |= IEEE_MAC_LOBIT_ENC; } else { /* use real regular MAC address */ @@ -784,14 +844,15 @@ str_rsprintf(str, " clock: %ld (usually random)\n", (unsigned long)tmp32); /* decode node MAC address */ - str_rsprintf(str, " node: %02x:%02x:%02x:%02x:%02x:%02x (%s)\n", + str_rsprintf(str, " node: %02x:%02x:%02x:%02x:%02x:%02x (%s %s)\n", (unsigned int)uuid->obj.node[0], (unsigned int)uuid->obj.node[1], (unsigned int)uuid->obj.node[2], (unsigned int)uuid->obj.node[3], (unsigned int)uuid->obj.node[4], (unsigned int)uuid->obj.node[5], - (uuid->obj.node[0] & 0x80 ? "random multicast" : "real unicast")); + (uuid->obj.node[0] & IEEE_MAC_LOBIT_DEC ? "local" : "global"), + (uuid->obj.node[0] & IEEE_MAC_MCBIT_DEC ? "multicast" : "unicast")); } else if (tmp16 == 3) { /* decode version 3 */