Add dhcp-request-options setting

Add a setting to request additional dhcp options from a DHCP server.
This is intended to be used for external software like dispatcher
scripts, which want to query these additional option values.
This commit is contained in:
Sven Püschel 2025-09-23 11:00:21 +02:00
parent 19b065bc4a
commit c06bfae5fd
15 changed files with 1398 additions and 695 deletions

View file

@ -982,6 +982,10 @@ ipv6.ip6-privacy=0
<term><varname>ipv4.dhcp-hostname-flags</varname></term>
<listitem><para>If left unspecified, the value 3 (fqdn-encoded,fqdn-serv-update) is used.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv4.dhcp-request-options</varname></term>
<listitem><para>A comma or space separated list of additional DHCP option numbers to request. The returned option values can be used by external components like dispatcher scripts.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv4.dhcp-send-hostname</varname></term>
<listitem><para>Whether a hostname is sent to the DHCP server when acquiring a lease. When the property is not specified in the connection, the global value from NetworkManager configuration is looked up. If the global value is not set, the value from ipv4.dhcp-send-hostname-deprecated, which defaults to true, is used for backwards compatibility. In the future this will change and, in absence of a global default, it will always fallback to true.</para></listitem>
@ -1046,6 +1050,10 @@ ipv6.ip6-privacy=0
<term><varname>ipv6.dhcp-hostname-flags</varname></term>
<listitem><para>If left unspecified, the value 1 (fqdn-serv-update) is used.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv6.dhcp-request-options</varname></term>
<listitem><para>A comma or space separated list of additional DHCP option numbers to request. The returned option values can be used by external components like dispatcher scripts.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv6.dhcp-send-hostname</varname></term>
<listitem><para>Whether a hostname is sent to the DHCP server when acquiring a lease. When the property is not specified in the connection, the global value from NetworkManager configuration is looked up. If the global value is not set, the value from ipv6.dhcp-send-hostname-deprecated, which defaults to true, is used for backwards compatibility. In the future this will change and, in absence of a global default, it will always fallback to true.</para></listitem>

View file

