Blame SOURCES/1019-dhcp-client-id-for-infiniband-rh1658057.patch

f86c11
From 700afdb5ebf0109e41aaad18f5701c06660331b7 Mon Sep 17 00:00:00 2001
f86c11
From: Thomas Haller <thaller@redhat.com>
f86c11
Date: Fri, 14 Dec 2018 08:45:09 +0100
f86c11
Subject: [PATCH 1/2] core: add nm_utils_detect_arp_type_from_addrlen() helper
f86c11
f86c11
and use it in "nm-dhcp-systemd.c".
f86c11
f86c11
(cherry picked from commit 6e48e99be4fe11e9bf1e2c2a20b1caadb63377d3)
f86c11
(cherry picked from commit 17e7eba7a35e419a8654df19cc170df236c0e4ea)
f86c11
---
f86c11
 src/dhcp/nm-dhcp-systemd.c | 25 ++++++-------------------
f86c11
 src/nm-core-utils.c        | 28 ++++++++++++++++++++++++++++
f86c11
 src/nm-core-utils.h        |  2 ++
f86c11
 3 files changed, 36 insertions(+), 19 deletions(-)
f86c11
f86c11
diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c
f86c11
index facd59886..1e123117d 100644
f86c11
--- a/src/dhcp/nm-dhcp-systemd.c
f86c11
+++ b/src/dhcp/nm-dhcp-systemd.c
f86c11
@@ -530,19 +530,6 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
f86c11
 	}
f86c11
 }
f86c11
 
f86c11
-static guint16
f86c11
-get_arp_type (gsize hwaddr_len)
f86c11
-{
f86c11
-	switch (hwaddr_len) {
f86c11
-	case ETH_ALEN:
f86c11
-		return ARPHRD_ETHER;
f86c11
-	case INFINIBAND_ALEN:
f86c11
-		return ARPHRD_INFINIBAND;
f86c11
-	default:
f86c11
-		return ARPHRD_NONE;
f86c11
-	}
f86c11
-}
f86c11
-
f86c11
 static gboolean
