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 58287cbcc0 ('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: 58287cbcc0 ('core: rework IP configuration in NetworkManager using layer 3 configuration')
This commit is contained in:
Thomas Haller
2022-12-12 20:29:30 +01:00
parent 28d7f9b7c4
commit bea72c3d6d
2 changed files with 23 additions and 8 deletions

View File

@@ -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);

View File

@@ -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,17 +633,17 @@ 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);
NMDhcpClient *client = NM_DHCP_CLIENT(self);
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
const NMDhcpClientConfig *client_config;
GBytes *duid = NULL;