From 1d6b9953ad3b7cbfe593da06aac435c95e562a30 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 May 2020 19:05:12 +0200 Subject: device: set accept_ra to 1 when changing IPv6 kernel token Setting the kernel token is not strictly necessary as the IPv6 address is generated in userspace by NetworkManager. However it is convenient for users to see that the value set in the profile is also set in the kernel, to confirm that everything is working as expected. The kernel allows setting a token only when 'accept_ra' is 1: temporarily flip it if necessary. Unfortunately this will also generate an additional Router Solicitation from kernel, but this is not a big issue. --- src/devices/nm-device.c | 56 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index dc46d3f7cc..1a3efaefec 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1509,6 +1509,50 @@ nm_device_sysctl_ip_conf_get_int_checked (NMDevice *self, fallback); } +static void +set_ipv6_token (NMDevice *self, NMUtilsIPv6IfaceId iid, const char *token_str) +{ + NMPlatform *platform; + int ifindex; + const NMPlatformLink *link; + char buf[32]; + gint64 val; + + /* Setting the kernel token is not strictly necessary as the + * IPv6 address is generated in userspace. However it is + * convenient so that users can see the token with iproute + * ('ip token'). */ + platform = nm_device_get_platform (self); + ifindex = nm_device_get_ip_ifindex (self); + link = nm_platform_link_get (platform, ifindex); + + if (link && link->inet6_token.id == iid.id) { + _LOGT (LOGD_DEVICE | LOGD_IP6, "token %s already set", token_str); + return; + } + + /* The kernel allows setting a token only when 'accept_ra' + * is 1: temporarily flip it if necessary; unfortunately + * this will also generate an additional Router Solicitation + * from kernel. */ + val = nm_device_sysctl_ip_conf_get_int_checked (self, + AF_INET6, + "accept_ra", + 10, + G_MININT32, + G_MAXINT32, + 1); + if (val != 1) + nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra", "1"); + + nm_platform_link_set_ipv6_token (platform, ifindex, iid); + + if (val != 1) { + nm_sprintf_buf (buf, "%d", (int) val); + nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra", buf); + } +} + gboolean nm_device_sysctl_ip_conf_set (NMDevice *self, int addr_family, @@ -8178,23 +8222,13 @@ ip_config_merge_and_apply (NMDevice *self, } if (!IS_IPv4) { - const NMPlatformLink *link; NMUtilsIPv6IfaceId iid; - NMPlatform *platform; - int ifindex; if ( commit && priv->ndisc_started && ip6_addr_gen_token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, ip6_addr_gen_token)) { - platform = nm_device_get_platform (self); - ifindex = nm_device_get_ip_ifindex (self); - link = nm_platform_link_get (platform, ifindex); - - if (link && link->inet6_token.id == iid.id) - _LOGT (LOGD_DEVICE | LOGD_IP6, "token %s already set", ip6_addr_gen_token); - else - nm_platform_link_set_ipv6_token (platform, ifindex, iid); + set_ipv6_token (self, iid, ip6_addr_gen_token); } } -- cgit v1.2.1 From 49305559dc2a1244a3c9c80e9cec2a0d0c25960d Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 May 2020 19:05:31 +0200 Subject: core: clear IPv6 kernel token when deactivating a device Clear the IPv6 kernel token when deactivating a device. --- src/devices/nm-device.c | 2 ++ src/platform/nm-platform.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 1a3efaefec..9b018ccc8c 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -15730,11 +15730,13 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean /* Take out any entries in the routing table and any IP address the device had. */ if (ifindex > 0) { NMPlatform *platform = nm_device_get_platform (self); + NMUtilsIPv6IfaceId iid = { }; nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex); nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex); nm_platform_tfilter_sync (platform, ifindex, NULL); nm_platform_qdisc_sync (platform, ifindex, NULL); + set_ipv6_token (self, iid, "::"); } } diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 5ac788f73f..b7a43a0ea1 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1572,7 +1572,6 @@ nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6Iface _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (iid.id, FALSE); if (klass->link_set_token) return klass->link_set_token (self, ifindex, iid); -- cgit v1.2.1