diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 2ca25c9b33..3846cf7476 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; - assert_return(client, -EINVAL); - zero(client->client_id); + size_t len; + assert_return(client, -EINVAL); + 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 d3714b174f..4adb053a57 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 d355aaa19c..0cb5781c71 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;