nm-device: avoid improper IPv6 MTU configuration

Ensure it's always (before address configuration starts and on updates) >= 1280
and not higher than the device MTU.

(cherry picked from commit fbf3a93c6bb88632ca4c8480ddbd04ca1dee151a)
This commit is contained in:
Lubomir Rintel 2015-02-25 15:35:26 +01:00
parent 9b79e6c732
commit 6a8a4d0c28

View file

@ -467,6 +467,12 @@ nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *val
return nm_platform_sysctl_set (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), property), value);
}
static guint32
nm_device_ipv6_sysctl_get_int32 (NMDevice *self, const char *property, gint32 fallback)
{
return nm_platform_sysctl_get_int32 (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), property), fallback);
}
static gboolean
device_has_capability (NMDevice *self, NMDeviceCapabilities caps)
{
@ -4032,21 +4038,53 @@ print_support_extended_ifa_flags (NMSettingIP6ConfigPrivacy use_tempaddr)
warn = 2;
}
static void nm_device_ipv6_set_mtu (NMDevice *self, guint32 mtu);
static void
nm_device_set_mtu (NMDevice *self, guint32 mtu)
{
/* MTU */
if (mtu && mtu != nm_platform_link_get_mtu (ifindex))
nm_platform_link_set_mtu (ifindex, mtu);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
int ifindex = nm_device_get_ifindex (self);
if (mtu)
priv->mtu = mtu;
/* Ensure the IPv6 MTU is still alright. */
if (priv->ip6_mtu)
nm_device_ipv6_set_mtu (self, priv->ip6_mtu);
if (priv->mtu != nm_platform_link_get_mtu (ifindex))
nm_platform_link_set_mtu (ifindex, priv->mtu);
}
static void
nm_device_ipv6_set_mtu (NMDevice *self, guint32 mtu)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint32 plat_mtu = nm_device_ipv6_sysctl_get_int32 (self, "mtu", priv->mtu);
char val[16];
if (mtu) {
priv->ip6_mtu = mtu ?: plat_mtu;
if (priv->ip6_mtu && priv->mtu < priv->ip6_mtu) {
_LOGW (LOGD_DEVICE | LOGD_IP6, "Lowering IPv6 MTU (%d) to match device MTU (%d)",
priv->ip6_mtu, priv->mtu);
priv->ip6_mtu = priv->mtu;
}
if (priv->ip6_mtu < 1280) {
_LOGW (LOGD_DEVICE | LOGD_IP6, "IPv6 MTU (%d) smaller than 1280, adjusting",
priv->ip6_mtu);
priv->ip6_mtu = 1280;
}
if (priv->mtu < priv->ip6_mtu) {
_LOGW (LOGD_DEVICE | LOGD_IP6, "Raising device MTU (%d) to match IPv6 MTU (%d)",
priv->mtu, priv->ip6_mtu);
nm_device_set_mtu (self, priv->ip6_mtu);
}
if (priv->ip6_mtu != plat_mtu) {
g_snprintf (val, sizeof (val), "%d", mtu);
nm_device_ipv6_sysctl_set (self, "mtu", val);
}
@ -4542,6 +4580,13 @@ act_stage3_ip6_config_start (NMDevice *self,
return NM_ACT_STAGE_RETURN_STOP;
}
/* Ensure the MTU makes sense. If it was below 1280 the kernel would not
* expose any ipv6 sysctls or allow presence of any addresses on the interface,
* including LL, which * would make it impossible to autoconfigure MTU to a
* correct value. */
if (!nm_device_uses_assumed_connection (self))
nm_device_ipv6_set_mtu (self, priv->ip6_mtu);
/* Any method past this point requires an IPv6LL address. Use NM-controlled
* IPv6LL if this is not an assumed connection, since assumed connections
* will already have IPv6 set up.