Commit 3c34f1d9 authored by Dan Williams's avatar Dan Williams

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.
parent cd12e976
......@@ -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;
}
......@@ -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__ */
......@@ -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 \
......
......@@ -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 ();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment