mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 06:00:08 +01:00
ip: shared: stop using the global forwarding
As we introduced the ipv4.forwarding property ina8a2e6d727('ip-config: Support configuring per-device IPv4 sysctl forwarding option'), we must not enable or disable the global forwarding setting in the kernel, as it affects to all the devices, maybe forcing them to behave in a way different to what the user requested in ipv4.forwarding. Instead, we need to selectively enable or disable the per-device forwarding settings. Specifically, only devices activated with ipv4.forwarding=auto must have their forwarding enabled or disabled depending on shared connections. Devices with yes/no must not be affected by shared connections. Also, devices with ipv4.forwarding=auto must get the proper forwarding value on activation, but also change it when shared connections appear or disappear dynamically. Use the new sharing-ipv4-change signal from nm_manager to achieve it. Fixes:a8a2e6d727('ip-config: Support configuring per-device IPv4 sysctl forwarding option') (cherry picked from commit32cbf4c629)
This commit is contained in:
parent
d8e3561eaf
commit
2a264ee841
1 changed files with 93 additions and 33 deletions
|
|
@ -692,6 +692,8 @@ typedef struct _NMDevicePrivate {
|
|||
|
||||
IPDevStateData ipdev_data_unspec;
|
||||
|
||||
gulong sharing_ipv4_changed_id;
|
||||
|
||||
struct {
|
||||
/* If we set the addrgenmode6, this records the previously set value. */
|
||||
guint8 previous_mode_val;
|
||||
|
|
@ -866,6 +868,8 @@ static void _dev_ipshared4_spawn_dnsmasq(NMDevice *self);
|
|||
|
||||
static void _dev_ipshared6_start(NMDevice *self);
|
||||
|
||||
static void _dev_ipforwarding4_start(NMDevice *self, int addr_family);
|
||||
|
||||
static void
|
||||
_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean preserve_dhcp);
|
||||
|
||||
|
|
@ -13163,17 +13167,12 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family)
|
|||
goto out_devip;
|
||||
|
||||
if (IS_IPv4) {
|
||||
NMSettingIPConfigForwarding ipv4_forwarding = _prop_get_ipv4_forwarding(self);
|
||||
|
||||
if (NM_IN_SET(ipv4_forwarding,
|
||||
NM_SETTING_IP_CONFIG_FORWARDING_NO,
|
||||
NM_SETTING_IP_CONFIG_FORWARDING_YES)) {
|
||||
nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", ipv4_forwarding ? "1" : "0");
|
||||
}
|
||||
priv->ipll_data_4.v4.mode = _prop_get_ipv4_link_local(self);
|
||||
if (priv->ipll_data_4.v4.mode == NM_SETTING_IP4_LL_ENABLED)
|
||||
_dev_ipll4_start(self);
|
||||
|
||||
_dev_ipforwarding4_start(self, addr_family);
|
||||
|
||||
if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
|
||||
_dev_ipdhcpx_start(self, AF_INET);
|
||||
else if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
|
|
@ -13608,19 +13607,6 @@ _dev_ipshared4_init(NMDevice *self)
|
|||
break;
|
||||
}
|
||||
|
||||
if (nm_platform_sysctl_get_int32(nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"),
|
||||
-1)
|
||||
== 1) {
|
||||
/* nothing to do. */
|
||||
} else if (!nm_platform_sysctl_set(nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"),
|
||||
"1")) {
|
||||
errsv = errno;
|
||||
_LOGW_ipshared(AF_INET, "error enabling IPv4 forwarding: %s", nm_strerror_native(errsv));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_platform_sysctl_get_int32(nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_dynaddr"),
|
||||
-1)
|
||||
|
|
@ -13815,28 +13801,102 @@ _dev_ipshared6_start(NMDevice *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Set the device's forwarding to the specified value. If %NM_TERNARY_DEFAULT is specified,
|
||||
* it's set to the kernel's default, otherwise it's set to the specific value.
|
||||
*/
|
||||
static void
|
||||
_dev_ipforwarding_cleanup(NMDevice *self, int addr_family, CleanupType cleanup_type)
|
||||
_dev_ipforwarding4_set(NMDevice *self, NMTernary val)
|
||||
{
|
||||
gs_free const char *default_forwarding = NULL;
|
||||
gs_free const char *current_forwarding = NULL;
|
||||
const char *val_str;
|
||||
|
||||
if (val != NM_TERNARY_DEFAULT) {
|
||||
val_str = val ? "1" : "0";
|
||||
} else {
|
||||
default_forwarding = nm_platform_sysctl_get(
|
||||
nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"));
|
||||
|
||||
if (!default_forwarding) {
|
||||
_LOGW(LOGD_DEVICE,
|
||||
"error setting IPv4 forwarding: can't read default forwarding value: %s",
|
||||
nm_strerror_native(errno));
|
||||
return; /* Non fatal */
|
||||
}
|
||||
|
||||
val_str = default_forwarding;
|
||||
}
|
||||
|
||||
current_forwarding = nm_device_sysctl_ip_conf_get(self, AF_INET, "forwarding");
|
||||
if (nm_streq0(current_forwarding, val_str))
|
||||
return;
|
||||
|
||||
if (!nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", val_str))
|
||||
_LOGW(LOGD_DEVICE,
|
||||
"error setting IPv4 forwarding to '%s': %s",
|
||||
val_str,
|
||||
nm_strerror_native(errno));
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipforwarding4_auto_cb(NMManager *manager, gboolean sharing_ipv4, gpointer data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE(data);
|
||||
|
||||
_dev_ipforwarding4_set(self, sharing_ipv4 ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipforwarding4_start(NMDevice *self, int addr_family)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
NMSettingIPConfigForwarding ipv4_forwarding = _prop_get_ipv4_forwarding(self);
|
||||
NMTernary new_forwarding = NM_TERNARY_DEFAULT;
|
||||
|
||||
/* IPv6 per-interface forwarding not supported yet */
|
||||
if (addr_family != AF_INET)
|
||||
return;
|
||||
|
||||
if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
|
||||
new_forwarding = NM_TERNARY_TRUE;
|
||||
} else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_YES) {
|
||||
new_forwarding = NM_TERNARY_TRUE;
|
||||
} else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_NO) {
|
||||
new_forwarding = NM_TERNARY_FALSE;
|
||||
} else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_AUTO) {
|
||||
if (nm_manager_get_sharing_ipv4(NM_MANAGER_GET))
|
||||
new_forwarding = NM_TERNARY_TRUE;
|
||||
else
|
||||
new_forwarding = NM_TERNARY_DEFAULT;
|
||||
|
||||
if (!priv->sharing_ipv4_changed_id)
|
||||
priv->sharing_ipv4_changed_id = g_signal_connect(NM_MANAGER_GET,
|
||||
NM_MANAGER_SHARING_IPV4_CHANGED,
|
||||
G_CALLBACK(_dev_ipforwarding4_auto_cb),
|
||||
self);
|
||||
} else {
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
||||
_dev_ipforwarding4_set(self, new_forwarding);
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipforwarding_cleanup(NMDevice *self, int addr_family, CleanupType cleanup_type)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
|
||||
if (!NM_IS_IPv4(addr_family))
|
||||
return;
|
||||
|
||||
if (!NM_IN_SET(cleanup_type, CLEANUP_TYPE_DECONFIGURE, CLEANUP_TYPE_KEEP_REAPPLY))
|
||||
return;
|
||||
nm_clear_g_signal_handler(NM_MANAGER_GET, &priv->sharing_ipv4_changed_id);
|
||||
|
||||
default_forwarding = nm_platform_sysctl_get(
|
||||
nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"));
|
||||
|
||||
if (!default_forwarding)
|
||||
return; /* Non fatal */
|
||||
|
||||
current_forwarding = nm_device_sysctl_ip_conf_get(self, AF_INET, "forwarding");
|
||||
if (!nm_streq0(current_forwarding, default_forwarding))
|
||||
nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", default_forwarding);
|
||||
if (NM_IN_SET(cleanup_type, CLEANUP_TYPE_DECONFIGURE, CLEANUP_TYPE_KEEP_REAPPLY)) {
|
||||
/* Deconfigure by restoring kernel's default */
|
||||
_dev_ipforwarding4_set(self, NM_TERNARY_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue