From e2b9019ac0c26e2f51c15f24e6abcdcd05dcdc9b Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 24 Oct 2022 17:12:42 +0200 Subject: dhcp: support prefix delegation hint Support the prefix delegation hint in the DHCP client. dhclient only supports a prefix length, emit a warning if the user set a non-zero prefix. --- src/core/devices/nm-device.c | 16 ++++++++++++++++ src/core/dhcp/nm-dhcp-client.h | 4 ++++ src/core/dhcp/nm-dhcp-dhclient.c | 12 ++++++++++++ src/core/dhcp/nm-dhcp-systemd.c | 9 +++++++++ 4 files changed, 41 insertions(+) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index c150cbf6ba..edcf160c4b 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -10631,6 +10631,7 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) gboolean iaid_explicit; guint32 iaid; NMDhcpClientConfig config; + const char *pd_hint; iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, FALSE, &iaid_explicit); duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid); @@ -10657,6 +10658,21 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) }, }; + pd_hint = nm_setting_ip6_config_get_dhcp_pd_hint(NM_SETTING_IP6_CONFIG(s_ip)); + if (pd_hint) { + int pd_hint_length; + gboolean res; + + res = nm_inet_parse_with_prefix_bin(AF_INET6, + pd_hint, + NULL, + &config.v6.pd_hint_addr, + &pd_hint_length); + nm_assert(res); + nm_assert(pd_hint_length > 0 || pd_hint_length <= 128); + config.v6.pd_hint_length = pd_hint_length; + } + priv->ipdhcp_data_6.client = nm_dhcp_manager_start_client(nm_dhcp_manager_get(), &config, &error); } diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index f43770a07b..f21dc9133a 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -174,6 +174,10 @@ typedef struct { /* Number to prefixes (IA_PD) to request */ guint needed_prefixes; + /* A hint to send to server for prefix delegation (IA_PD). */ + struct in6_addr pd_hint_addr; + guint8 pd_hint_length; + /* Use Information-request to get stateless configuration * parameters (don't request a IA_NA) */ bool info_only : 1; diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c index 35b2fb2ebd..4aab4b1efb 100644 --- a/src/core/dhcp/nm-dhcp-dhclient.c +++ b/src/core/dhcp/nm-dhcp-dhclient.c @@ -356,6 +356,7 @@ dhclient_start(NMDhcpClient *client, gs_free char *preferred_leasefile_path = NULL; int addr_family; const NMDhcpClientConfig *client_config; + char pd_length_str[16]; g_return_val_if_fail(!priv->pid_file, FALSE); client_config = nm_dhcp_client_get_config(client); @@ -463,6 +464,17 @@ dhclient_start(NMDhcpClient *client, if (mode_opt) g_ptr_array_add(argv, (gpointer) mode_opt); + + if (prefixes > 0 && client_config->v6.pd_hint_length > 0) { + if (!IN6_IS_ADDR_UNSPECIFIED(&client_config->v6.pd_hint_addr)) { + _LOGW("dhclient only supports a length as prefix delegation hint, not a prefix"); + } + + nm_sprintf_buf(pd_length_str, "%u", client_config->v6.pd_hint_length); + g_ptr_array_add(argv, "--prefix-len-hint"); + g_ptr_array_add(argv, pd_length_str); + } + while (prefixes--) g_ptr_array_add(argv, (gpointer) "-P"); } diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index 6f9312da27..b26a15a45b 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -366,6 +366,15 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error) _LOGW("dhcp-client6: only one prefix request is supported"); } prefix_delegation = TRUE; + if (client_config->v6.pd_hint_length > 0) { + r = sd_dhcp6_client_set_prefix_delegation_hint(sd_client, + client_config->v6.pd_hint_length, + &client_config->v6.pd_hint_addr); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set prefix delegation hint: %s"); + return FALSE; + } + } } r = sd_dhcp6_client_set_prefix_delegation(sd_client, prefix_delegation); if (r < 0) { -- cgit v1.2.1