ip: support dhcp-send-release in NMSettingIpConfig

Introduce a new option to NMSettingIpConfig. The new option is ternary
type being the default value set to disabled. When enabled,
NetworkManager will instruct the DHCP client to send RELEASE message
when IP addresses are being removed.
This commit is contained in:
Fernando Fernandez Mancera 2024-01-26 14:04:51 +01:00
parent 243cc433fb
commit ac4e63ddda
15 changed files with 1069 additions and 668 deletions

View file

@ -950,6 +950,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-send-release</varname></term>
<listitem><para>Whether the DHCP client will send RELEASE message when bringing the connection down.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv4.dhcp-timeout</varname></term>
<listitem><para>If left unspecified, the default value for
@ -1003,6 +1007,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-send-release</varname></term>
<listitem><para>Whether the DHCP client will send RELEASE message when bringing the connection down.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv6.dhcp-timeout</varname></term>
<listitem><para>If left unspecified, the default value for

View file

@ -10806,11 +10806,38 @@ _dev_ipdhcpx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state)
static void
_dev_ipdhcpx_cleanup(NMDevice *self, int addr_family, gboolean full_cleanup, gboolean force_release)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMSettingIPConfig *s_ip4 = NULL;
NMSettingIPConfig *s_ip6 = NULL;
gboolean release;
_dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
if (IS_IPv4)
s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG);
else
s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG);
if ((IS_IPv4 && s_ip4) || (!IS_IPv4 && s_ip6)) {
if (nm_setting_ip_config_get_dhcp_send_release(IS_IPv4 ? s_ip4 : s_ip6)
== NM_TERNARY_DEFAULT)
release = nm_config_data_get_connection_default_int64(
NM_CONFIG_GET_DATA,
IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-send-release")
: NM_CON_DEFAULT("ipv6.dhcp-send-release"),
self,
NM_TERNARY_FALSE,
NM_TERNARY_TRUE,
NM_TERNARY_FALSE);
else
release = nm_setting_ip_config_get_dhcp_send_release(IS_IPv4 ? s_ip4 : s_ip6);
release = force_release || (release && full_cleanup);
} else {
release = force_release;
}
if (full_cleanup && !IS_IPv4) {
priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE;
priv->ipdhcp_data_6.v6.needed_prefixes = 0;
@ -10822,7 +10849,7 @@ _dev_ipdhcpx_cleanup(NMDevice *self, int addr_family, gboolean full_cleanup, gbo
if (priv->ipdhcp_data_x[IS_IPv4].client) {
nm_clear_g_signal_handler(priv->ipdhcp_data_x[IS_IPv4].client,
&priv->ipdhcp_data_x[IS_IPv4].notify_sigid);
nm_dhcp_client_stop(priv->ipdhcp_data_x[IS_IPv4].client, force_release);
nm_dhcp_client_stop(priv->ipdhcp_data_x[IS_IPv4].client, release);
g_clear_object(&priv->ipdhcp_data_x[IS_IPv4].client);
}
@ -16666,6 +16693,10 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
_cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE, FALSE);
}
break;
case NM_DEVICE_STATE_DEACTIVATING:
/* If we are now deactivating we should enforce IP cleanup. */
_cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_DECONFIGURE, FALSE);
_cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE, FALSE);
default:
break;
}

View file

@ -1483,6 +1483,11 @@ stop(NMDhcpClient *client, gboolean release)
NMDhcpNettools *self = NM_DHCP_NETTOOLS(client);
NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
if (release) {
if (n_dhcp4_client_probe_release(priv->probe))
_LOGT("dhcp-client4: failed to send request with RELEASE message");
}
NM_DHCP_CLIENT_CLASS(nm_dhcp_nettools_parent_class)->stop(client, release);
_LOGT("dhcp-client4: stop " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(priv->client));

View file

