From 75c1ddce19a8d47c138297102eafa5661db74da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20P=C3=BCschel?= Date: Wed, 29 Oct 2025 16:02:20 +0100 Subject: [PATCH] dhcp-client4: implement additional DHCP request options Implement requesting additional DHCP options in the internal DHCPv4 client and encode the returned values as hex string to be used by external components like dispatcher scripts. --- src/core/dhcp/nm-dhcp-nettools.c | 27 +++++++++++++++++++-- src/libnm-core-impl/nm-setting-ip4-config.c | 18 ++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index 35d71e8b55..c671a77694 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -18,6 +18,7 @@ #include "libnm-glib-aux/nm-dedup-multi.h" #include "libnm-glib-aux/nm-io-utils.h" #include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-shared-utils.h" #include "libnm-std-aux/unaligned.h" #include "NetworkManagerUtils.h" @@ -636,11 +637,14 @@ lease_to_ip4_config(NMDhcpNettools *self, NDhcp4ClientLease *lease, GError **err const guint8 *l_data; gsize l_data_len; const char *v_str; + char *v_mut_str; guint16 v_u16; in_addr_t v_inaddr; in_addr_t lease_address; struct in_addr v_inaddr_s; int r; + gsize i; + const NMDhcpClientConfig *client_config; nm_assert(lease); @@ -650,6 +654,8 @@ lease_to_ip4_config(NMDhcpNettools *self, NDhcp4ClientLease *lease, GError **err options = nm_dhcp_client_create_options_dict(NM_DHCP_CLIENT(self), TRUE); + client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self)); + if (!lease_parse_address(self, lease, l3cd, iface, options, &lease_address, error)) return NULL; @@ -703,8 +709,6 @@ lease_to_ip4_config(NMDhcpNettools *self, NDhcp4ClientLease *lease, GError **err nm_str_buf_reset(&sbuf); if (domains) { - gsize i; - for (i = 0; domains[i]; i++) { gs_free char *s = NULL; @@ -865,6 +869,19 @@ lease_to_ip4_config(NMDhcpNettools *self, NDhcp4ClientLease *lease, GError **err _add_option(options, NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, v_str ?: ""); } + for (i = 0; i < client_config->request_additional_options->len; i++) { + guint8 option_id = nm_g_array_index(client_config->request_additional_options, guint16, i); + r = _client_lease_query(lease, option_id, &l_data, &l_data_len); + if (r == 0) { + v_mut_str = nm_utils_bin2hexstr_fuller(l_data, l_data_len, '\0', TRUE, TRUE, NULL); + nm_dhcp_option_take_option(options, + TRUE, + AF_INET, + option_id, + g_steal_pointer(&v_mut_str)); + } + } + lease_parse_address_list(lease, l3cd, iface, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf); lease_parse_address_list(lease, @@ -1430,6 +1447,12 @@ ip4_start(NMDhcpClient *client, GError **error) NM_DHCP_OPTION_DHCP4_IPV6_ONLY_PREFERRED); } + for (i = 0; i < client_config->request_additional_options->len; i++) { + n_dhcp4_client_probe_config_request_option( + config, + nm_g_array_index(client_config->request_additional_options, guint16, i)); + } + if (client_config->mud_url) { r = n_dhcp4_client_probe_config_append_option(config, NM_DHCP_OPTION_DHCP4_MUD_URL, diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 5cc4f47213..e0c9dc62b3 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -7,6 +7,7 @@ #include "nm-setting-ip4-config.h" +#include "libnm-glib-aux/nm-shared-utils.h" #include "nm-setting-private.h" #include "nm-utils-private.h" @@ -195,6 +196,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); NMSettingVerifyResult ret; const char *method; + gsize i; ret = NM_SETTING_CLASS(nm_setting_ip4_config_parent_class)->verify(setting, connection, error); if (ret != NM_SETTING_VERIFY_SUCCESS) @@ -391,6 +393,22 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) && !nm_utils_validate_dhcp4_vendor_class_id(priv->dhcp_vendor_class_identifier, error)) return FALSE; + for (i = 0; i < nm_g_array_len(priv->parent.dhcp_request_options); i++) { + guint32 value = nm_g_array_index(priv->parent.dhcp_request_options, guint32, i); + if (value > 255) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("DHCPv4 options value %d higher than the maximum possible value 255"), + value); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_DHCP_REQUEST_OPTIONS); + return FALSE; + } + } + /* Failures from here on are NORMALIZABLE_ERROR... */ if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)