summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-12-14 10:37:15 +0100
committerThomas Haller <thaller@redhat.com>2022-12-19 11:33:50 +0100
commit6bc03e9c9517b396aae0f0d0a87bc52d598cf756 (patch)
treeae162a13948b15c1e59e7de54a4fff581d637d66
parentb7d343af05675d2635312c74400d257869de0cdd (diff)
dhcp/dhclient: fix honoring "ipv6.dhcp-duid" when explicitly setth/nm-1-40
Previously, we only set the "default-duid" line in the lease file. That means, if the lease already contained a matching entry with a "dhcp6.client-id" option, it was not honored. That is wrong. If the profile has "ipv6.dhcp-duid" set, then we must use it and get rid of those options from the lease. It's easy to reproduce: PROFILE=eth1 nmcli connection down "$PROFILE" rm -f /var/lib/NetworkManager/*lease nmcli connection modify "$PROFILE" ipv6.dhcp-duid "aa:bb:cc:dd:00:00:11" nmcli connection up "$PROFILE" # Verify the expected duid in /var/lib/NetworkManager/*lease and "/run/NetworkManager/devices/$IFINDEX" nmcli connection modify "$PROFILE" ipv6.dhcp-duid "aa:bb:cc:dd:00:00:22" nmcli connection up "$PROFILE" # Check the DUID again. (cherry picked from commit 1d85608e1c13545556cd90d053d2b959adc354dd)
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient-utils.c35
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient-utils.h5
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c1
-rw-r--r--src/core/dhcp/tests/test-dhcp-dhclient.c6
4 files changed, 40 insertions, 7 deletions
diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c
index 5bc135f02f..ea8943fa1e 100644
--- a/src/core/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c
@@ -524,6 +524,20 @@ nm_dhcp_dhclient_create_config(const char *interface,
return g_string_free(g_steal_pointer(&new_contents), FALSE);
}
+/* In the lease file, dhclient will write "option dhcp6.client-id $HEXSTR". This
+ * function does the same. */
+static char *
+nm_dhcp_dhclient_escape_duid_as_hex(GBytes *duid)
+{
+ const guint8 *s;
+ gsize len;
+
+ nm_assert(duid);
+
+ s = g_bytes_get_data(duid, &len);
+ return nm_utils_bin2hexstr_fuller(s, len, ':', FALSE, FALSE, NULL);
+}
+
/* Roughly follow what dhclient's quotify_buf() and pretty_escape() functions do */
char *
nm_dhcp_dhclient_escape_duid(GBytes *duid)
@@ -648,14 +662,18 @@ nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error)
}
gboolean
-nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error)
+nm_dhcp_dhclient_save_duid(const char *leasefile,
+ GBytes *duid,
+ gboolean enforce_duid,
+ GError **error)
{
gs_free char *escaped_duid = NULL;
gs_free const char **lines = NULL;
nm_auto_free_gstring GString *s = NULL;
const char *const *iter;
- gs_free char *contents = NULL;
- gsize contents_len = 0;
+ gs_free char *conflicting_duid_line = NULL;
+ gs_free char *contents = NULL;
+ gsize contents_len = 0;
g_return_val_if_fail(leasefile != NULL, FALSE);
@@ -702,6 +720,17 @@ nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error)
continue;
}
+ if (enforce_duid & NM_STR_HAS_PREFIX(l, "option dhcp6.client-id ")) {
+ /* we want to use our duid. Skip the per-lease client-id. */
+ if (!conflicting_duid_line) {
+ gs_free char *duid_hex = nm_dhcp_dhclient_escape_duid_as_hex(duid);
+
+ conflicting_duid_line = g_strdup_printf("option dhcp6.client-id %s;", duid_hex);
+ }
+ /* We adjust the duid line and set what we want. */
+ l = conflicting_duid_line;
+ }
+
g_string_append_len(s, str, prefix_len);
g_string_append(s, l);
if (ends_with_r) {
diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.h b/src/core/dhcp/nm-dhcp-dhclient-utils.h
index 0ce7dd90f0..6187cce0fb 100644
--- a/src/core/dhcp/nm-dhcp-dhclient-utils.h
+++ b/src/core/dhcp/nm-dhcp-dhclient-utils.h
@@ -29,6 +29,9 @@ GBytes *nm_dhcp_dhclient_unescape_duid(const char *duid);
GBytes *nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error);
-gboolean nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error);
+gboolean nm_dhcp_dhclient_save_duid(const char *leasefile,
+ GBytes *duid,
+ gboolean enforce_duid,
+ GError **error);
#endif /* __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ */
diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c
index 7e578d13ad..e4f40d7cb0 100644
--- a/src/core/dhcp/nm-dhcp-dhclient.c
+++ b/src/core/dhcp/nm-dhcp-dhclient.c
@@ -418,6 +418,7 @@ dhclient_start(NMDhcpClient *client,
if (set_duid && addr_family == AF_INET6) {
if (!nm_dhcp_dhclient_save_duid(priv->lease_file,
nm_dhcp_client_get_effective_client_id(client),
+ client_config->v6.enforce_duid,
&local)) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c
index 6daf689145..937ac2e3d6 100644
--- a/src/core/dhcp/tests/test-dhcp-dhclient.c
+++ b/src/core/dhcp/tests/test-dhcp-dhclient.c
@@ -897,7 +897,7 @@ test_read_commented_duid_from_leasefile(void)
static void
_check_duid_impl(const guint8 *duid_bin,
gsize duid_len,
- gboolean enforce_duid, /* Unused at the moment. */
+ gboolean enforce_duid,
const char *old_content,
const char *new_content)
{
@@ -919,7 +919,7 @@ _check_duid_impl(const guint8 *duid_bin,
duid = g_bytes_new(duid_bin, duid_len);
- success = nm_dhcp_dhclient_save_duid(path, duid, &error);
+ success = nm_dhcp_dhclient_save_duid(path, duid, enforce_duid, &error);
nmtst_assert_success(success, error);
success = g_file_get_contents(path, &contents, &contents_len, &error);
@@ -1060,7 +1060,7 @@ test_write_duid(void)
" max-life 120;\n }\n }\n option fqdn.encoded true;\n option "
"fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn "
"\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id "
- "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option "
+ "aa:b:cc:d:ee:e;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option "
"dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn "
"1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success "
"\"success\";\n}\n");