From c3bb7dc2940a3aaa6555c235a0427358d592f779 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Wed, 9 Nov 2022 16:41:34 +0000 Subject: [PATCH] guid_new() returns GUIDs compatible with RFC4122 --- common/guid.c | 16 ++++++++++++++++ common/guid.h | 21 +++++++++++++++++++-- tests/common/test_guid.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/common/guid.c b/common/guid.c index cf863648..e614ebe4 100644 --- a/common/guid.c +++ b/common/guid.c @@ -30,11 +30,27 @@ #include "os_calls.h" #include "string_calls.h" +enum +{ + /* Field offsets in the UUID */ + E_CLOCK_SEQ_HI_AND_RESERVED = 8, + E_TIME_HI_AND_VERSION_MSB = 7, + /* UUID versions from RFC4122 section 4.1.3 */ + E_UUID_VERSION_RANDOM = 4 +}; + struct guid guid_new(void) { struct guid guid = {0}; g_random(guid.g, sizeof(guid.g)); + /* Show this UUID as conforming to RFC4122 (section 4.1.1) */ + guid.g[E_CLOCK_SEQ_HI_AND_RESERVED] &= ~0x40; /* Clear bit 6 */ + guid.g[E_CLOCK_SEQ_HI_AND_RESERVED] |= (char)0x80; /* Set bit 7 */ + + guid.g[E_TIME_HI_AND_VERSION_MSB] &= ~0xf0; + guid.g[E_TIME_HI_AND_VERSION_MSB] |= (E_UUID_VERSION_RANDOM << 4); + return guid; } diff --git a/common/guid.h b/common/guid.h index 2951fa12..1d53935a 100644 --- a/common/guid.h +++ b/common/guid.h @@ -32,8 +32,23 @@ /** - * Use a struct for the guid so we can easily copy by assignment - */ + * Use a struct for the guid so we can easily copy by assignment. + * We use an array of char so that + * we can compare GUIDs with a straight memcmp() + * + * Some fields of the GUID are in little-endian-order as specified by + * [MS-DTYP]. This is at odds with RFC4122 which specifies big-endian + * order for all fields. + * + * Octets RFC4122 field + * ------ ------------- + * 0-3 time_low (little-endian) + * 4-5 time_mid (little-endian) + * 6-7 time_hi_and_version (little-endian) + * 8 clock_seq_hi_and_reserved + * 9 clock_seq_low (in order) + * 10-15 node + */ struct guid { char g[GUID_SIZE]; @@ -42,6 +57,8 @@ struct guid /** * Get an initialised GUID * + * The GUID is compatible with RFC4122 section 4.4. + * * @return new GUID */ struct guid guid_new(void); diff --git a/tests/common/test_guid.c b/tests/common/test_guid.c index 7580bb95..ed3ccc1a 100644 --- a/tests/common/test_guid.c +++ b/tests/common/test_guid.c @@ -57,6 +57,42 @@ START_TEST(test_guid_to_str_ignore) } END_TEST +START_TEST(test_guid_to_str_random) +{ + /* setup */ + char dest[GUID_STR_SIZE]; + struct guid guid; + unsigned int i; + for (i = 0 ; i < 100; ++i) + { + guid = guid_new(); + /* test */ + guid_to_str(&guid, dest); + + /* Check all the '-' signs are in the right places */ + ck_assert_int_eq(dest[8], '-'); + ck_assert_int_eq(dest[13], '-'); + ck_assert_int_eq(dest[18], '-'); + ck_assert_int_eq(dest[23], '-'); + + /* Check the variant is RFC4122 */ + char c = dest[18 + 1]; /* char after 3rd dash */ + if (c != '8' && c != '9' && c != 'A' && c != 'B') + { + ck_abort_msg("Generated UUID is not RFC4122 compliant"); + } + + /* Check the version is 'randomly generated' */ + c = dest[13 + 1]; /* char after 2nd dash */ + if (c != '4') + { + ck_abort_msg("Generated UUID is not RFC4122 randomly-generated"); + } + + } +} +END_TEST + /******************************************************************************/ Suite * @@ -72,6 +108,7 @@ make_suite_test_guid(void) tcase_add_test(tc_guid, test_guid_to_str_remotefx); tcase_add_test(tc_guid, test_guid_to_str_nscodec); tcase_add_test(tc_guid, test_guid_to_str_ignore); + tcase_add_test(tc_guid, test_guid_to_str_random); return s; }