@ -2204,6 +2204,56 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family)
return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6;
}
static GArray *
_prop_get_ipvx_dhcp_request_options(NMDevice *self, int addr_family)
{
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMSettingIPConfig *s_ip = IS_IPv4
? nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG)
: nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG);
const char *defval;
gs_free const char **split = NULL;
const char **iter;
GArray *ret;
guint i;
if (nm_setting_ip_config_has_dhcp_request_options(s_ip)) {
const guint num = nm_setting_ip_config_get_num_dhcp_request_options(s_ip);
ret = g_array_sized_new(FALSE, FALSE, sizeof(guint16), num);
for (i = 0; i < num; i++) {
guint16 option = nm_setting_ip_config_get_dhcp_request_option(s_ip, i);
g_array_append_val(ret, option);
}
return ret;
}
defval =
nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-request-options")
: NM_CON_DEFAULT("ipv6.dhcp-request-options"),
self);
ret = g_array_new(FALSE, FALSE, sizeof(guint16));
split = nm_strsplit_set(defval, ", ");
if (!split)
return ret;
for (iter = split; *iter; iter++) {
guint64 val;
guint16 u16val;
/* use 65536 as max to have it as a fallback for invalid values */
val = _nm_utils_ascii_str_to_uint64(*iter, 10, 0, 65536, 256);
if (val > 65535)
continue;
u16val = (guint16) val;
g_array_append_val(ret, u16val);
}
return ret;
}
static gboolean
_prop_get_ipvx_dhcp_send_hostname(NMDevice *self, int addr_family)
{
@ -11774,6 +11824,7 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
const char *str;
gboolean request_broadcast;
const char *fail_reason;
GArray *request_additional_options;
if (priv->ipdhcp_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_NONE)
_dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_PENDING);
@ -11836,7 +11887,8 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
return;
}
no_lease_timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family);
no_lease_timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family);
request_additional_options = _prop_get_ipvx_dhcp_request_options(self, addr_family);
if (IS_IPv4) {
NMDhcpClientConfig config;
@ -11883,23 +11935,24 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
}
config = (NMDhcpClientConfig) {
.addr_family = AF_INET,
.l3cfg = nm_device_get_l3cfg(self),
.iface = nm_device_get_ip_iface(self),
.iface_type_log = nm_device_get_type_desc_for_log(self),
.uuid = nm_connection_get_uuid(connection),
.hwaddr = hwaddr,
.bcast_hwaddr = bcast_hwaddr,
.send_hostname = _prop_get_ipvx_dhcp_send_hostname(self, AF_INET),
.hostname = hostname,
.hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
.client_id = client_id,
.mud_url = _prop_get_connection_mud_url(self, s_con),
.timeout = no_lease_timeout_sec,
.anycast_address = _device_get_dhcp_anycast_address(self),
.vendor_class_identifier = vendor_class_identifier,
.use_fqdn = hostname_is_fqdn,
.reject_servers = reject_servers,
.addr_family = AF_INET,
.l3cfg = nm_device_get_l3cfg(self),
.iface = nm_device_get_ip_iface(self),
.iface_type_log = nm_device_get_type_desc_for_log(self),
.uuid = nm_connection_get_uuid(connection),
.hwaddr = hwaddr,
.bcast_hwaddr = bcast_hwaddr,
.send_hostname = _prop_get_ipvx_dhcp_send_hostname(self, AF_INET),
.hostname = hostname,
.hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
.client_id = client_id,
.mud_url = _prop_get_connection_mud_url(self, s_con),
.timeout = no_lease_timeout_sec,
.anycast_address = _device_get_dhcp_anycast_address(self),
.vendor_class_identifier = vendor_class_identifier,
.use_fqdn = hostname_is_fqdn,
.reject_servers = reject_servers,
.request_additional_options = request_additional_options,
.v4 =
{
.request_broadcast = request_broadcast,
@ -11925,18 +11978,19 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid);
config = (NMDhcpClientConfig) {
.addr_family = AF_INET6,
.l3cfg = nm_device_get_l3cfg(self),
.iface = nm_device_get_ip_iface(self),
.iface_type_log = nm_device_get_type_desc_for_log(self),
.uuid = nm_connection_get_uuid(connection),
.send_hostname = _prop_get_ipvx_dhcp_send_hostname(self, AF_INET6),
.hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip),
.hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
.client_id = duid,
.mud_url = _prop_get_connection_mud_url(self, s_con),
.timeout = no_lease_timeout_sec,
.anycast_address = _device_get_dhcp_anycast_address(self),
.addr_family = AF_INET6,
.l3cfg = nm_device_get_l3cfg(self),
.iface = nm_device_get_ip_iface(self),
.iface_type_log = nm_device_get_type_desc_for_log(self),
.uuid = nm_connection_get_uuid(connection),
.send_hostname = _prop_get_ipvx_dhcp_send_hostname(self, AF_INET6),
.hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip),
.hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
.client_id = duid,
.mud_url = _prop_get_connection_mud_url(self, s_con),
.timeout = no_lease_timeout_sec,
.anycast_address = _device_get_dhcp_anycast_address(self),
.request_additional_options = request_additional_options,
.v6 =
{
.enforce_duid = enforce_duid,

View file

@ -1574,6 +1574,7 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release)
nm_clear_l3cd(&priv->l3cd_next);
nm_clear_l3cd(&priv->l3cd_curr);
nm_clear_pointer(&priv->config.request_additional_options, g_array_unref);
_nm_dhcp_client_notify(self, NM_DHCP_CLIENT_EVENT_TYPE_TERMINATED, NULL);
}

View file

