This makes users can configure DHCPv4 client with ClientIdentifier=duid-only.
If set so, then DHCP client sends only DUID as the client identifier.
This may not be RFC compliant, but some setups require this.
Closes #7828.
<varlistentry>
<term><varname>ClientIdentifier=</varname></term>
<listitem>
- <para>The DHCPv4 client identifier to use. Either <literal>mac</literal> to use the MAC address of the link
- or <literal>duid</literal> (the default, see below) to use an RFC4361-compliant Client ID.</para>
+ <para>The DHCPv4 client identifier to use. Takes one of <literal>mac</literal>, <literal>duid</literal> or <literal>duid-only</literal>.
+ If set to <literal>mac</literal>, the MAC address of the link is used.
+ If set to <literal>duid</literal>, an RFC4361-compliant Client ID, which is the combination of IAID and DUID (see below), is used.
+ If set to <literal>duid-only</literal>, only DUID is used, this may not be RFC compliant, but some setups may require to use this.
+ Defaults to <literal>duid</literal>.</para>
</listitem>
</varlistentry>
* 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(
+static int dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
uint32_t iaid,
+ bool append_iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
zero(client->client_id);
client->client_id.type = 255;
- /* If IAID is not configured, generate it. */
- if (iaid == 0) {
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
- client->mac_addr_len,
- &client->client_id.ns.iaid);
- if (r < 0)
- return r;
- } else
- client->client_id.ns.iaid = htobe32(iaid);
+ if (append_iaid) {
+ /* If IAID is not configured, generate it. */
+ if (iaid == 0) {
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
+ client->mac_addr_len,
+ &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+ } else
+ client->client_id.ns.iaid = htobe32(iaid);
+ }
if (duid != NULL) {
client->client_id.ns.duid.type = htobe16(duid_type);
return -EOPNOTSUPP;
client->client_id_len = sizeof(client->client_id.type) + len +
- sizeof(client->client_id.ns.iaid);
+ (append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured IAID+DUID, restarting.");
return 0;
}
+int sd_dhcp_client_set_iaid_duid(
+ sd_dhcp_client *client,
+ uint32_t iaid,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len);
+}
+
+int sd_dhcp_client_set_duid(
+ sd_dhcp_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len);
+}
+
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname) {
return r;
break;
}
+ case DHCP_CLIENT_ID_DUID_ONLY: {
+ /* If configured, apply user specified DUID */
+ const DUID *duid = link_duid(link);
+
+ r = sd_dhcp_client_set_duid(link->dhcp_client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return r;
+ break;
+ }
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
break;
}
+ case DHCP_CLIENT_ID_DUID_ONLY: {
+ const DUID *duid = link_duid(link);
+
+ r = sd_dhcp_client_set_duid(link->dhcp_client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DUID in DHCP client: %m");
+ break;
+ }
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
[DHCP_CLIENT_ID_MAC] = "mac",
- [DHCP_CLIENT_ID_DUID] = "duid"
+ [DHCP_CLIENT_ID_DUID] = "duid",
+ [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
typedef enum DHCPClientIdentifier {
DHCP_CLIENT_ID_MAC,
DHCP_CLIENT_ID_DUID,
+ /* The following option may not be good for RFC regarding DHCP (3315 and 4361).
+ * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK
+ * requires the client id to be set to a custom string, reported at
+ * https://github.com/systemd/systemd/issues/7828 */
+ DHCP_CLIENT_ID_DUID_ONLY,
_DHCP_CLIENT_ID_MAX,
_DHCP_CLIENT_ID_INVALID = -1,
} DHCPClientIdentifier;
uint16_t duid_type,
const void *duid,
size_t duid_len);
+int sd_dhcp_client_set_duid(
+ sd_dhcp_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len);
int sd_dhcp_client_get_client_id(
sd_dhcp_client *client,
uint8_t *type,