summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-12-21 19:27:48 +0100
committerThomas Haller <thaller@redhat.com>2018-12-21 19:29:35 +0100
commitbf604ae2d8d57b2087c7358e54a1fe7867d11f11 (patch)
tree7febb0d1df20ed179fabda4e4442b6d162b28e63
parent7bd193ef30fb2a1d4c328bb61412e35a5bccfced (diff)
parentd65ee3bb18fd27072113065c189e76d8abe16b25 (diff)
downloadNetworkManager-bf604ae2d8d57b2087c7358e54a1fe7867d11f11.tar.gz
systemd: merge branch 'thom311/dhcp-set-client-id-no-inval'
We use sd_dhcp_client_set_client_id() and sd_dhcp6_client_set_duid() with the aim to set arbitrary client identifiers and DUIDs. Adjust systemd DHCP library to not reject certain values. https://github.com/systemd/systemd/pull/11210 https://github.com/systemd/systemd/commit/5848a9eb4d4c937012461d440eb798db265a65f9
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c8
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.h2
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c29
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c10
4 files changed, 27 insertions, 22 deletions
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index a9fc8de164..e2055386b5 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -20,13 +20,19 @@
#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
-int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) {
struct duid d;
assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
if (duid_len > MAX_DUID_LEN)
return -EINVAL;
+ if (!strict) {
+ /* Strict validation is not requested. We only ensure that the
+ * DUID is not too long. */
+ return 0;
+ }
+
switch (duid_type) {
case DUID_TYPE_LLT:
if (duid_len <= sizeof(d.llt))
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h
index a544f38ab8..b3115125d9 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.h
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h
@@ -52,7 +52,7 @@ struct duid {
};
} _packed_;
-int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict);
int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index a8c14072ef..6ca6bcab53 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -302,27 +302,22 @@ int sd_dhcp_client_set_client_id(
assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
G_STATIC_ASSERT_EXPR (_NM_SD_MAX_CLIENT_ID_LEN == MAX_CLIENT_ID_LEN);
- switch (type) {
-
- case ARPHRD_ETHER:
- if (data_len != ETH_ALEN)
- return -EINVAL;
- break;
-
- case ARPHRD_INFINIBAND:
- if (data_len != INFINIBAND_ALEN)
- return -EINVAL;
- break;
-
- default:
- break;
- }
-
if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
client->client_id.type == type &&
memcmp(&client->client_id.raw.data, data, data_len) == 0)
return 0;
+ /* For hardware types, log debug message about unexpected data length.
+ *
+ * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
+ * last last 8 bytes of the address are stable and suitable to put into
+ * the client-id. The caller is advised to account for that. */
+ if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) ||
+ (type == ARPHRD_INFINIBAND && data_len != 8))
+ log_dhcp_client(client, "Changing client ID to hardware type %u with "
+ "unexpected address length %zu",
+ type, data_len);
+
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Changing client ID on running DHCP "
"client, restarting");
@@ -363,7 +358,7 @@ static int dhcp_client_set_iaid_duid_internal(
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
if (duid != NULL) {
- r = dhcp_validate_duid_len(duid_type, duid_len);
+ r = dhcp_validate_duid_len(duid_type, duid_len, true);
if (r < 0)
return r;
}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index e39b185f2e..8c9fb932bc 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -208,9 +208,13 @@ static int dhcp6_client_set_duid_internal(
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
if (duid != NULL) {
- r = dhcp_validate_duid_len(duid_type, duid_len);
- if (r < 0)
- return r;
+ r = dhcp_validate_duid_len(duid_type, duid_len, true);
+ if (r < 0) {
+ r = dhcp_validate_duid_len(duid_type, duid_len, false);
+ if (r < 0)
+ return r;
+ log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type);
+ }
client->duid.type = htobe16(duid_type);
memcpy(&client->duid.raw.data, duid, duid_len);