f86c11
 ip4_start (NMDhcpClient *client,
f86c11
            const char *dhcp_anycast_addr,
f86c11
@@ -556,7 +543,7 @@ ip4_start (NMDhcpClient *client,
f86c11
 	GBytes *hwaddr;
f86c11
 	const uint8_t *hwaddr_arr;
f86c11
 	gsize hwaddr_len;
f86c11
-	guint16 arptype;
f86c11
+	int arp_type;
f86c11
 	GBytes *client_id;
f86c11
 	gs_unref_bytes GBytes *client_id_new = NULL;
f86c11
 	const uint8_t *client_id_arr;
f86c11
@@ -585,14 +572,14 @@ ip4_start (NMDhcpClient *client,
f86c11
 	hwaddr = nm_dhcp_client_get_hw_addr (client);
f86c11
 	if (   !hwaddr
f86c11
 	    || !(hwaddr_arr = g_bytes_get_data (hwaddr, &hwaddr_len))
f86c11
-	    || (arptype = get_arp_type (hwaddr_len)) == ARPHRD_NONE) {
f86c11
+	    || (arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len)) < 0) {
f86c11
 		nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
f86c11
 		return FALSE;
f86c11
 	}
f86c11
 	r = sd_dhcp_client_set_mac (sd_client,
f86c11
 	                            hwaddr_arr,
f86c11
 	                            hwaddr_len,
f86c11
-	                            arptype);
f86c11
+	                            (guint16) arp_type);
f86c11
 	if (r < 0) {
f86c11
 		nm_utils_error_set_errno (error, r, "failed to set MAC address: %s");
f86c11
 		return FALSE;
f86c11
@@ -871,7 +858,7 @@ ip6_start (NMDhcpClient *client,
f86c11
 	GBytes *duid;
f86c11
 	const uint8_t *hwaddr_arr;
f86c11
 	gsize hwaddr_len;
f86c11
-	guint16 arptype;
f86c11
+	int arp_type;
f86c11
 
f86c11
 	g_return_val_if_fail (!priv->client4, FALSE);
f86c11
 	g_return_val_if_fail (!priv->client6, FALSE);
f86c11
@@ -917,14 +904,14 @@ ip6_start (NMDhcpClient *client,
f86c11
 	hwaddr = nm_dhcp_client_get_hw_addr (client);
f86c11
 	if (   !hwaddr
f86c11
 	    || !(hwaddr_arr = g_bytes_get_data (hwaddr, &hwaddr_len))
f86c11
-	    || (arptype = get_arp_type (hwaddr_len)) == ARPHRD_NONE) {
f86c11
+	    || (arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len)) < 0) {
f86c11
 		nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
f86c11
 		return FALSE;
f86c11
 	}
f86c11
 	r = sd_dhcp6_client_set_mac (sd_client,
f86c11
 	                             hwaddr_arr,
f86c11
 	                             hwaddr_len,
f86c11
-	                             arptype);
f86c11
+	                             (guint16) arp_type);
f86c11
 	if (r < 0) {
f86c11
 		nm_utils_error_set_errno (error, r, "failed to set MAC address: %s");
f86c11
 		return FALSE;
f86c11
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
f86c11
index d5e6346de..34a77bbc9 100644
f86c11
--- a/src/nm-core-utils.c
f86c11
+++ b/src/nm-core-utils.c
f86c11
@@ -36,6 +36,7 @@
f86c11
 #include <sys/stat.h>
f86c11
 #include <linux/if.h>
f86c11
 #include <linux/if_infiniband.h>
f86c11
+#include <net/if_arp.h>
f86c11
 #include <net/ethernet.h>
f86c11
 
f86c11
 #include "nm-utils/nm-random-utils.h"
f86c11
@@ -3041,6 +3042,33 @@ nm_utils_boot_id_bin (void)
f86c11
 
f86c11
 /*****************************************************************************/
f86c11
 
f86c11
+/**
f86c11
+ * nm_utils_detect_arp_type_from_addrlen:
f86c11
+ * @hwaddr_len: the length of the hardware address in bytes.
f86c11
+ *
f86c11
+ * Detects the arp-type based on the length of the MAC address.
f86c11
+ * On success, this returns a (positive) value in uint16_t range,
f86c11
+ * like ARPHRD_ETHER or ARPHRD_INFINIBAND.
f86c11
+ *
f86c11
+ * On failure, returns a negative error code.
f86c11
+ *
f86c11
+ * Returns: the arp-type or negative value on error. */
f86c11
+int
f86c11
+nm_utils_detect_arp_type_from_addrlen (gsize hwaddr_len)
f86c11
+{
f86c11
+	switch (hwaddr_len) {
f86c11
+	case ETH_ALEN:
f86c11
+		return ARPHRD_ETHER;
f86c11
+	case INFINIBAND_ALEN:
f86c11
+		return ARPHRD_INFINIBAND;
f86c11
+	default:
f86c11
+		/* Note: if you ever support anything but ethernet and infiniband,
f86c11
+		 * make sure to look at all callers. They assert that it's one of
f86c11
+		 * these two. */
f86c11
+		return -EINVAL;
f86c11
+	}
f86c11
+}
f86c11
+
f86c11
 /* Returns the "u" (universal/local) bit value for a Modified EUI-64 */
f86c11
 static gboolean
f86c11
 get_gre_eui64_u_bit (guint32 addr)
f86c11
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
f86c11
index 16ca50b60..bdeb1b662 100644
f86c11
--- a/src/nm-core-utils.h
f86c11
+++ b/src/nm-core-utils.h
f86c11
@@ -293,6 +293,8 @@ gboolean nm_utils_host_id_get (const guint8 **out_host_id,
f86c11
                                gsize *out_host_id_len);
f86c11
 gint64 nm_utils_host_id_get_timestamp_ns (void);
f86c11
 
f86c11
+int nm_utils_detect_arp_type_from_addrlen (gsize hwaddr_len);
f86c11
+
f86c11
 /* IPv6 Interface Identifier helpers */
f86c11
 
f86c11
 /**
f86c11
-- 
f86c11
2.19.2
f86c11
f86c11
f86c11
From c169947ea96f54565bb4e12e23f7c2defda2ec1a Mon Sep 17 00:00:00 2001
f86c11
From: Thomas Haller <thaller@redhat.com>
f86c11
Date: Fri, 14 Dec 2018 08:55:42 +0100
f86c11
Subject: [PATCH 2/2] dhcp: support generating DHCP client-id/duid for
f86c11
 infiniband
f86c11
f86c11
https://bugzilla.redhat.com/show_bug.cgi?id=1658057
f86c11
(cherry picked from commit 672852c4d3786b2ed1418fd885bcaafb46afc427)
f86c11
(cherry picked from commit 42c07a033d31c4c19709120460d7d5e188d68e11)
f86c11
---
f86c11
 src/devices/nm-device.c | 164 +++++++++++++++++++++++++++++++---------
f86c11
 1 file changed, 129 insertions(+), 35 deletions(-)
f86c11
f86c11
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
f86c11
index ebd699c65..f521cc2bb 100644
f86c11
--- a/src/devices/nm-device.c
f86c11
+++ b/src/devices/nm-device.c
f86c11
@@ -7430,16 +7430,35 @@ get_dhcp_timeout (NMDevice *self, int addr_family)
f86c11
 	return timeout ?: NM_DHCP_TIMEOUT_DEFAULT;
f86c11
 }
f86c11
 
f86c11
+static void
f86c11
+_ASSERT_arp_type (guint16 arp_type,
f86c11
+                  const guint8 *hwaddr,
f86c11
+                  gsize hwaddr_len)
f86c11
+{
f86c11
+	/* we actually only support ethernet and infiniband below. Assert that
f86c11
+	 * the arp-type and the address length correspond. */
f86c11
+	nm_assert (NM_IN_SET (arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND));
f86c11
+	nm_assert (arp_type <= 255);
f86c11
+	nm_assert (hwaddr_len > 0);
f86c11
+	nm_assert (arp_type != ARPHRD_ETHER      || hwaddr_len == ETH_ALEN);
f86c11
+	nm_assert (arp_type != ARPHRD_INFINIBAND || hwaddr_len == INFINIBAND_ALEN);
f86c11
+	nm_assert (hwaddr);
f86c11
+}
f86c11
+
f86c11
 static GBytes *
f86c11
-dhcp4_get_client_id_mac (const guint8 *hwaddr /* ETH_ALEN bytes */)
f86c11
+dhcp4_get_client_id_mac (guint16 arp_type,
f86c11
+                         const guint8 *hwaddr,
f86c11
+                         gsize hwaddr_len)
f86c11
 {
f86c11
 	guint8 *client_id_buf;
f86c11
-	guint8 hwaddr_type = ARPHRD_ETHER;
f86c11
+	const guint8 hwaddr_type = arp_type;
f86c11
 
f86c11
-	client_id_buf = g_malloc (ETH_ALEN + 1);
f86c11
+	_ASSERT_arp_type (arp_type, hwaddr, hwaddr_len);
f86c11
+
f86c11
+	client_id_buf = g_malloc (hwaddr_len + 1);
f86c11
 	client_id_buf[0] = hwaddr_type;
f86c11
-	memcpy (&client_id_buf[1], hwaddr, ETH_ALEN);
f86c11
-	return g_bytes_new_take (client_id_buf, ETH_ALEN + 1);
f86c11
+	memcpy (&client_id_buf[1], hwaddr, hwaddr_len);
f86c11
+	return g_bytes_new_take (client_id_buf, hwaddr_len + 1);
f86c11
 }
f86c11
 
f86c11
 static GBytes *
f86c11
@@ -7454,6 +7473,7 @@ dhcp4_get_client_id (NMDevice *self,
f86c11
 	const char *fail_reason;
f86c11
 	guint8 hwaddr_bin_buf[NM_UTILS_HWADDR_LEN_MAX];
f86c11
 	const guint8 *hwaddr_bin;
f86c11
+	int arp_type;
f86c11
 	gsize hwaddr_len;
f86c11
 	GBytes *result;
f86c11
 	gs_free char *logstr1 = NULL;
f86c11
@@ -7478,17 +7498,18 @@ dhcp4_get_client_id (NMDevice *self,
f86c11
 
f86c11
 	if (nm_streq (client_id, "mac")) {
f86c11
 		if (!hwaddr) {
f86c11
-			fail_reason = "failed to get current MAC address";
f86c11
+			fail_reason = "missing link-layer address";
f86c11
 			goto out_fail;
f86c11
 		}
f86c11
 
f86c11
 		hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
f86c11
-		if (hwaddr_len != ETH_ALEN) {
f86c11
-			fail_reason = "MAC address is not ethernet";
f86c11
+		arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len);
f86c11
+		if (arp_type < 0) {
f86c11
+			fail_reason = "unsupported link-layer address";
f86c11
 			goto out_fail;
f86c11
 		}
f86c11
 
f86c11
-		result = dhcp4_get_client_id_mac (hwaddr_bin);
f86c11
+		result = dhcp4_get_client_id_mac ((guint16) arp_type, hwaddr_bin, hwaddr_len);
f86c11
 		goto out_good;
f86c11
 	}
f86c11
 
f86c11
@@ -7497,20 +7518,20 @@ dhcp4_get_client_id (NMDevice *self,
f86c11
 
f86c11
 		hwaddr_str = nm_device_get_permanent_hw_address (self);
f86c11
 		if (!hwaddr_str) {
f86c11
-			fail_reason = "failed to get permanent MAC address";
f86c11
+			fail_reason = "missing permanent link-layer address";
f86c11
 			goto out_fail;
f86c11
 		}
f86c11
 
f86c11
 		if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_bin_buf, sizeof (hwaddr_bin_buf), &hwaddr_len))
f86c11
 			g_return_val_if_reached (NULL);
f86c11
 
f86c11
-		if (hwaddr_len != ETH_ALEN) {
f86c11
-			/* unsupported type. */
f86c11
-			fail_reason = "MAC address is not ethernet";
f86c11
+		arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len);
f86c11
+		if (arp_type < 0) {
f86c11
+			fail_reason = "unsupported permanent link-layer address";
f86c11
 			goto out_fail;
f86c11
 		}
f86c11
 
f86c11
-		result = dhcp4_get_client_id_mac (hwaddr_bin_buf);
f86c11
+		result = dhcp4_get_client_id_mac ((guint16) arp_type, hwaddr_bin_buf, hwaddr_len);
f86c11
 		goto out_good;
f86c11
 	}
f86c11
 
f86c11
@@ -8173,38 +8194,46 @@ dhcp6_prefix_delegated (NMDhcpClient *client,
f86c11
 #define EPOCH_DATETIME_200001010000  946684800
f86c11
 
f86c11
 static GBytes *
f86c11
-generate_duid_llt (const guint8 *hwaddr /* ETH_ALEN bytes */,
f86c11
+generate_duid_llt (guint16 arp_type,
f86c11
+                   const guint8 *hwaddr,
f86c11
+                   gsize hwaddr_len,
f86c11
                    gint64 time)
f86c11
 {
f86c11
 	guint8 *arr;
f86c11
 	const guint16 duid_type = htons (1);
f86c11
-	const guint16 hw_type = htons (ARPHRD_ETHER);
f86c11
+	const guint16 hw_type = htons (arp_type);
f86c11
 	const guint32 duid_time = htonl (NM_MAX (0, time - EPOCH_DATETIME_200001010000));
f86c11
 
f86c11
-	arr = g_new (guint8, 2 + 2 + 4 + ETH_ALEN);
f86c11
+	_ASSERT_arp_type (arp_type, hwaddr, hwaddr_len);
f86c11
+
f86c11
+	arr = g_new (guint8, 2 + 2 + 4 + hwaddr_len);
f86c11
 
f86c11
 	memcpy (&arr[0], &duid_type, 2);
f86c11
 	memcpy (&arr[2], &hw_type, 2);
f86c11
 	memcpy (&arr[4], &duid_time, 4);
f86c11
-	memcpy (&arr[8], hwaddr, ETH_ALEN);
f86c11
+	memcpy (&arr[8], hwaddr, hwaddr_len);
f86c11
 
f86c11
-	return g_bytes_new_take (arr, 2 + 2 + 4 + ETH_ALEN);
f86c11
+	return g_bytes_new_take (arr, 2 + 2 + 4 + hwaddr_len);
f86c11
 }
f86c11
 
f86c11
 static GBytes *
f86c11
-generate_duid_ll (const guint8 *hwaddr /* ETH_ALEN bytes */)
f86c11
+generate_duid_ll (guint16 arp_type,
f86c11
+                  const guint8 *hwaddr,
f86c11
+                  gsize hwaddr_len)
f86c11
 {
f86c11
 	guint8 *arr;
f86c11
 	const guint16 duid_type = htons (3);
f86c11
-	const guint16 hw_type = htons (ARPHRD_ETHER);
f86c11
+	const guint16 hw_type = htons (arp_type);
f86c11
 
f86c11
-	arr = g_new (guint8, 2 + 2 + ETH_ALEN);
f86c11
+	_ASSERT_arp_type (arp_type, hwaddr, hwaddr_len);
f86c11
+
f86c11
+	arr = g_new (guint8, 2 + 2 + hwaddr_len);
f86c11
 
f86c11
 	memcpy (&arr[0], &duid_type, 2);
f86c11
 	memcpy (&arr[2], &hw_type, 2);
f86c11
-	memcpy (&arr[4], hwaddr, ETH_ALEN);
f86c11
+	memcpy (&arr[4], hwaddr, hwaddr_len);
f86c11
 
f86c11
-	return g_bytes_new_take (arr, 2 + 2 + ETH_ALEN);
f86c11
+	return g_bytes_new_take (arr, 2 + 2 + hwaddr_len);
f86c11
 }
f86c11
 
f86c11
 static GBytes *
f86c11
@@ -8274,6 +8303,9 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
f86c11
 	GBytes *duid_out;
f86c11
 	gboolean duid_enforce = TRUE;
f86c11
 	gs_free char *logstr1 = NULL;
f86c11
+	const guint8 *hwaddr_bin;
f86c11
+	gsize hwaddr_len;
f86c11
+	int arp_type;
f86c11
 
f86c11
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
f86c11
 	duid = nm_setting_ip6_config_get_dhcp_duid (NM_SETTING_IP6_CONFIG (s_ip6));
f86c11
@@ -8305,15 +8337,18 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
f86c11
 			duid_error = "missing link-layer address";
f86c11
 			goto out_fail;
f86c11
 		}
f86c11
-		if (g_bytes_get_size (hwaddr) != ETH_ALEN) {
f86c11
+
f86c11
+		hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
f86c11
+		arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len);
f86c11
+		if (arp_type < 0) {
f86c11
 			duid_error = "unsupported link-layer address";
f86c11
 			goto out_fail;
f86c11
 		}
f86c11
 
f86c11
-		if (nm_streq (duid, "ll")) {
f86c11
-			duid_out = generate_duid_ll (g_bytes_get_data (hwaddr, NULL));
f86c11
-		} else {
f86c11
-			duid_out = generate_duid_llt (g_bytes_get_data (hwaddr, NULL),
f86c11
+		if (nm_streq (duid, "ll"))
f86c11
+			duid_out = generate_duid_ll (arp_type, hwaddr_bin, hwaddr_len);
f86c11
+		else {
f86c11
+			duid_out = generate_duid_llt (arp_type, hwaddr_bin, hwaddr_len,
f86c11
 			                              nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NS_PER_SECOND);
f86c11
 		}
f86c11
 
f86c11
@@ -8321,6 +8356,12 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
f86c11
 	}
f86c11
 
f86c11
 	if (NM_IN_STRSET (duid, "stable-ll", "stable-llt", "stable-uuid")) {
f86c11
+		/* preferably, we would salt the checksum differently for each @duid type. We missed
f86c11
+		 * to do that initially, so most types use the DEFAULT_SALT.
f86c11
+		 *
f86c11
+		 * Implemenations that are added later, should use a distinct salt instead,
f86c11
+		 * like "stable-ll"/"stable-llt" with ARPHRD_INFINIBAND below. */
f86c11
+		const guint32 DEFAULT_SALT = 670531087u;
f86c11
 		nm_auto_free_checksum GChecksum *sum = NULL;
f86c11
 		NMUtilsStableType stable_type;
f86c11
 		const char *stable_id = NULL;
f86c11
@@ -8329,19 +8370,50 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
f86c11
 		gsize host_id_len;
f86c11
 		union {
f86c11
 			guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256];
f86c11
-			guint8 hwaddr[ETH_ALEN];
f86c11
+			guint8 hwaddr_eth[ETH_ALEN];
f86c11
+			guint8 hwaddr_infiniband[INFINIBAND_ALEN];
f86c11
 			NMUuid uuid;
f86c11
 			struct _nm_packed {
f86c11
 				guint8 hwaddr[ETH_ALEN];
f86c11
 				guint32 timestamp;
f86c11
-			} llt;
f86c11
+			} llt_eth;
f86c11
+			struct _nm_packed {
f86c11
+				guint8 hwaddr[INFINIBAND_ALEN];
f86c11
+				guint32 timestamp;
f86c11
+			} llt_infiniband;
f86c11
 		} digest;
f86c11
 
f86c11
 		stable_id = _get_stable_id (self, connection, &stable_type);
f86c11
 		if (!stable_id)
f86c11
 			g_return_val_if_reached (NULL);
f86c11
 
f86c11
-		salted_header = htonl (670531087 + stable_type);
f86c11
+		if (NM_IN_STRSET (duid, "stable-ll", "stable-llt")) {
f86c11
+			/* for stable LL/LLT DUIDs, we still need a hardware address to detect
f86c11
+			 * the arp-type. Alternatively, we would be able to detect it based on
f86c11
+			 * other means (e.g. NMDevice type), but instead require the hardware
f86c11
+			 * address to be present. This is at least consistent with the "ll"/"llt"
f86c11
+			 * modes above. */
f86c11
+			if (!hwaddr) {
f86c11
+				duid_error = "missing link-layer address";
f86c11
+				goto out_fail;
f86c11
+			}
f86c11
+			if ((arp_type = nm_utils_detect_arp_type_from_addrlen (g_bytes_get_size (hwaddr))) < 0) {
f86c11
+				duid_error = "unsupported link-layer address";
f86c11
+				goto out_fail;
f86c11
+			}
f86c11
+
f86c11
+			if (arp_type == ARPHRD_ETHER)
f86c11
+				salted_header = DEFAULT_SALT;
f86c11
+			else {
f86c11
+				nm_assert (arp_type == ARPHRD_INFINIBAND);
f86c11
+				salted_header = 0x42492CEFu + ((guint32) arp_type);
f86c11
+			}
f86c11
+		} else {
f86c11
+			salted_header = DEFAULT_SALT;
f86c11
+			arp_type = -1;
f86c11
+		}
f86c11
+
f86c11
+		salted_header = htonl (salted_header + ((guint32) stable_type));
f86c11
 
f86c11
 		nm_utils_host_id_get (&host_id, &host_id_len);
f86c11
 
f86c11
@@ -8354,9 +8426,19 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
f86c11
 		G_STATIC_ASSERT_EXPR (sizeof (digest) == sizeof (digest.sha256));
f86c11
 
f86c11
 		if (nm_streq (duid, "stable-ll")) {
f86c11
-			duid_out = generate_duid_ll (digest.hwaddr);
f86c11
+			switch (arp_type) {
f86c11
+			case ARPHRD_ETHER:
f86c11
+				duid_out = generate_duid_ll (arp_type, digest.hwaddr_eth, sizeof (digest.hwaddr_eth));
f86c11
+				break;
f86c11
+			case ARPHRD_INFINIBAND:
f86c11
+				duid_out = generate_duid_ll (arp_type, digest.hwaddr_infiniband, sizeof (digest.hwaddr_infiniband));
f86c11
+				break;
f86c11
+			default:
f86c11
+				g_return_val_if_reached (NULL);
f86c11
+			}
f86c11
 		} else if (nm_streq (duid, "stable-llt")) {
f86c11
 			gint64 time;
f86c11
+			guint32 timestamp;
f86c11
 
f86c11
 #define EPOCH_DATETIME_THREE_YEARS  (356 * 24 * 3600 * 3)
f86c11
 
f86c11
@@ -8369,9 +8451,21 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
f86c11
 			/* don't use too old timestamps. They cannot be expressed in DUID-LLT and
f86c11
 			 * would all be truncated to zero. */
f86c11
 			time = NM_MAX (time, EPOCH_DATETIME_200001010000 + EPOCH_DATETIME_THREE_YEARS);
f86c11
-			time -= unaligned_read_be32 (&digest.llt.timestamp) % EPOCH_DATETIME_THREE_YEARS;
f86c11
 
f86c11
-			duid_out = generate_duid_llt (digest.llt.hwaddr, time);
f86c11
+			switch (arp_type) {
f86c11
+			case ARPHRD_ETHER:
f86c11
+				timestamp = unaligned_read_be32 (&digest.llt_eth.timestamp);
f86c11
+				time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
f86c11
+				duid_out = generate_duid_llt (arp_type, digest.llt_eth.hwaddr, sizeof (digest.llt_eth.hwaddr), time);
f86c11
+				break;
f86c11
+			case ARPHRD_INFINIBAND:
f86c11
+				timestamp = unaligned_read_be32 (&digest.llt_infiniband.timestamp);
f86c11
+				time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
f86c11
+				duid_out = generate_duid_llt (arp_type, digest.llt_infiniband.hwaddr, sizeof (digest.llt_infiniband.hwaddr), time);
f86c11
+				break;
f86c11
+			default:
f86c11
+				g_return_val_if_reached (NULL);
f86c11
+			}
f86c11
 		} else {
f86c11
 			nm_assert (nm_streq (duid, "stable-uuid"));
f86c11
 			duid_out = generate_duid_uuid (&digest.uuid);
f86c11
-- 
f86c11
2.19.2
f86c11