]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #11210 from thom311/dhcp-set-client-id-no-inval
authorLennart Poettering <lennart@poettering.net>
Fri, 21 Dec 2018 17:00:42 +0000 (18:00 +0100)
committerGitHub <noreply@github.com>
Fri, 21 Dec 2018 17:00:42 +0000 (18:00 +0100)
dhcp: don't enforce hardware address length for sd_dhcp_client_set_client_id()

src/libsystemd-network/dhcp-identifier.c
src/libsystemd-network/dhcp-identifier.h
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp6-client.c

index c768adeb6da39ff2a1f540bd201e4e9606b69b36..07496adaa390f06555810d0cfb8ea5121b13c1c5 100644 (file)
 #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))
index a544f38ab8652a1c073227f24b787b19321aa45d..b3115125d9ab1ae59043388e9355ab32763afc54 100644 (file)
@@ -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);
index 3bdd584bb55858852d53feb2d29dc30bf987c90a..2d7ffd22ca51364057e88115e0df34ef3f939f74 100644 (file)
@@ -300,27 +300,22 @@ int sd_dhcp_client_set_client_id(
         assert_return(data, -EINVAL);
         assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
 
-        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");
@@ -361,7 +356,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;
         }
index 8ff4585f63c6f1dd1b0eb8dcda3ca7489fdc7709..593ffd1b644fed6d88693488760f361190ff8229 100644 (file)
@@ -206,9 +206,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);