@ -464,6 +464,10 @@ stop(NMDhcpClient *client, gboolean release)
if (!priv->client6)
return;
r = sd_dhcp6_client_set_send_release(priv->client6, release);
if (r)
_LOGT("dhcp-client6: failed setting send-release");
sd_dhcp6_client_set_callback(priv->client6, NULL, NULL);
r = sd_dhcp6_client_stop(priv->client6);
if (r)

View file

@ -1983,4 +1983,5 @@ libnm_1_48_0 {
global:
nm_setting_connection_down_on_poweroff_get_type;
nm_setting_connection_get_down_on_poweroff;
nm_setting_ip_config_get_dhcp_send_release;
} libnm_1_46_0;

View file

@ -1600,6 +1600,10 @@
dbus-type="b"
gprop-type="gboolean"
/>
<property name="dhcp-send-release"
dbus-type="i"
gprop-type="NMTernary"
/>
<property name="dhcp-timeout"
dbus-type="i"
gprop-type="gint"
@ -1739,6 +1743,10 @@
dbus-type="b"
gprop-type="gboolean"
/>
<property name="dhcp-send-release"
dbus-type="i"
gprop-type="NMTernary"
/>
<property name="dhcp-timeout"
dbus-type="i"
gprop-type="gint"

View file

@ -4004,7 +4004,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig,
PROP_DHCP_IAID,
PROP_DHCP_REJECT_SERVERS,
PROP_AUTO_ROUTE_EXT_GW,
PROP_REPLACE_LOCAL_RULE, );
PROP_REPLACE_LOCAL_RULE,
PROP_DHCP_SEND_RELEASE, );
G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING)
@ -5463,6 +5464,22 @@ nm_setting_ip_config_get_replace_local_rule(NMSettingIPConfig *setting)
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->replace_local_rule;
}
/**
* nm_setting_ip_config_get_dhcp_send_release:
* @setting: the #NMSettingIPConfig
*
* Returns: the #NMSettingIPConfig:dhcp-send-release property of the setting
*
* Since: 1.48
**/
NMTernary
nm_setting_ip_config_get_dhcp_send_release(NMSettingIPConfig *setting)
{
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NM_TERNARY_DEFAULT);
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_send_release;
}
static gboolean
verify_label(const char *label)
{
@ -6150,6 +6167,14 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family)
NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule),
.direct_data.enum_gtype = NM_TYPE_TERNARY);
_nm_properties_override_gobj(
properties_override,
obj_properties[PROP_DHCP_SEND_RELEASE],
&nm_sett_info_propert_type_direct_enum,
.direct_offset =
NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, dhcp_send_release),
.direct_data.enum_gtype = NM_TYPE_TERNARY);
_nm_properties_override_gobj(
properties_override,
obj_properties[PROP_DNS_SEARCH],
@ -6903,5 +6928,23 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass)
NM_TERNARY_DEFAULT,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* NMSettingIPConfig:dhcp-send-release:
*
* Whether the DHCP client will send RELEASE message when
* bringing the connection down. The default value is %NM_TERNARY_DEFAULT.
* When the default value is specified, then the global value from NetworkManager
* configuration is looked up, if not set, it is considered as %FALSE.
*
* Since: 1.48
*/
obj_properties[PROP_DHCP_SEND_RELEASE] =
g_param_spec_enum(NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE,
"",
"",
NM_TYPE_TERNARY,
NM_TERNARY_DEFAULT,
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

@ -189,6 +189,7 @@ typedef struct {
gint64 route_metric;
int auto_route_ext_gw;
int replace_local_rule;
int dhcp_send_release;
gint32 required_timeout;
gint32 dad_timeout;
gint32 dhcp_timeout;

View file

@ -4089,6 +4089,7 @@ test_connection_diff_a_only(void)
{NM_SETTING_IP4_CONFIG_LINK_LOCAL, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE, NM_SETTING_DIFF_RESULT_IN_A},
{NULL, NM_SETTING_DIFF_RESULT_UNKNOWN},
}},
};

View file

@ -342,6 +342,7 @@ char *nm_ip_routing_rule_to_string(const NMIPRoutingRule *self,
#define NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS "dhcp-reject-servers"
#define NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW "auto-route-ext-gw"
#define NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE "replace-local-rule"
#define NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE "dhcp-send-release"
/* these are not real GObject properties. */
#define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules"
@ -509,6 +510,8 @@ NM_AVAILABLE_IN_1_42
NMTernary nm_setting_ip_config_get_auto_route_ext_gw(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_44
NMTernary nm_setting_ip_config_get_replace_local_rule(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_48
NMTernary nm_setting_ip_config_get_dhcp_send_release(NMSettingIPConfig *setting);
G_END_DECLS

View file

@ -6343,6 +6343,9 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = {
PROPERTY_INFO (NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_REPLACE_LOCAL_RULE,
.property_type = &_pt_gobject_ternary,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_RELEASE,
.property_type = &_pt_gobject_ternary,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES,
.property_type = &_pt_gobject_bool,
),
@ -6613,6 +6616,9 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = {
PROPERTY_INFO (NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_REPLACE_LOCAL_RULE,
.property_type = &_pt_gobject_ternary,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_RELEASE,
.property_type = &_pt_gobject_ternary,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
.property_type = &_pt_gobject_bool,
),

View file

@ -174,6 +174,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_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_SEND_HOSTNAME 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.")
#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.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server name can be specified by appending \"#example.com\" to the IP address of the DNS server. This currently only has effect when using systemd-resolved.")
@ -205,6 +206,7 @@
#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_SEND_HOSTNAME 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.")
#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.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server name can be specified by appending \"#example.com\" to the IP address of the DNS server. This currently only has effect when using systemd-resolved.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("DNS options for /etc/resolv.conf as described in resolv.conf(5) manual. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"ndots\", \"no-aaaa\", \"no-check-names\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\" and \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"no-ip6-dotint\". See the resolv.conf(5) manual. Note that there is a distinction between an unset (default) list and an empty list. In nmcli, to unset the list set the value to \"\". To set an empty list, set it to \" \". Currently, an unset list has the same meaning as an empty list. That might change in the future. The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled. When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then \"edns0\" and \"trust-ad\" are automatically added. The valid \"ipv4.dns-options\" and \"ipv6.dns-options\" get merged together.")

View file

@ -1301,6 +1301,10 @@
nmcli-description="Connections will default to keep the autogenerated priority 0 local rule unless this setting is set to TRUE."
format="ternary"
values="true/yes/on, false/no/off, default/unknown" />
<property name="dhcp-send-release"
nmcli-description="Whether the DHCP client will send RELEASE message when bringing the connection down. The default value is &quot;default&quot; (-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."
format="ternary"
values="true/yes/on, false/no/off, default/unknown" />
<property name="ignore-auto-routes"
nmcli-description="When &quot;method&quot; is set to &quot;auto&quot; and this property to TRUE, automatically configured routes are ignored and only routes specified in the &quot;routes&quot; property, if any, are used."
format="boolean"
@ -1415,6 +1419,10 @@
nmcli-description="Connections will default to keep the autogenerated priority 0 local rule unless this setting is set to TRUE."
format="ternary"
values="true/yes/on, false/no/off, default/unknown" />
<property name="dhcp-send-release"
nmcli-description="Whether the DHCP client will send RELEASE message when bringing the connection down. The default value is &quot;default&quot; (-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."
format="ternary"
values="true/yes/on, false/no/off, default/unknown" />
<property name="ignore-auto-routes"
nmcli-description="When &quot;method&quot; is set to &quot;auto&quot; and this property to TRUE, automatically configured routes are ignored and only routes specified in the &quot;routes&quot; property, if any, are used."
format="boolean"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff