summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2022-10-24 17:12:42 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2023-04-03 16:04:55 +0200
commite2b9019ac0c26e2f51c15f24e6abcdcd05dcdc9b (patch)
tree3fff5e156ac69788ec715f0e87c135a21e8d4f4c
parentf9c1d06e64d1172648260730ba54cc4d07c3ec37 (diff)
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.
-rw-r--r--src/core/devices/nm-device.c16
-rw-r--r--src/core/dhcp/nm-dhcp-client.h4
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c12
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c9
4 files changed, 41 insertions, 0 deletions
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) {