From bea72c3d6de5a294a89fc659e475fe9db0abf6ac Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 12 Dec 2022 20:29:30 +0100 Subject: [PATCH] dhcp: fix "ipv6.dhcp-duid=lease" for dhclient DHCPv6 client The "lease" mode is unusual, because it means to prefer the DUID configuration from the DHCP plugin over the explicit configuration in NetworkManager. It is only for the DHCPv6 DUID and not for the IPv4 client-id. It also is only special for the "dhclient" plugin, because with the internal plugin, this always corresponds to a generated, stable DUID. Commit 58287cbcc0c8 ('core: rework IP configuration in NetworkManager using layer 3 configuration') broke this. The commit refactored the code to track the effective-client-id separately. Previously, the client-id which was read from the dhclient lease, was overwriting NMDhcpClient.client_id. But with the refactor, it broke because nm_dhcp_client_get_effective_client_id() was never called. Fix that. Fixes: 58287cbcc0c8 ('core: rework IP configuration in NetworkManager using layer 3 configuration') --- src/core/dhcp/nm-dhcp-dhclient-utils.c | 2 ++ src/core/dhcp/nm-dhcp-dhclient.c | 29 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c index 74e6b90507..72dbc7885e 100644 --- a/src/core/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c @@ -399,6 +399,7 @@ nm_dhcp_dhclient_create_config(const char *interface, if (out_new_client_id) nm_clear_pointer(out_new_client_id, g_bytes_unref); NM_SET_OUT(out_new_client_id, read_client_id(p)); + /* fall-through. We keep the line... */ } /* Override config file hostname and use one from the connection */ @@ -656,6 +657,7 @@ nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error) gsize len = 0; g_return_val_if_fail(leasefile != NULL, FALSE); + if (!duid) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing duid"); g_return_val_if_reached(FALSE); diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c index 92b4332a74..34aa7d44e0 100644 --- a/src/core/dhcp/nm-dhcp-dhclient.c +++ b/src/core/dhcp/nm-dhcp-dhclient.c @@ -82,6 +82,10 @@ G_DEFINE_TYPE(NMDhcpDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) /*****************************************************************************/ +static GBytes *read_duid_from_lease(NMDhcpDhclient *self); + +/*****************************************************************************/ + static const char * nm_dhcp_dhclient_get_path(void) { @@ -332,6 +336,7 @@ static gboolean dhclient_start(NMDhcpClient *client, gboolean set_mode, gboolean release, + gboolean set_duid, pid_t *out_pid, GError **error) { @@ -410,8 +415,10 @@ dhclient_start(NMDhcpClient *client, } /* Save the DUID to the leasefile dhclient will actually use */ - if (addr_family == AF_INET6) { - if (!nm_dhcp_dhclient_save_duid(priv->lease_file, client_config->client_id, &local)) { + if (set_duid && addr_family == AF_INET6) { + if (!nm_dhcp_dhclient_save_duid(priv->lease_file, + nm_dhcp_client_get_effective_client_id(client), + &local)) { nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "failed to save DUID to '%s': %s", @@ -560,6 +567,7 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error) NMDhcpDhclient *self = NM_DHCP_DHCLIENT(client); NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); const NMDhcpClientConfig *config; + gs_unref_bytes GBytes *effective_client_id = NULL; config = nm_dhcp_client_get_config(client); @@ -586,7 +594,12 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error) return FALSE; } - return dhclient_start(client, TRUE, FALSE, NULL, error); + nm_assert(config->client_id); + if (!config->v6.enforce_duid) + effective_client_id = read_duid_from_lease(self); + nm_dhcp_client_set_effective_client_id(client, effective_client_id ?: config->client_id); + + return dhclient_start(client, TRUE, FALSE, TRUE, NULL, error); } static void @@ -620,18 +633,18 @@ stop(NMDhcpClient *client, gboolean release) if (release) { pid_t rpid = -1; - if (dhclient_start(client, FALSE, TRUE, &rpid, NULL)) { + if (dhclient_start(client, FALSE, TRUE, FALSE, &rpid, NULL)) { /* Wait a few seconds for the release to happen */ nm_dhcp_client_stop_pid(rpid, nm_dhcp_client_get_iface(client)); } } } -_nm_unused static GBytes * -get_duid(NMDhcpClient *client) +static GBytes * +read_duid_from_lease(NMDhcpDhclient *self) { - NMDhcpDhclient *self = NM_DHCP_DHCLIENT(client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); + NMDhcpClient *client = NM_DHCP_CLIENT(self); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); const NMDhcpClientConfig *client_config; GBytes *duid = NULL; gs_free char *leasefile = NULL;