@ -151,6 +151,8 @@ typedef struct {
* For DHCPv6 this is always TRUE. */
bool use_fqdn : 1;
GArray *request_additional_options;
union {
struct {
/* The address from the previous lease */

View file

@ -2134,4 +2134,11 @@ global:
nm_utils_wifi_6ghz_freqs;
nm_utils_wifi_freq_to_band;
nm_wifi_band_get_type;
nm_setting_ip_config_has_dhcp_request_options;
nm_setting_ip_config_get_num_dhcp_request_options;
nm_setting_ip_config_get_dhcp_request_option;
nm_setting_ip_config_add_dhcp_request_option;
nm_setting_ip_config_remove_dhcp_request_option;
nm_setting_ip_config_remove_dhcp_request_option_by_value;
nm_setting_ip_config_clear_dhcp_request_options;
} libnm_1_56_0;

View file

@ -1720,6 +1720,10 @@
dbus-type="as"
gprop-type="GStrv"
/>
<property name="dhcp-request-options"
dbus-type="au"
gprop-type="GArray"
/>
<property name="dhcp-send-hostname"
dbus-type="b"
gprop-type="gboolean"
@ -1883,6 +1887,10 @@
dbus-type="as"
gprop-type="GStrv"
/>
<property name="dhcp-request-options"
dbus-type="au"
gprop-type="GArray"
/>
<property name="dhcp-send-hostname"
dbus-type="b"
gprop-type="gboolean"

View file

@ -4010,7 +4010,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig,
PROP_ROUTED_DNS,
PROP_SHARED_DHCP_RANGE,
PROP_SHARED_DHCP_LEASE_TIME,
PROP_FORWARDING, );
PROP_FORWARDING,
PROP_DHCP_REQUEST_OPTIONS, );
G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING)
@ -4641,6 +4642,188 @@ nm_setting_ip_config_get_address(NMSettingIPConfig *setting, int idx)
return priv->addresses->pdata[idx];
}
static gssize
_dhcp_request_option_find_idx_garray(const GArray *arr, guint16 option)
{
gsize i;
if (!arr)
return -1;
for (i = 0; i < arr->len; i++)
if (nm_g_array_index(arr, guint32, i) == option)
return i;
return -1;
}
/**
* nm_setting_ip_config_has_dhcp_request_options:
* @setting: the #NMSettingIPConfig
*
* NMSettingIPConfig can have a list of DHCP options that are
* additionally requested from the DHCP server. If the list
* is empty, there are two similar (but differentiated) states.
* Either the options are explicitly set to have no values,
* or the options are left undefined. The latter means to use
* a default configuration, while the former explicitly means "no-options".
*
* Returns: whether DHCP options are initialized or left unset (the default).
*
* Since: 1.58
**/
gboolean
nm_setting_ip_config_has_dhcp_request_options(NMSettingIPConfig *setting)
{
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0);
return !!NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_request_options;
}
/**
* nm_setting_ip_config_get_num_dhcp_request_options:
* @setting: the #NMSettingIPConfig
*
* Returns: the number of additional DHCP options to request
*
* Since: 1.58
**/
guint
nm_setting_ip_config_get_num_dhcp_request_options(NMSettingIPConfig *setting)
{
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0);
return nm_g_array_len(NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_request_options);
}
/**
* nm_setting_ip_config_get_dhcp_request_option:
* @setting: the #NMSettingIPConfig
* @idx: index number of the option to return
*
* Returns: the DHCP option at index @idx
*
* Since: 1.58
**/
guint16
nm_setting_ip_config_get_dhcp_request_option(NMSettingIPConfig *setting, int idx)
{
NMSettingIPConfigPrivate *priv;
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0);
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting);
g_return_val_if_fail(idx < nm_g_array_len(priv->dhcp_request_options), 0);
return nm_g_array_index(priv->dhcp_request_options, guint32, idx);
}
/**
* nm_setting_ip_config_add_dhcp_request_option:
* @setting: the #NMSettingIPConfig
* @option: the DHCP option number as string to add
*
* Adds a new DHCP option to the setting.
*
* Since: 1.58
**/
void
nm_setting_ip_config_add_dhcp_request_option(NMSettingIPConfig *setting, guint16 option)
{
NMSettingIPConfigPrivate *priv;
guint32 u32val;
g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting));
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting);
if (!priv->dhcp_request_options)
priv->dhcp_request_options = g_array_new(FALSE, FALSE, sizeof(guint32));
else if (_dhcp_request_option_find_idx_garray(priv->dhcp_request_options, option) >= 0)
return;
u32val = option;
g_array_append_val(priv->dhcp_request_options, u32val);
_notify(setting, PROP_DHCP_REQUEST_OPTIONS);
}
/**
* nm_setting_ip_config_remove_dhcp_request_option:
* @setting: the #NMSettingIPConfig
* @idx: index number of the DHCP option number
*
* Removes the DHCP option at index @idx.
*
* Since: 1.58
**/
void
nm_setting_ip_config_remove_dhcp_request_option(NMSettingIPConfig *setting, guint idx)
{
NMSettingIPConfigPrivate *priv;
g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting));
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting);
g_return_if_fail(idx < nm_g_array_len(priv->dhcp_request_options));
g_array_remove_index(priv->dhcp_request_options, idx);
_notify(setting, PROP_DHCP_REQUEST_OPTIONS);
}
/**
* nm_setting_ip_config_remove_dhcp_request_option_by_value:
* @setting: the #NMSettingIPConfig
* @option: the DHCP option to remove
*
* Removes the DHCP option @dhcp_option.
*
* Returns: %TRUE if the DHCP option was found and removed; %FALSE if it was not.
*
* Since: 1.58
**/
gboolean
nm_setting_ip_config_remove_dhcp_request_option_by_value(NMSettingIPConfig *setting, guint16 option)
{
NMSettingIPConfigPrivate *priv;
gssize i;
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE);
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting);
i = _dhcp_request_option_find_idx_garray(priv->dhcp_request_options, option);
if (i < 0)
return FALSE;
g_array_remove_index(priv->dhcp_request_options, i);
_notify(setting, PROP_DHCP_REQUEST_OPTIONS);
return TRUE;
}
/**
* nm_setting_ip_config_clear_dhcp_request_options:
* @setting: the #NMSettingIPConfig
*
* Removes all additional requested DHCP options.
*
* Since: 1.58
**/
void
nm_setting_ip_config_clear_dhcp_request_options(NMSettingIPConfig *setting)
{
NMSettingIPConfigPrivate *priv;
g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting));
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting);
if (!priv->dhcp_request_options)
return;
nm_clear_pointer(&priv->dhcp_request_options, g_array_unref);
_notify(setting, PROP_DHCP_REQUEST_OPTIONS);
}
/**
* nm_setting_ip_config_add_address:
* @setting: the #NMSettingIPConfig
@ -6160,6 +6343,29 @@ dns_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
return TRUE;
}
static void
_nm_setting_ip_config_u32_array_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil)
{
gconstpointer array;
GArray *new_array;
gsize length;
array = g_variant_get_fixed_array(from, &length, sizeof(guint32));
new_array = g_array_sized_new(FALSE, FALSE, sizeof(guint32), length);
g_array_append_vals(new_array, array, length);
g_value_take_boxed(to, new_array);
}
static const NMSettInfoPropertType nm_sett_info_propert_type_dhcp_options_au = {
.dbus_type = NM_G_VARIANT_TYPE("au"),
.typdata_to_dbus.gprop_type = NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_GARRAY_UINT,
.typdata_from_dbus.gprop_fcn = _nm_setting_ip_config_u32_array_from_dbus,
.compare_fcn = _nm_setting_property_compare_fcn_default,
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_gprop,
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
.from_dbus_is_full = TRUE};
GArray *
_nm_sett_info_property_override_create_array_ip_config(int addr_family)
{
@ -6410,6 +6616,10 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family)
.direct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, forwarding),
.direct_data.enum_gtype = NM_TYPE_SETTING_IP_CONFIG_FORWARDING);
_nm_properties_override_gobj(properties_override,
obj_properties[PROP_DHCP_REQUEST_OPTIONS],
&nm_sett_info_propert_type_dhcp_options_au);
return properties_override;
}
@ -6437,6 +6647,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
(NMUtilsCopyFunc) nm_ip_route_dup,
(GDestroyNotify) nm_ip_route_unref));
break;
case PROP_DHCP_REQUEST_OPTIONS:
g_value_set_boxed(value, priv->dhcp_request_options);
break;
default:
_nm_setting_property_get_property_direct(object, prop_id, value, pspec);
break;
@ -6449,6 +6662,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
NMSettingIPConfig *setting = NM_SETTING_IP_CONFIG(object);
NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting);
gs_unref_array GArray *array = NULL;
const GArray *src_array;
const char *const *strv;
guint i;
@ -6494,6 +6708,18 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
(NMUtilsCopyFunc) nm_ip_route_dup,
(GDestroyNotify) nm_ip_route_unref);
break;
case PROP_DHCP_REQUEST_OPTIONS:
src_array = g_value_get_boxed(value);
if (src_array) {
array = g_array_sized_new(FALSE, FALSE, sizeof(guint32), src_array->len);
for (i = 0; i < src_array->len; i++) {
guint32 val = nm_g_array_index(src_array, guint32, i);
g_array_append_val(array, val);
}
} else
array = NULL;
NM_SWAP(&priv->dhcp_request_options, &array);
break;
default:
_nm_setting_property_set_property_direct(object, prop_id, value, pspec);
break;
@ -6527,6 +6753,7 @@ finalize(GObject *object)
g_ptr_array_unref(priv->addresses);
g_ptr_array_unref(priv->routes);
nm_g_ptr_array_unref(priv->routing_rules);
nm_g_array_unref(priv->dhcp_request_options);
G_OBJECT_CLASS(nm_setting_ip_config_parent_class)->finalize(object);
}
@ -7305,5 +7532,22 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass)
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | NM_SETTING_PARAM_FUZZY_IGNORE
| G_PARAM_STATIC_STRINGS);
/**
* NMSettingIPConfig:dhcp-request-options:
*
* Array of additional DHCP option numbers to request.
*
* This is intended to request additional DHCP options, which are handled by external components
* like dispatcher scripts. This property expects the options as numbers in base 10.
*
* Since: 1.58
**/
obj_properties[PROP_DHCP_REQUEST_OPTIONS] =
g_param_spec_boxed(NM_SETTING_IP_CONFIG_DHCP_REQUEST_OPTIONS,
"",
"",
G_TYPE_ARRAY,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}

