]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dh-dhcp{,6}-client: change the semantics of DUID setting
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 30 Apr 2016 01:18:11 +0000 (21:18 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 3 May 2016 16:12:04 +0000 (12:12 -0400)
Both versions of the code are changed to allow the caller to override
DUID using simple rules: duid type and value may be specified, in
which case the caller is responsible to providing the contents,
or just duid type may be specified as DUID_TYPE_EN, in which case we
we fill in the values. In the future more support for other types may
be added, e.g. DUID_TYPE_LLT.

There still remains and ugly discrepancy between dhcp4 and dhcp6 code:
dhcp6 has sd_dhcp6_client_set_duid and sd_dhcp6_client_set_iaid and
requires client->state to be DHCP6_STATE_STOPPED, while dhcp4 has
sd_dhcp_client_set_iaid_duid and will reconfigure the client if it
is not stopped. This commit doesn't touch that part.

This addresses #3127 § 2.

src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp6-client.c
src/network/networkd-manager.c

index 2ca25c9b337255d59755981c22acfbe1d5e6397f..3846cf74760c8c4cba01bd1ec440d2f85afad1d8 100644 (file)
@@ -318,6 +318,11 @@ int sd_dhcp_client_set_client_id(
         return 0;
 }
 
+/**
+ * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
+ * without further modification. Otherwise, if duid_type is supported, DUID
+ * is set based on that type. Otherwise, an error is returned.
+ */
 int sd_dhcp_client_set_iaid_duid(
                 sd_dhcp_client *client,
                 uint32_t iaid,
@@ -327,9 +332,18 @@ int sd_dhcp_client_set_iaid_duid(
 
         DHCP_CLIENT_DONT_DESTROY(client);
         int r;
+        size_t len;
+
         assert_return(client, -EINVAL);
-        zero(client->client_id);
+        assert_return(duid_len == 0 || duid != NULL, -EINVAL);
+
+        if (duid != NULL) {
+                r = dhcp_validate_duid_len(duid_type, duid_len);
+                if (r < 0)
+                        return r;
+        }
 
+        zero(client->client_id);
         client->client_id.type = 255;
 
         /* If IAID is not configured, generate it. */
@@ -342,22 +356,18 @@ int sd_dhcp_client_set_iaid_duid(
         } else
                 client->client_id.ns.iaid = htobe32(iaid);
 
-        /* If DUID is not configured, generate DUID-EN. */
-        if (duid_len == 0) {
-                r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
-                                                &duid_len);
-                if (r < 0)
-                        return r;
-        } else {
-                r = dhcp_validate_duid_len(client->client_id.type, duid_len);
-                if (r < 0)
-                        return r;
+        if (duid != NULL) {
                 client->client_id.ns.duid.type = htobe16(duid_type);
                 memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
-                duid_len += sizeof(client->client_id.ns.duid.type);
-        }
+                len = sizeof(client->client_id.ns.duid.type) + duid_len;
+        } else if (duid_type == DUID_TYPE_EN) {
+                r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
+                if (r < 0)
+                        return r;
+        } else
+                return -EOPNOTSUPP;
 
-        client->client_id_len = sizeof(client->client_id.type) + duid_len +
+        client->client_id_len = sizeof(client->client_id.type) + len +
                                 sizeof(client->client_id.ns.iaid);
 
         if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
index d3714b174f675c36cfa367f23b2af3518878566d..4adb053a57a83f53b520db38d8df86e0eb9d4f42 100644 (file)
@@ -186,6 +186,11 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
         return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
 }
 
+/**
+ * Sets DUID. If duid is non-null, the DUID is set to duid_type + duid
+ * without further modification. Otherwise, if duid_type is supported, DUID
+ * is set based on that type. Otherwise, an error is returned.
+ */
 int sd_dhcp6_client_set_duid(
                 sd_dhcp6_client *client,
                 uint16_t duid_type,
@@ -194,16 +199,25 @@ int sd_dhcp6_client_set_duid(
 
         int r;
         assert_return(client, -EINVAL);
+        assert_return(duid_len == 0 || duid != NULL, -EINVAL);
         assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
 
-        if (duid_len > 0) {
+        if (duid != NULL) {
                 r = dhcp_validate_duid_len(duid_type, duid_len);
                 if (r < 0)
                         return r;
+        }
+
+        if (duid != NULL) {
                 client->duid.type = htobe16(duid_type);
                 memcpy(&client->duid.raw.data, duid, duid_len);
-                client->duid_len = duid_len + sizeof(client->duid.type);
-        }
+                client->duid_len = sizeof(client->duid.type) + duid_len;
+        } else if (duid_type == DUID_TYPE_EN) {
+                r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
+                if (r < 0)
+                        return r;
+        } else
+                return -EOPNOTSUPP;
 
         return 0;
 }
index d355aaa19c8d598530d8fe9666e1ff0eace43c4d..0cb5781c7189859829862153447e79b976a51441 100644 (file)
@@ -1037,7 +1037,7 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        m->duid_type = _DUID_TYPE_INVALID;
+        m->duid_type = DUID_TYPE_EN;
 
         *ret = m;
         m = NULL;