summaryrefslogtreecommitdiff
path: root/src/dhcp-manager
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-11-03 15:16:31 -0600
committerDan Williams <dcbw@redhat.com>2014-11-06 21:58:32 -0600
commit3c34f1d92fb1f8cb01e3d54216d80eb2dd85cedf (patch)
treece115a1ddcd139b4dd361990371fd2f63d8140e8 /src/dhcp-manager
parentcd12e97620faffeb76ba1fff85867a3cdb8a4ea8 (diff)
downloadNetworkManager-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.c65
-rw-r--r--src/dhcp-manager/nm-dhcp-utils.h2
-rw-r--r--src/dhcp-manager/tests/Makefile.am12
-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 ();
}