View file

@ -181,6 +181,7 @@ struct _NMSettingIPConfigClass {
typedef struct {
NMValueStrv dns_search; /* array of domain name strings */
NMValueStrv dhcp_reject_servers;
GArray *dhcp_request_options;
NMValueStrv dns_options; /* array of DNS options */
GPtrArray *dns; /* array of IP address strings */
GPtrArray *addresses; /* array of NMIPAddress */

View file

@ -4078,6 +4078,7 @@ test_connection_diff_a_only(void)
{NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_REQUEST_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME_V2, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A},

View file

@ -386,6 +386,7 @@ char *nm_ip_routing_rule_to_string(const NMIPRoutingRule *self,
#define NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE "shared-dhcp-range"
#define NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME "shared-dhcp-lease-time"
#define NM_SETTING_IP_CONFIG_FORWARDING "forwarding"
#define NM_SETTING_IP_CONFIG_DHCP_REQUEST_OPTIONS "dhcp-request-options"
/* these are not real GObject properties. */
#define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules"
@ -570,6 +571,22 @@ NMSettingIPConfigForwarding nm_setting_ip_config_get_forwarding(NMSettingIPConfi
NM_AVAILABLE_IN_1_56
gboolean nm_dns_server_validate(const char *str, int family, GError **error);
NM_AVAILABLE_IN_1_58
gboolean nm_setting_ip_config_has_dhcp_request_options(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_58
guint nm_setting_ip_config_get_num_dhcp_request_options(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_58
guint16 nm_setting_ip_config_get_dhcp_request_option(NMSettingIPConfig *setting, int idx);
NM_AVAILABLE_IN_1_58
void nm_setting_ip_config_add_dhcp_request_option(NMSettingIPConfig *setting, guint16 option);
NM_AVAILABLE_IN_1_58
void nm_setting_ip_config_remove_dhcp_request_option(NMSettingIPConfig *setting, guint idx);
NM_AVAILABLE_IN_1_58
gboolean nm_setting_ip_config_remove_dhcp_request_option_by_value(NMSettingIPConfig *setting,
guint16 option);
NM_AVAILABLE_IN_1_58
void nm_setting_ip_config_clear_dhcp_request_options(NMSettingIPConfig *setting);
G_END_DECLS
#endif /* NM_SETTING_IP_CONFIG_H */

View file

@ -3588,6 +3588,48 @@ _is_default_func_ip_config_dns_options(NMSetting *setting)
return !nm_setting_ip_config_has_dns_options(NM_SETTING_IP_CONFIG(setting));
}
static void
_obj_to_str_ip_config_dhcp_request_options(NMMetaAccessorGetType get_type,
NMSetting *setting,
guint idx,
GString *str)
{
guint16 val = nm_setting_ip_config_get_dhcp_request_option(NM_SETTING_IP_CONFIG(setting), idx);
g_string_append_printf(str, "%" G_GUINT16_FORMAT, val);
}
static gboolean
_set_fcn_ip_config_dhcp_request_options(NMSetting *setting,
gboolean do_add,
const char *value,
GError **error)
{
NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting);
guint64 val;
val = _nm_utils_ascii_str_to_uint64(value, 10, 0, 65536, 65536);
if (val == 65536) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_SETTING,
_("DHCP option value '%s' not between 0 and 65535"),
value);
return FALSE;
}
nm_setting_ip_config_remove_dhcp_request_option_by_value(s_ip, val);
if (do_add)
nm_setting_ip_config_add_dhcp_request_option(s_ip, val);
return TRUE;
}
static gboolean
_is_default_func_ip_config_dhcp_request_options(NMSetting *setting)
{
return !nm_setting_ip_config_has_dhcp_request_options(NM_SETTING_IP_CONFIG(setting));
}
static void
_objlist_obj_to_str_fcn_ip_config_routing_rules(NMMetaAccessorGetType get_type,
NMSetting *setting,
@ -6698,6 +6740,21 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = {
),
),
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_REQUEST_OPTIONS, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_REQUEST_OPTIONS,
.property_type = &_pt_objlist,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
PROPERTY_TYP_DATA_SUBTYPE (objlist,
.get_num_fcn = OBJLIST_GET_NUM_FCN (NMSettingIPConfig, nm_setting_ip_config_get_num_dhcp_request_options),
.obj_to_str_fcn = _obj_to_str_ip_config_dhcp_request_options,
.set_fcn = _set_fcn_ip_config_dhcp_request_options,
.clear_all_fcn = OBJLIST_CLEAR_ALL_FCN (NMSettingIPConfig, nm_setting_ip_config_clear_dhcp_request_options),
.remove_by_idx_fcn_u = OBJLIST_REMOVE_BY_IDX_FCN_U (NMSettingIPConfig, nm_setting_ip_config_remove_dhcp_request_option),
.strsplit_plain = TRUE,
),
.is_default_fcn = _is_default_func_ip_config_dhcp_request_options,
.list_items_doc_format = NM_META_PROPERTY_TYPE_FORMAT_INT,
),
),
NULL
};
@ -7015,6 +7072,21 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_IP6_CONFIG_TOKEN,
.property_type = &_pt_gobject_string,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_REQUEST_OPTIONS, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_REQUEST_OPTIONS,
.property_type = &_pt_objlist,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
PROPERTY_TYP_DATA_SUBTYPE (objlist,
.get_num_fcn = OBJLIST_GET_NUM_FCN (NMSettingIPConfig, nm_setting_ip_config_get_num_dhcp_request_options),
.obj_to_str_fcn = _obj_to_str_ip_config_dhcp_request_options,
.set_fcn = _set_fcn_ip_config_dhcp_request_options,
.clear_all_fcn = OBJLIST_CLEAR_ALL_FCN (NMSettingIPConfig, nm_setting_ip_config_clear_dhcp_request_options),
.remove_by_idx_fcn_u = OBJLIST_REMOVE_BY_IDX_FCN_U (NMSettingIPConfig, nm_setting_ip_config_remove_dhcp_request_option),
.strsplit_plain = TRUE,
),
.is_default_fcn = _is_default_func_ip_config_dhcp_request_options,
.list_items_doc_format = NM_META_PROPERTY_TYPE_FORMAT_STRING,
),
),
NULL
};

View file

@ -196,6 +196,7 @@
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_IAID N_("A string containing the \"Identity Association Identifier\" (IAID) used by the DHCP client. The string can be a 32-bit number (either decimal, hexadecimal or as colon separated hexadecimal numbers). Alternatively it can be set to the special values \"mac\", \"perm-mac\", \"ifname\" or \"stable\". When set to \"mac\" (or \"perm-mac\"), the last 4 bytes of the current (or permanent) MAC address are used as IAID. When set to \"ifname\", the IAID is computed by hashing the interface name. The special value \"stable\" can be used to generate an IAID based on the stable-id (see connection.stable-id), a per-host key and the interface name. When the property is unset, the value from global configuration is used; if no global default is set then the IAID is assumed to be \"ifname\". For DHCPv4, the IAID is only used with \"ipv4.dhcp-client-id\" values \"duid\" and \"ipv6-duid\" to generate the client-id. For DHCPv6, note that at the moment this property is only supported by the \"internal\" DHCPv6 plugin. The \"dhclient\" DHCPv6 plugin always derives the IAID from the MAC address. The actually used DHCPv6 IAID for a currently activated interface is exposed in the lease information of the device.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_IPV6_ONLY_PREFERRED N_("Controls the \"IPv6-Only Preferred\" DHCPv4 option (option 108 - RFC 8925). When set to \"yes\" (1), the host adds the option to the parameter request list; if the DHCP server sends the option back, the host stops the DHCP client for the time interval specified in the option. Enable this feature if the host supports an IPv6-only mode, i.e. either all applications are IPv6-only capable or there is a form of CLAT (464XLAT) deployed. If set to \"auto\" (2), the option is automatically turned on when the IPv6 method is \"auto\" and the connection profile has ipv4.clat set to \"yes\" or \"auto\". If these two conditions are met, the host can operate in IPv6-only mode and therefore it is safe to disable DHCPv4 when the network also supports it. When set to \"default\" (-1), the actual value is looked up in the global configuration; if not specified, it defaults to \"auto\" (2). If the connection has IPv6 method set to \"disabled\", this property does not have effect and the \"IPv6-Only Preferred\" option is always disabled.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_REQUEST_OPTIONS N_("Array of additional DHCP option numbers to request. This is intended to request additional DHCP options, which are handled by external components like dispatcher scripts. This property expects the options as numbers in base 10.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("Since 1.52 this property is deprecated and is only used as fallback value for dhcp-send-hostname if it's set to 'default'. This is only done to avoid breaking existing configurations, the new property should be used from now on.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME_V2 N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the dhcp-hostname property is NULL and this property is TRUE, the current persistent hostname of the computer is sent. The default value is default (-1). In this case the global value from NetworkManager configuration is looked up. If it's not set, the value from dhcp-send-hostname-deprecated, which defaults to TRUE, is used for backwards compatibility. In the future this will change and, in absence of a global default, it will always fallback to TRUE.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_RELEASE N_("Whether the DHCP client will send RELEASE message when bringing the connection down. The default value is \"default\" (-1). When the default value is specified, then the global value from NetworkManager configuration is looked up, if not set, it is considered as FALSE.")
@ -233,6 +234,7 @@
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_IAID N_("A string containing the \"Identity Association Identifier\" (IAID) used by the DHCP client. The string can be a 32-bit number (either decimal, hexadecimal or as colon separated hexadecimal numbers). Alternatively it can be set to the special values \"mac\", \"perm-mac\", \"ifname\" or \"stable\". When set to \"mac\" (or \"perm-mac\"), the last 4 bytes of the current (or permanent) MAC address are used as IAID. When set to \"ifname\", the IAID is computed by hashing the interface name. The special value \"stable\" can be used to generate an IAID based on the stable-id (see connection.stable-id), a per-host key and the interface name. When the property is unset, the value from global configuration is used; if no global default is set then the IAID is assumed to be \"ifname\". For DHCPv4, the IAID is only used with \"ipv4.dhcp-client-id\" values \"duid\" and \"ipv6-duid\" to generate the client-id. For DHCPv6, note that at the moment this property is only supported by the \"internal\" DHCPv6 plugin. The \"dhclient\" DHCPv6 plugin always derives the IAID from the MAC address. The actually used DHCPv6 IAID for a currently activated interface is exposed in the lease information of the device.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_PD_HINT N_("A IPv6 address followed by a slash and a prefix length. If set, the value is sent to the DHCPv6 server as hint indicating the prefix delegation (IA_PD) we want to receive. To only hint a prefix length without prefix, set the address part to the zero address (for example \"::/60\").")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_REQUEST_OPTIONS N_("Array of additional DHCP option numbers to request. This is intended to request additional DHCP options, which are handled by external components like dispatcher scripts. This property expects the options as numbers in base 10.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME N_("Since 1.52 this property is deprecated and is only used as fallback value for dhcp-send-hostname if it's set to 'default'. This is only done to avoid breaking existing configurations, the new property should be used from now on.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME_V2 N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the dhcp-hostname property is NULL and this property is TRUE, the current persistent hostname of the computer is sent. The default value is default (-1). In this case the global value from NetworkManager configuration is looked up. If it's not set, the value from dhcp-send-hostname-deprecated, which defaults to TRUE, is used for backwards compatibility. In the future this will change and, in absence of a global default, it will always fallback to TRUE.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_RELEASE N_("Whether the DHCP client will send RELEASE message when bringing the connection down. The default value is \"default\" (-1). When the default value is specified, then the global value from NetworkManager configuration is looked up, if not set, it is considered as FALSE.")

View file

@ -1508,6 +1508,9 @@
format="integer"
values="0 - 2147483647"
special-values="default (0), infinity (2147483647)" />
<property name="dhcp-request-options"
nmcli-description="Array of additional DHCP option numbers to request. This is intended to request additional DHCP options, which are handled by external components like dispatcher scripts. This property expects the options as numbers in base 10."
format="list of ipv4.dhcp-request-options objects" />
</setting>
<setting name="ipv6" >
<property name="method"
@ -1645,6 +1648,9 @@
<property name="token"
nmcli-description="Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode. When set, the token is used as IPv6 interface identifier instead of the hardware address. This only applies to addresses from stateless autoconfiguration, not to IPv6 link local addresses."
format="string" />
<property name="dhcp-request-options"
nmcli-description="Array of additional DHCP option numbers to request. This is intended to request additional DHCP options, which are handled by external components like dispatcher scripts. This property expects the options as numbers in base 10."
format="list of ipv6.dhcp-request-options objects" />
</setting>
<setting name="ipvlan" >
<property name="parent"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff