diff options
author | Thomas Haller <thaller@redhat.com> | 2022-12-14 10:37:15 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-12-19 11:33:50 +0100 |
commit | 6bc03e9c9517b396aae0f0d0a87bc52d598cf756 (patch) | |
tree | ae162a13948b15c1e59e7de54a4fff581d637d66 | |
parent | b7d343af05675d2635312c74400d257869de0cdd (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.c | 35 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-dhclient-utils.h | 5 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-dhclient.c | 1 | ||||
-rw-r--r-- | src/core/dhcp/tests/test-dhcp-dhclient.c | 6 |
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"); |