diff options
author | Dan Williams <dcbw@redhat.com> | 2014-11-03 15:16:31 -0600 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2014-11-06 21:58:32 -0600 |
commit | 3c34f1d92fb1f8cb01e3d54216d80eb2dd85cedf (patch) | |
tree | ce115a1ddcd139b4dd361990371fd2f63d8140e8 /src/dhcp-manager | |
parent | cd12e97620faffeb76ba1fff85867a3cdb8a4ea8 (diff) | |
download | NetworkManager-3c34f1d92fb1f8cb01e3d54216d80eb2dd85cedf.tar.gz |
dhcp: add nm_dhcp_utils_client_id_string_to_bytes()
Generic function to convert a DHCP client identifier string in either
hex form ("aa:bb:cc") or string form ("blahblah") to bytes.
Diffstat (limited to 'src/dhcp-manager')
-rw-r--r-- | src/dhcp-manager/nm-dhcp-utils.c | 65 | ||||
-rw-r--r-- | src/dhcp-manager/nm-dhcp-utils.h | 2 | ||||
-rw-r--r-- | src/dhcp-manager/tests/Makefile.am | 12 | ||||
-rw-r--r-- | src/dhcp-manager/tests/test-dhcp-utils.c (renamed from src/dhcp-manager/tests/test-dhcp-options.c) | 37 |
4 files changed, 110 insertions, 6 deletions
diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c index 014937f6ea..02fc4fe513 100644 --- a/src/dhcp-manager/nm-dhcp-utils.c +++ b/src/dhcp-manager/nm-dhcp-utils.c @@ -692,3 +692,68 @@ nm_dhcp_utils_duid_to_string (const GByteArray *duid) return g_string_free (s, FALSE); } +/** + * nm_dhcp_utils_client_id_string_to_bytes: + * @client_id: the client ID string + * + * Accepts either a hex string ("aa:bb:cc") representing a binary client ID + * (the first byte is assumed to be the 'type' field per RFC 2132 section 9.14), + * or a string representing a non-hardware-address client ID, in which case + * the 'type' field is set to 0. + * + * Returns: the binary client ID suitable for sending over the wire + * to the DHCP server. + */ +GBytes * +nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) +{ + GBytes *bytes = NULL; + guint i = 0, x = 0; + guint len; + char *c; + int a; + + g_return_val_if_fail (client_id && client_id[0], NULL); + + /* Accept a binary client ID in hex digits with the ':' delimiter, + * otherwise treat it as a string. + */ + len = strlen (client_id); + c = g_malloc0 (len / 2 + 1); + while (client_id[i]) { + a = g_ascii_xdigit_value (client_id[i++]); + if (a >= 0) { + if (client_id[i] != ':') { + c[x] = ((guint8) a << 4); + a = g_ascii_xdigit_value (client_id[i++]); + } + if (a >= 0) + c[x++] |= (guint8) a; + } + if (client_id[i]) { + if (client_id[i] != ':' || !client_id[i + 1]) { + /* missing or trailing ':' is invalid for hex-format */ + a = -1; + } + i++; + } + + if (a < 0) { + g_clear_pointer (&c, g_free); + break; + } + } + + if (c) { + g_assert (x > 0); + bytes = g_bytes_new_take (c, x); + } else { + c = g_malloc (len + 1); + c[0] = 0; /* type: non-hardware address per RFC 2132 section 9.14 */ + memcpy (c + 1, client_id, len); + bytes = g_bytes_new_take (c, len + 1); + } + + return bytes; +} + diff --git a/src/dhcp-manager/nm-dhcp-utils.h b/src/dhcp-manager/nm-dhcp-utils.h index ab9d45fe4b..a01cf4c267 100644 --- a/src/dhcp-manager/nm-dhcp-utils.h +++ b/src/dhcp-manager/nm-dhcp-utils.h @@ -35,5 +35,7 @@ NMIP6Config *nm_dhcp_utils_ip6_config_from_options (const char *iface, char * nm_dhcp_utils_duid_to_string (const GByteArray *duid); +GBytes * nm_dhcp_utils_client_id_string_to_bytes (const char *client_id); + #endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */ diff --git a/src/dhcp-manager/tests/Makefile.am b/src/dhcp-manager/tests/Makefile.am index 9d6e7b97b4..0292db2b7a 100644 --- a/src/dhcp-manager/tests/Makefile.am +++ b/src/dhcp-manager/tests/Makefile.am @@ -13,7 +13,7 @@ AM_CPPFLAGS = \ noinst_PROGRAMS = \ test-dhcp-dhclient \ - test-dhcp-options + test-dhcp-utils ####### dhclient leases test ####### @@ -23,17 +23,17 @@ test_dhcp_dhclient_SOURCES = \ test_dhcp_dhclient_LDADD = \ $(top_builddir)/src/libNetworkManager.la -####### DHCP options test ####### +####### DHCP utils test ####### -test_dhcp_options_SOURCES = \ - test-dhcp-options.c +test_dhcp_utils_SOURCES = \ + test-dhcp-utils.c -test_dhcp_options_LDADD = \ +test_dhcp_utils_LDADD = \ $(top_builddir)/src/libNetworkManager.la ################################# -TESTS = test-dhcp-dhclient test-dhcp-options +TESTS = test-dhcp-dhclient test-dhcp-utils EXTRA_DIST = \ test-dhclient-duid.leases \ diff --git a/src/dhcp-manager/tests/test-dhcp-options.c b/src/dhcp-manager/tests/test-dhcp-utils.c index 15f5ee60b5..6ed10e0474 100644 --- a/src/dhcp-manager/tests/test-dhcp-options.c +++ b/src/dhcp-manager/tests/test-dhcp-utils.c @@ -652,6 +652,42 @@ test_ip4_prefix_classless (void) g_hash_table_destroy (options); } +#define COMPARE_ID(src, is_str, expected, expected_len) \ +G_STMT_START { \ + gs_unref_bytes GBytes *b = NULL; \ + gconstpointer p; \ + gsize l; \ + \ + b = nm_dhcp_utils_client_id_string_to_bytes (src); \ + g_assert (b); \ + p = g_bytes_get_data (b, &l); \ + if (is_str) { \ + g_assert_cmpint (l, ==, expected_len + 1); \ + g_assert_cmpint (((const char *) p)[0], ==, 0); \ + g_assert (memcmp (p + 1, expected, expected_len) == 0); \ + } else { \ + g_assert_cmpint (l, ==, expected_len); \ + g_assert (memcmp (p, expected, expected_len) == 0); \ + } \ +} G_STMT_END + +static void +test_client_id_from_string (void) +{ + const char *nothex = "asdfasdfasdfasdfasdfasdfasdf"; + const char *allhex = "00:11:22:33:4:55:66:77:88"; + const guint8 allhex_bin[] = { 0x00, 0x11, 0x22, 0x33, 0x04, 0x55, 0x66, 0x77, 0x88 }; + const char *somehex = "00:11:22:33:44:55:asdfasdfasdf:99:10"; + const char *nocolons = "0011223344559910"; + const char *endcolon = "00:11:22:33:44:55:"; + + COMPARE_ID (nothex, TRUE, nothex, strlen (nothex)); + COMPARE_ID (allhex, FALSE, allhex_bin, sizeof (allhex_bin)); + COMPARE_ID (somehex, TRUE, somehex, strlen (somehex)); + COMPARE_ID (nocolons, TRUE, nocolons, strlen (nocolons)); + COMPARE_ID (endcolon, TRUE, endcolon, strlen (endcolon)); +} + NMTST_DEFINE (); int main (int argc, char **argv) @@ -678,6 +714,7 @@ int main (int argc, char **argv) g_test_add_func ("/dhcp/ip4-missing-prefix-16", test_ip4_missing_prefix_16); g_test_add_func ("/dhcp/ip4-missing-prefix-8", test_ip4_missing_prefix_8); g_test_add_func ("/dhcp/ip4-prefix-classless", test_ip4_prefix_classless); + g_test_add_func ("/dhcp/client-id-from-string", test_client_id_from_string); return g_test_run (); } |