mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-05 01:47:58 +02:00
dhcp: merge branch 'th/dhcp-infiniband-client-id'
https://bugzilla.redhat.com/show_bug.cgi?id=1658057
https://github.com/NetworkManager/NetworkManager/pull/262
(cherry picked from commit f22492f8fc)
This commit is contained in:
commit
0d980e76b1
4 changed files with 165 additions and 54 deletions
|
|
@ -7454,16 +7454,35 @@ get_dhcp_timeout (NMDevice *self, int addr_family)
|
|||
return timeout ?: NM_DHCP_TIMEOUT_DEFAULT;
|
||||
}
|
||||
|
||||
static void
|
||||
_ASSERT_arp_type (guint16 arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len)
|
||||
{
|
||||
/* we actually only support ethernet and infiniband below. Assert that
|
||||
* the arp-type and the address length correspond. */
|
||||
nm_assert (NM_IN_SET (arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND));
|
||||
nm_assert (arp_type <= 255);
|
||||
nm_assert (hwaddr_len > 0);
|
||||
nm_assert (arp_type != ARPHRD_ETHER || hwaddr_len == ETH_ALEN);
|
||||
nm_assert (arp_type != ARPHRD_INFINIBAND || hwaddr_len == INFINIBAND_ALEN);
|
||||
nm_assert (hwaddr);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
dhcp4_get_client_id_mac (const guint8 *hwaddr /* ETH_ALEN bytes */)
|
||||
dhcp4_get_client_id_mac (guint16 arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len)
|
||||
{
|
||||
guint8 *client_id_buf;
|
||||
guint8 hwaddr_type = ARPHRD_ETHER;
|
||||
const guint8 hwaddr_type = arp_type;
|
||||
|
||||
client_id_buf = g_malloc (ETH_ALEN + 1);
|
||||
_ASSERT_arp_type (arp_type, hwaddr, hwaddr_len);
|
||||
|
||||
client_id_buf = g_malloc (hwaddr_len + 1);
|
||||
client_id_buf[0] = hwaddr_type;
|
||||
memcpy (&client_id_buf[1], hwaddr, ETH_ALEN);
|
||||
return g_bytes_new_take (client_id_buf, ETH_ALEN + 1);
|
||||
memcpy (&client_id_buf[1], hwaddr, hwaddr_len);
|
||||
return g_bytes_new_take (client_id_buf, hwaddr_len + 1);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
|
|
@ -7478,6 +7497,7 @@ dhcp4_get_client_id (NMDevice *self,
|
|||
const char *fail_reason;
|
||||
guint8 hwaddr_bin_buf[NM_UTILS_HWADDR_LEN_MAX];
|
||||
const guint8 *hwaddr_bin;
|
||||
int arp_type;
|
||||
gsize hwaddr_len;
|
||||
GBytes *result;
|
||||
gs_free char *logstr1 = NULL;
|
||||
|
|
@ -7502,17 +7522,18 @@ dhcp4_get_client_id (NMDevice *self,
|
|||
|
||||
if (nm_streq (client_id, "mac")) {
|
||||
if (!hwaddr) {
|
||||
fail_reason = "failed to get current MAC address";
|
||||
fail_reason = "missing link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
|
||||
if (hwaddr_len != ETH_ALEN) {
|
||||
fail_reason = "MAC address is not ethernet";
|
||||
arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len);
|
||||
if (arp_type < 0) {
|
||||
fail_reason = "unsupported link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
result = dhcp4_get_client_id_mac (hwaddr_bin);
|
||||
result = dhcp4_get_client_id_mac ((guint16) arp_type, hwaddr_bin, hwaddr_len);
|
||||
goto out_good;
|
||||
}
|
||||
|
||||
|
|
@ -7521,20 +7542,20 @@ dhcp4_get_client_id (NMDevice *self,
|
|||
|
||||
hwaddr_str = nm_device_get_permanent_hw_address (self);
|
||||
if (!hwaddr_str) {
|
||||
fail_reason = "failed to get permanent MAC address";
|
||||
fail_reason = "missing permanent link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_bin_buf, sizeof (hwaddr_bin_buf), &hwaddr_len))
|
||||
g_return_val_if_reached (NULL);
|
||||
|
||||
if (hwaddr_len != ETH_ALEN) {
|
||||
/* unsupported type. */
|
||||
fail_reason = "MAC address is not ethernet";
|
||||
arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len);
|
||||
if (arp_type < 0) {
|
||||
fail_reason = "unsupported permanent link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
result = dhcp4_get_client_id_mac (hwaddr_bin_buf);
|
||||
result = dhcp4_get_client_id_mac ((guint16) arp_type, hwaddr_bin_buf, hwaddr_len);
|
||||
goto out_good;
|
||||
}
|
||||
|
||||
|
|
@ -8197,38 +8218,46 @@ dhcp6_prefix_delegated (NMDhcpClient *client,
|
|||
#define EPOCH_DATETIME_200001010000 946684800
|
||||
|
||||
static GBytes *
|
||||
generate_duid_llt (const guint8 *hwaddr /* ETH_ALEN bytes */,
|
||||
generate_duid_llt (guint16 arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len,
|
||||
gint64 time)
|
||||
{
|
||||
guint8 *arr;
|
||||
const guint16 duid_type = htons (1);
|
||||
const guint16 hw_type = htons (ARPHRD_ETHER);
|
||||
const guint16 hw_type = htons (arp_type);
|
||||
const guint32 duid_time = htonl (NM_MAX (0, time - EPOCH_DATETIME_200001010000));
|
||||
|
||||
arr = g_new (guint8, 2 + 2 + 4 + ETH_ALEN);
|
||||
_ASSERT_arp_type (arp_type, hwaddr, hwaddr_len);
|
||||
|
||||
arr = g_new (guint8, 2 + 2 + 4 + hwaddr_len);
|
||||
|
||||
memcpy (&arr[0], &duid_type, 2);
|
||||
memcpy (&arr[2], &hw_type, 2);
|
||||
memcpy (&arr[4], &duid_time, 4);
|
||||
memcpy (&arr[8], hwaddr, ETH_ALEN);
|
||||
memcpy (&arr[8], hwaddr, hwaddr_len);
|
||||
|
||||
return g_bytes_new_take (arr, 2 + 2 + 4 + ETH_ALEN);
|
||||
return g_bytes_new_take (arr, 2 + 2 + 4 + hwaddr_len);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
generate_duid_ll (const guint8 *hwaddr /* ETH_ALEN bytes */)
|
||||
generate_duid_ll (guint16 arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len)
|
||||
{
|
||||
guint8 *arr;
|
||||
const guint16 duid_type = htons (3);
|
||||
const guint16 hw_type = htons (ARPHRD_ETHER);
|
||||
const guint16 hw_type = htons (arp_type);
|
||||
|
||||
arr = g_new (guint8, 2 + 2 + ETH_ALEN);
|
||||
_ASSERT_arp_type (arp_type, hwaddr, hwaddr_len);
|
||||
|
||||
arr = g_new (guint8, 2 + 2 + hwaddr_len);
|
||||
|
||||
memcpy (&arr[0], &duid_type, 2);
|
||||
memcpy (&arr[2], &hw_type, 2);
|
||||
memcpy (&arr[4], hwaddr, ETH_ALEN);
|
||||
memcpy (&arr[4], hwaddr, hwaddr_len);
|
||||
|
||||
return g_bytes_new_take (arr, 2 + 2 + ETH_ALEN);
|
||||
return g_bytes_new_take (arr, 2 + 2 + hwaddr_len);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
|
|
@ -8298,6 +8327,9 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|||
GBytes *duid_out;
|
||||
gboolean duid_enforce = TRUE;
|
||||
gs_free char *logstr1 = NULL;
|
||||
const guint8 *hwaddr_bin;
|
||||
gsize hwaddr_len;
|
||||
int arp_type;
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
duid = nm_setting_ip6_config_get_dhcp_duid (NM_SETTING_IP6_CONFIG (s_ip6));
|
||||
|
|
@ -8329,15 +8361,18 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|||
duid_error = "missing link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
if (g_bytes_get_size (hwaddr) != ETH_ALEN) {
|
||||
|
||||
hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
|
||||
arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len);
|
||||
if (arp_type < 0) {
|
||||
duid_error = "unsupported link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
if (nm_streq (duid, "ll")) {
|
||||
duid_out = generate_duid_ll (g_bytes_get_data (hwaddr, NULL));
|
||||
} else {
|
||||
duid_out = generate_duid_llt (g_bytes_get_data (hwaddr, NULL),
|
||||
if (nm_streq (duid, "ll"))
|
||||
duid_out = generate_duid_ll (arp_type, hwaddr_bin, hwaddr_len);
|
||||
else {
|
||||
duid_out = generate_duid_llt (arp_type, hwaddr_bin, hwaddr_len,
|
||||
nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NS_PER_SECOND);
|
||||
}
|
||||
|
||||
|
|
@ -8345,6 +8380,12 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|||
}
|
||||
|
||||
if (NM_IN_STRSET (duid, "stable-ll", "stable-llt", "stable-uuid")) {
|
||||
/* preferably, we would salt the checksum differently for each @duid type. We missed
|
||||
* to do that initially, so most types use the DEFAULT_SALT.
|
||||
*
|
||||
* Implemenations that are added later, should use a distinct salt instead,
|
||||
* like "stable-ll"/"stable-llt" with ARPHRD_INFINIBAND below. */
|
||||
const guint32 DEFAULT_SALT = 670531087u;
|
||||
nm_auto_free_checksum GChecksum *sum = NULL;
|
||||
NMUtilsStableType stable_type;
|
||||
const char *stable_id = NULL;
|
||||
|
|
@ -8353,19 +8394,50 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|||
gsize host_id_len;
|
||||
union {
|
||||
guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256];
|
||||
guint8 hwaddr[ETH_ALEN];
|
||||
guint8 hwaddr_eth[ETH_ALEN];
|
||||
guint8 hwaddr_infiniband[INFINIBAND_ALEN];
|
||||
NMUuid uuid;
|
||||
struct _nm_packed {
|
||||
guint8 hwaddr[ETH_ALEN];
|
||||
guint32 timestamp;
|
||||
} llt;
|
||||
} llt_eth;
|
||||
struct _nm_packed {
|
||||
guint8 hwaddr[INFINIBAND_ALEN];
|
||||
guint32 timestamp;
|
||||
} llt_infiniband;
|
||||
} digest;
|
||||
|
||||
stable_id = _get_stable_id (self, connection, &stable_type);
|
||||
if (!stable_id)
|
||||
g_return_val_if_reached (NULL);
|
||||
|
||||
salted_header = htonl (670531087 + stable_type);
|
||||
if (NM_IN_STRSET (duid, "stable-ll", "stable-llt")) {
|
||||
/* for stable LL/LLT DUIDs, we still need a hardware address to detect
|
||||
* the arp-type. Alternatively, we would be able to detect it based on
|
||||
* other means (e.g. NMDevice type), but instead require the hardware
|
||||
* address to be present. This is at least consistent with the "ll"/"llt"
|
||||
* modes above. */
|
||||
if (!hwaddr) {
|
||||
duid_error = "missing link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
if ((arp_type = nm_utils_detect_arp_type_from_addrlen (g_bytes_get_size (hwaddr))) < 0) {
|
||||
duid_error = "unsupported link-layer address";
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
if (arp_type == ARPHRD_ETHER)
|
||||
salted_header = DEFAULT_SALT;
|
||||
else {
|
||||
nm_assert (arp_type == ARPHRD_INFINIBAND);
|
||||
salted_header = 0x42492CEFu + ((guint32) arp_type);
|
||||
}
|
||||
} else {
|
||||
salted_header = DEFAULT_SALT;
|
||||
arp_type = -1;
|
||||
}
|
||||
|
||||
salted_header = htonl (salted_header + ((guint32) stable_type));
|
||||
|
||||
nm_utils_host_id_get (&host_id, &host_id_len);
|
||||
|
||||
|
|
@ -8378,9 +8450,19 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|||
G_STATIC_ASSERT_EXPR (sizeof (digest) == sizeof (digest.sha256));
|
||||
|
||||
if (nm_streq (duid, "stable-ll")) {
|
||||
duid_out = generate_duid_ll (digest.hwaddr);
|
||||
switch (arp_type) {
|
||||
case ARPHRD_ETHER:
|
||||
duid_out = generate_duid_ll (arp_type, digest.hwaddr_eth, sizeof (digest.hwaddr_eth));
|
||||
break;
|
||||
case ARPHRD_INFINIBAND:
|
||||
duid_out = generate_duid_ll (arp_type, digest.hwaddr_infiniband, sizeof (digest.hwaddr_infiniband));
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
} else if (nm_streq (duid, "stable-llt")) {
|
||||
gint64 time;
|
||||
guint32 timestamp;
|
||||
|
||||
#define EPOCH_DATETIME_THREE_YEARS (356 * 24 * 3600 * 3)
|
||||
|
||||
|
|
@ -8393,9 +8475,21 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole
|
|||
/* don't use too old timestamps. They cannot be expressed in DUID-LLT and
|
||||
* would all be truncated to zero. */
|
||||
time = NM_MAX (time, EPOCH_DATETIME_200001010000 + EPOCH_DATETIME_THREE_YEARS);
|
||||
time -= unaligned_read_be32 (&digest.llt.timestamp) % EPOCH_DATETIME_THREE_YEARS;
|
||||
|
||||
duid_out = generate_duid_llt (digest.llt.hwaddr, time);
|
||||
switch (arp_type) {
|
||||
case ARPHRD_ETHER:
|
||||
timestamp = unaligned_read_be32 (&digest.llt_eth.timestamp);
|
||||
time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
|
||||
duid_out = generate_duid_llt (arp_type, digest.llt_eth.hwaddr, sizeof (digest.llt_eth.hwaddr), time);
|
||||
break;
|
||||
case ARPHRD_INFINIBAND:
|
||||
timestamp = unaligned_read_be32 (&digest.llt_infiniband.timestamp);
|
||||
time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
|
||||
duid_out = generate_duid_llt (arp_type, digest.llt_infiniband.hwaddr, sizeof (digest.llt_infiniband.hwaddr), time);
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
} else {
|
||||
nm_assert (nm_streq (duid, "stable-uuid"));
|
||||
duid_out = generate_duid_uuid (&digest.uuid);
|
||||
|
|
|
|||
|
|
@ -559,19 +559,6 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static guint16
|
||||
get_arp_type (gsize hwaddr_len)
|
||||
{
|
||||
switch (hwaddr_len) {
|
||||
case ETH_ALEN:
|
||||
return ARPHRD_ETHER;
|
||||
case INFINIBAND_ALEN:
|
||||
return ARPHRD_INFINIBAND;
|
||||
default:
|
||||
return ARPHRD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_start (NMDhcpClient *client,
|
||||
const char *dhcp_anycast_addr,
|
||||
|
|
@ -585,7 +572,7 @@ ip4_start (NMDhcpClient *client,
|
|||
GBytes *hwaddr;
|
||||
const uint8_t *hwaddr_arr;
|
||||
gsize hwaddr_len;
|
||||
guint16 arptype;
|
||||
int arp_type;
|
||||
GBytes *client_id;
|
||||
gs_unref_bytes GBytes *client_id_new = NULL;
|
||||
const uint8_t *client_id_arr;
|
||||
|
|
@ -614,14 +601,14 @@ ip4_start (NMDhcpClient *client,
|
|||
hwaddr = nm_dhcp_client_get_hw_addr (client);
|
||||
if ( !hwaddr
|
||||
|| !(hwaddr_arr = g_bytes_get_data (hwaddr, &hwaddr_len))
|
||||
|| (arptype = get_arp_type (hwaddr_len)) == ARPHRD_NONE) {
|
||||
|| (arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len)) < 0) {
|
||||
nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
|
||||
return FALSE;
|
||||
}
|
||||
r = sd_dhcp_client_set_mac (sd_client,
|
||||
hwaddr_arr,
|
||||
hwaddr_len,
|
||||
arptype);
|
||||
(guint16) arp_type);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno (error, r, "failed to set MAC address: %s");
|
||||
return FALSE;
|
||||
|
|
@ -900,7 +887,7 @@ ip6_start (NMDhcpClient *client,
|
|||
GBytes *duid;
|
||||
const uint8_t *hwaddr_arr;
|
||||
gsize hwaddr_len;
|
||||
guint16 arptype;
|
||||
int arp_type;
|
||||
|
||||
g_return_val_if_fail (!priv->client4, FALSE);
|
||||
g_return_val_if_fail (!priv->client6, FALSE);
|
||||
|
|
@ -946,14 +933,14 @@ ip6_start (NMDhcpClient *client,
|
|||
hwaddr = nm_dhcp_client_get_hw_addr (client);
|
||||
if ( !hwaddr
|
||||
|| !(hwaddr_arr = g_bytes_get_data (hwaddr, &hwaddr_len))
|
||||
|| (arptype = get_arp_type (hwaddr_len)) == ARPHRD_NONE) {
|
||||
|| (arp_type = nm_utils_detect_arp_type_from_addrlen (hwaddr_len)) < 0) {
|
||||
nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
|
||||
return FALSE;
|
||||
}
|
||||
r = sd_dhcp6_client_set_mac (sd_client,
|
||||
hwaddr_arr,
|
||||
hwaddr_len,
|
||||
arptype);
|
||||
(guint16) arp_type);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno (error, r, "failed to set MAC address: %s");
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_infiniband.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
#include "nm-utils/nm-random-utils.h"
|
||||
|
|
@ -3041,6 +3042,33 @@ nm_utils_boot_id_bin (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_utils_detect_arp_type_from_addrlen:
|
||||
* @hwaddr_len: the length of the hardware address in bytes.
|
||||
*
|
||||
* Detects the arp-type based on the length of the MAC address.
|
||||
* On success, this returns a (positive) value in uint16_t range,
|
||||
* like ARPHRD_ETHER or ARPHRD_INFINIBAND.
|
||||
*
|
||||
* On failure, returns a negative error code.
|
||||
*
|
||||
* Returns: the arp-type or negative value on error. */
|
||||
int
|
||||
nm_utils_detect_arp_type_from_addrlen (gsize hwaddr_len)
|
||||
{
|
||||
switch (hwaddr_len) {
|
||||
case ETH_ALEN:
|
||||
return ARPHRD_ETHER;
|
||||
case INFINIBAND_ALEN:
|
||||
return ARPHRD_INFINIBAND;
|
||||
default:
|
||||
/* Note: if you ever support anything but ethernet and infiniband,
|
||||
* make sure to look at all callers. They assert that it's one of
|
||||
* these two. */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the "u" (universal/local) bit value for a Modified EUI-64 */
|
||||
static gboolean
|
||||
get_gre_eui64_u_bit (guint32 addr)
|
||||
|
|
|
|||
|
|
@ -293,6 +293,8 @@ gboolean nm_utils_host_id_get (const guint8 **out_host_id,
|
|||
gsize *out_host_id_len);
|
||||
gint64 nm_utils_host_id_get_timestamp_ns (void);
|
||||
|
||||
int nm_utils_detect_arp_type_from_addrlen (gsize hwaddr_len);
|
||||
|
||||
/* IPv6 Interface Identifier helpers */
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue