summary refs log tree commit diff
path: root/src/dhcp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcp')
-rw-r--r--src/dhcp/nm-dhcp-client.c68
-rw-r--r--src/dhcp/nm-dhcp-client.h9
-rw-r--r--src/dhcp/nm-dhcp-dhclient-utils.c8
-rw-r--r--src/dhcp/nm-dhcp-systemd.c18
-rw-r--r--src/dhcp/nm-dhcp-utils.c9
5 files changed, 85 insertions, 27 deletions
diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c
index 20ea092f..ea3938d6 100644
--- a/src/dhcp/nm-dhcp-client.c
+++ b/src/dhcp/nm-dhcp-client.c
@@ -186,19 +186,70 @@ nm_dhcp_client_get_client_id (NMDhcpClient *self)
 	return NM_DHCP_CLIENT_GET_PRIVATE (self)->client_id;
 }
 
+static void
+_set_client_id (NMDhcpClient *self, GBytes *client_id, gboolean take)
+{
+	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
+
+	nm_assert (!client_id || g_bytes_get_size (client_id) >= 2);
+
+	if (   priv->client_id == client_id
+	    || (   priv->client_id
+	        && client_id
+	        && g_bytes_equal (priv->client_id, client_id))) {
+		if (take && client_id)
+			g_bytes_unref (client_id);
+		return;
+	}
+
+	if (priv->client_id)
+		g_bytes_unref (priv->client_id);
+	priv->client_id = client_id;
+	if (!take && client_id)
+		g_bytes_ref (client_id);
+}
+
 void
 nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id)
 {
-	NMDhcpClientPrivate *priv;
+	g_return_if_fail (NM_IS_DHCP_CLIENT (self));
+	g_return_if_fail (!client_id || g_bytes_get_size (client_id) >= 2);
+
+	_set_client_id (self, client_id, FALSE);
+}
+
+void
+nm_dhcp_client_set_client_id_bin (NMDhcpClient *self,
+                                  guint8 type,
+                                  const guint8 *client_id,
+                                  gsize len)
+{
+	guint8 *buf;
+	GBytes *b;
 
 	g_return_if_fail (NM_IS_DHCP_CLIENT (self));
+	g_return_if_fail (client_id);
+	g_return_if_fail (len > 0);
+
+	buf = g_malloc (len + 1);
+	buf[0] = type;
+	memcpy (buf + 1, client_id, len);
+	b = g_bytes_new_take (buf, len + 1);
+	_set_client_id (self, b, TRUE);
+}
 
-	priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
+void
+nm_dhcp_client_set_client_id_str (NMDhcpClient *self,
+                                  const char *dhcp_client_id)
+{
+	g_return_if_fail (NM_IS_DHCP_CLIENT (self));
+	g_return_if_fail (!dhcp_client_id || dhcp_client_id[0]);
 
-	if (priv->client_id && client_id && g_bytes_equal (priv->client_id, client_id))
-		return;
-	g_clear_pointer (&priv->client_id, g_bytes_unref);
-	priv->client_id = client_id ? g_bytes_ref (client_id) : NULL;
+	_set_client_id (self,
+	                dhcp_client_id
+	                  ? nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id)
+	                  : NULL,
+	                TRUE);
 }
 
 const char *
@@ -448,7 +499,6 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self,
                           const char *last_ip4_address)
 {
 	NMDhcpClientPrivate *priv;
-	gs_unref_bytes GBytes *tmp = NULL;
 
 	g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
 
@@ -462,9 +512,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self,
 	else
 		_LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
 
-	if (dhcp_client_id)
-		tmp = nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id);
-	nm_dhcp_client_set_client_id (self, tmp);
+	nm_dhcp_client_set_client_id_str (self, dhcp_client_id);
 
 	g_clear_pointer (&priv->hostname, g_free);
 	priv->hostname = g_strdup (hostname);
diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h
index 02804002..2c634168 100644
--- a/src/dhcp/nm-dhcp-client.h
+++ b/src/dhcp/nm-dhcp-client.h
@@ -173,7 +173,14 @@ gboolean nm_dhcp_client_handle_event (gpointer unused,
                                       const char *reason,
                                       NMDhcpClient *self);
 
-void nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id);
+void nm_dhcp_client_set_client_id (NMDhcpClient *self,
+                                   GBytes *client_id);
+void nm_dhcp_client_set_client_id_bin (NMDhcpClient *self,
+                                       guint8 type,
+                                       const guint8 *client_id,
+                                       gsize len);
+void nm_dhcp_client_set_client_id_str (NMDhcpClient *self,
+                                       const char *dhcp_client_id);
 
 /*****************************************************************************
  * Client data
diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c
index e63e6a86..4df90d76 100644
--- a/src/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/dhcp/nm-dhcp-dhclient-utils.c
@@ -178,7 +178,7 @@ read_client_id (const char *str)
 	gs_free char *s = NULL;
 	char *p;
 
-	g_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
+	nm_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
 
 	str += NM_STRLEN (CLIENTID_TAG);
 	while (g_ascii_isspace (*str))
@@ -198,6 +198,9 @@ read_client_id (const char *str)
 	if (s[strlen (s) - 1] == ';')
 		s[strlen (s) - 1] = '\0';
 
+	if (!s[0])
+		return NULL;
+
 	return nm_dhcp_utils_client_id_string_to_bytes (s);
 }
 
@@ -329,8 +332,7 @@ nm_dhcp_dhclient_create_config (const char *interface,
 					continue;
 
 				/* Otherwise capture and return the existing client id */
-				if (out_new_client_id)
-					*out_new_client_id = read_client_id (p);
+				NM_SET_OUT (out_new_client_id, read_client_id (p));
 			}
 
 			/* Override config file hostname and use one from the connection */
diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c
index 9b1a4433..f79b7cb1 100644
--- a/src/dhcp/nm-dhcp-systemd.c
+++ b/src/dhcp/nm-dhcp-systemd.c
@@ -489,19 +489,13 @@ _save_client_id (NMDhcpSystemd *self,
                  const uint8_t *client_id,
                  size_t len)
 {
-	gs_unref_bytes GBytes *b = NULL;
-	gs_free char *buf = NULL;
-
 	g_return_if_fail (self != NULL);
 	g_return_if_fail (client_id != NULL);
 	g_return_if_fail (len > 0);
 
 	if (!nm_dhcp_client_get_client_id (NM_DHCP_CLIENT (self))) {
-		buf = g_malloc (len + 1);
-		buf[0] = type;
-		memcpy (buf + 1, client_id, len);
-		b = g_bytes_new (buf, len + 1);
-		nm_dhcp_client_set_client_id (NM_DHCP_CLIENT (self), b);
+		nm_dhcp_client_set_client_id_bin (NM_DHCP_CLIENT (self),
+		                                  type, client_id, len);
 	}
 }
 
@@ -543,7 +537,7 @@ bound4_handle (NMDhcpSystemd *self)
 		add_requests_to_options (options, dhcp4_requests);
 		dhcp_lease_save (lease, priv->lease_file);
 
-		sd_dhcp_client_get_client_id(priv->client4, &type, &client_id, &client_id_len);
+		sd_dhcp_client_get_client_id (priv->client4, &type, &client_id, &client_id_len);
 		if (client_id)
 			_save_client_id (self, type, client_id, client_id_len);
 
@@ -691,14 +685,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 	override_client_id = nm_dhcp_client_get_client_id (client);
 	if (override_client_id) {
 		client_id = g_bytes_get_data (override_client_id, &client_id_len);
-		g_assert (client_id && client_id_len);
+		nm_assert (client_id && client_id_len >= 2);
 		sd_dhcp_client_set_client_id (priv->client4,
 		                              client_id[0],
 		                              client_id + 1,
-		                              client_id_len - 1);
+		                              NM_MIN (client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN));
 	} else if (lease) {
 		r = sd_dhcp_lease_get_client_id (lease, (const void **) &client_id, &client_id_len);
-		if (r == 0 && client_id_len) {
+		if (r == 0 && client_id_len >= 2) {
 			sd_dhcp_client_set_client_id (priv->client4,
 			                              client_id[0],
 			                              client_id + 1,
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
index 4b2d57b9..50ca2abe 100644
--- a/src/dhcp/nm-dhcp-utils.c
+++ b/src/dhcp/nm-dhcp-utils.c
@@ -750,8 +750,15 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id)
 	g_return_val_if_fail (client_id && client_id[0], NULL);
 
 	/* Try as hex encoded */
-	if (strchr (client_id, ':'))
+	if (strchr (client_id, ':')) {
 		bytes = nm_utils_hexstr2bin (client_id);
+
+		/* the result must be at least two bytes long,
+		 * because @client_id contains a delimiter
+		 * but nm_utils_hexstr2bin() does not allow
+		 * leading nor trailing delimiters. */
+		nm_assert (!bytes || g_bytes_get_size (bytes) >= 2);
+	}
 	if (!bytes) {
 		/* Fall back to string */
 		len = strlen (client_id);