From f78a18bf16ea624ab3eb85859c8b7c752d2c563c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Tue, 26 Sep 2023 12:40:52 +0200 Subject: [PATCH] dhcp: allow to not send client-id (option 61) in IPv4 Sending a client-id is not mandatory according to RFC2131. It is mandatory according to RFC4361 that superseedes it. Some weird DHCP servers conforming RFC2131 can get confused and break existing DHCP leases if they start receiving a client-id when it was not being previously received. Users that were using other DHCP client like dhclient, but want to use NetworkManager's internal DHCP client, can suffer this problem. Add "none" as accepted value in ipv4.dhcp-client-id to specify that client-id must not be sent. Note that this is generally not recommended unless it's explicitly needed for some reason like the explained above. Client-id is mandatory in DHCPv6. This commit allow to set the "none" value and properly parse it in the NMDhcpClientConfig struct. Next commits will modify the different DHCP plugins to honor it. --- src/core/devices/nm-device.c | 18 ++++++++++++++++-- src/core/dhcp/nm-dhcp-client.h | 3 +++ src/libnm-core-impl/nm-setting-ip4-config.c | 5 +++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 2a0a156bca..2f7b4f81b8 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -2017,7 +2017,10 @@ _prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con) } static GBytes * -_prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes *hwaddr) +_prop_get_ipv4_dhcp_client_id(NMDevice *self, + NMConnection *connection, + GBytes *hwaddr, + gboolean *out_send_client_id) { NMSettingIPConfig *s_ip4; const char *client_id; @@ -2030,6 +2033,8 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * GBytes *result; gs_free char *logstr1 = NULL; + NM_SET_OUT(out_send_client_id, TRUE); + s_ip4 = nm_connection_get_setting_ip4_config(connection); client_id = nm_setting_ip4_config_get_dhcp_client_id(NM_SETTING_IP4_CONFIG(s_ip4)); @@ -2049,6 +2054,12 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * return NULL; } + if (nm_streq(client_id, "none")) { + _LOGD(LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4, "ipv4.dhcp-client-id: set to \"none\""); + NM_SET_OUT(out_send_client_id, FALSE); + return NULL; + } + if (nm_streq(client_id, "mac")) { if (!hwaddr) { fail_reason = "missing link-layer address"; @@ -10707,8 +10718,10 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) const char *const *reject_servers; const char *hostname; gboolean hostname_is_fqdn; + gboolean send_client_id; + + client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr, &send_client_id); - client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr); vendor_class_identifier = _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip)); reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip, NULL); @@ -10745,6 +10758,7 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) { .request_broadcast = request_broadcast, .acd_timeout_msec = _prop_get_ipv4_dad_timeout(self), + .send_client_id = send_client_id, }, .previous_lease = priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4)].d, }; diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index 903ea6acc2..4dd2c4fd74 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -162,6 +162,9 @@ typedef struct { * will always broadcast replies. */ bool request_broadcast : 1; + /* Whether to send or not the client identifier */ + bool send_client_id : 1; + } v4; struct { /* If set, the DUID from the connection is used; otherwise diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 4e8606feea..1bdc2ebc5d 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -897,6 +897,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * If unset, a globally configured default is used. If still unset, the default * depends on the DHCP plugin. **/ + /* ---nmcli--- + * property: dhcp-client-id + * special-values: mac, perm-mac, duid, ipv6-duid, stable, none + * ---end--- + */ /* ---ifcfg-rh--- * property: dhcp-client-id * variable: DHCP_CLIENT_ID(+)