aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-04-29 21:18:11 -0400
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-05-03 12:12:04 -0400
commitd7df2fd317bb24d4d194dbd0d391f4dfa64d6924 (patch)
tree7ece328642aa2b95a7a74d8f1e72a9c237ea6a8d
parentdhcp-identifier: un-inline dhcp_validate_duid_len (diff)
downloadsystemd-d7df2fd317bb24d4d194dbd0d391f4dfa64d6924.tar.gz
systemd-d7df2fd317bb24d4d194dbd0d391f4dfa64d6924.tar.bz2
systemd-d7df2fd317bb24d4d194dbd0d391f4dfa64d6924.zip
dh-dhcp{,6}-client: change the semantics of DUID setting
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.
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c38
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c20
-rw-r--r--src/network/networkd-manager.c2
3 files changed, 42 insertions, 18 deletions
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 2ca25c9b3..3846cf747 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -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)) {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index d3714b174..4adb053a5 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -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;
}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index d355aaa19..0cb5781c7 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -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;