From dc4d39a2d4582eb5092651f5a86f6e77488dafa0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Dec 2014 14:30:36 -0600 Subject: core: don't assume connections for INTERNAL or PARENT unmanaged devices INTERNAL is actually a nop right now because the only thing that sets it is suspend/resume, which is covered by the preceding manager_sleeping() call. But we may use this more in the future, so add it while we're here. Devices that are unmanaged because their parent is unmanaged probably shouldn't assume connections either, per 4e105c50. --- src/nm-manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 06f24abdb8..bed07e4162 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1653,7 +1653,9 @@ recheck_assume_connection (NMDevice *device, gpointer user_data) if (manager_sleeping (self)) return FALSE; - if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_USER)) + if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_USER) || + nm_device_get_unmanaged_flag (device, NM_UNMANAGED_INTERNAL) || + nm_device_get_unmanaged_flag (device, NM_UNMANAGED_PARENT)) return FALSE; state = nm_device_get_state (device); -- cgit v1.2.1 From fa41627152df08216dc21a85a9412c83b0a5dcb8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 3 Dec 2014 12:47:30 -0600 Subject: core: don't manage externally created software devices until IFF_UP (rh #1030947) (bgo #725647) Externally created software devices would be managed/assumed immediately upon creation, which includes setting them IFF_UP and possibly turning on NM-managed IPv6LL. With this commit, expected behavior for external software devices is: 1) created: unmanaged state, no further action 2) IP address added but !IFF_UP: connection assumed, but device is not set IFF_UP 3) slave attached but !IFF_UP: connection assumed, but master is not set IFF_UP 3) set IFF_UP: connection assumed (if any), if not -> DISCONNECTED This branch ensures that external software devices are not set IFF_UP by NetworkManager when they are discovered. It additionally ensures that they are not set IFF_UP during connection assumption. They may be set IFF_UP later through specific user action. https://bugzilla.gnome.org/show_bug.cgi?id=725647 https://bugzilla.redhat.com/show_bug.cgi?id=1030947 --- src/devices/nm-device.c | 76 ++++++++++++++++++++++++++++++++++++++++++------- src/devices/nm-device.h | 12 ++++---- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c04a973877..c8cd66c6a0 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -977,6 +977,13 @@ nm_device_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure return success; } +static gboolean +is_software_external (NMDevice *self) +{ + return nm_device_is_software (self) + && !nm_device_get_is_nm_owned (self); +} + /** * nm_device_finish_init: * @self: the master device @@ -989,6 +996,12 @@ nm_device_finish_init (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + /* Do not manage externally created software devices until they are IFF_UP */ + if ( is_software_external (self) + && !nm_platform_link_is_up (priv->ifindex) + && priv->ifindex > 0) + nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); + if (priv->master) nm_device_enslave_slave (priv->master, self, NULL); } @@ -1228,10 +1241,41 @@ device_link_changed (NMDevice *self, NMPlatformLink *info) if (klass->link_changed) klass->link_changed (self, info); - /* Update DHCP, etc, if needed */ if (ip_ifname_changed) update_for_ip_ifname_change (self); + + /* Manage externally-created software interfaces only when they are IFF_UP */ + if ( is_software_external (self) + && (nm_device_get_state (self) <= NM_DEVICE_STATE_DISCONNECTED) + && priv->ifindex > 0) { + gboolean external_down = nm_device_get_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN); + + if (external_down && info->up) { + /* Ensure the assume check is queued before any queued state changes + * from the transition to UNAVAILABLE. + */ + nm_device_queue_recheck_assume (self); + + /* Resetting the EXTERNAL_DOWN flag may change the device's state + * to UNAVAILABLE. To ensure that the state change doesn't touch + * the device before assumption occurs, pass + * NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED as the reason. + */ + nm_device_set_unmanaged (self, + NM_UNMANAGED_EXTERNAL_DOWN, + FALSE, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } else if (!external_down && !info->up) { + /* If the device is already disconnected and is set !IFF_UP, + * unmanage it. + */ + nm_device_set_unmanaged (self, + NM_UNMANAGED_EXTERNAL_DOWN, + TRUE, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + } } static void @@ -6607,7 +6651,7 @@ nm_device_get_managed (NMDevice *self) gboolean nm_device_get_unmanaged_flag (NMDevice *self, NMUnmanagedFlags flag) { - return NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags & flag; + return NM_FLAGS_ANY (NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags, flag); } /** @@ -7352,6 +7396,17 @@ notify_ip_properties (NMDevice *self) g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); } +static void +ip6_managed_setup (NMDevice *self) +{ + set_nm_ipv6ll (self, TRUE); + set_disable_ipv6 (self, "1"); + nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0"); + nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0"); + nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0"); + nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0"); +} + static void _set_state_full (NMDevice *self, NMDeviceState state, @@ -7428,14 +7483,8 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_UNAVAILABLE: if (old_state == NM_DEVICE_STATE_UNMANAGED) { save_ip6_properties (self); - if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { - set_nm_ipv6ll (self, TRUE); - set_disable_ipv6 (self, "1"); - nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0"); - nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0"); - nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0"); - nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0"); - } + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + ip6_managed_setup (self); } if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { @@ -7462,6 +7511,13 @@ _set_state_full (NMDevice *self, set_nm_ipv6ll (self, TRUE); nm_device_cleanup (self, reason); + } else if (old_state < NM_DEVICE_STATE_DISCONNECTED) { + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + /* Ensure IPv6 is set up as it may not have been done when + * entering the UNAVAILABLE state depending on the reason. + */ + ip6_managed_setup (self); + } } break; case NM_DEVICE_STATE_NEED_AUTH: diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 38eddaa8df..b3855c7446 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -304,13 +304,15 @@ RfKillType nm_device_get_rfkill_type (NMDevice *device); * because NM is sleeping or not managed for some other reason) * @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs) * @NM_UNMANAGED_PARENT: %TRUE when unmanaged due to parent device being unmanaged + * @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM */ typedef enum { - NM_UNMANAGED_NONE = 0x00, - NM_UNMANAGED_DEFAULT = 0x01, - NM_UNMANAGED_INTERNAL = 0x02, - NM_UNMANAGED_USER = 0x04, - NM_UNMANAGED_PARENT = 0x08, + NM_UNMANAGED_NONE = 0x00, + NM_UNMANAGED_DEFAULT = 0x01, + NM_UNMANAGED_INTERNAL = 0x02, + NM_UNMANAGED_USER = 0x04, + NM_UNMANAGED_PARENT = 0x08, + NM_UNMANAGED_EXTERNAL_DOWN = 0x10, /* Boundary value */ __NM_UNMANAGED_LAST, -- cgit v1.2.1 From 80f15f5284efb147ce8c204699bd9cbc38ef2158 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Dec 2014 14:13:28 -0600 Subject: core: don't bring up devices using assumed connections (bgo #725647) (rh #1030947) We want to export the IP configuration of interfaces when they have some, but the kernel doesn't care if they are IFF_UP or not. Neither should NetworkManager, so don't force devices IFF_UP just because we're assuming their IP config. --- src/devices/nm-device.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c8cd66c6a0..957a8bf691 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -5176,7 +5176,7 @@ nm_device_activate_ip4_config_commit (gpointer user_data) /* Interface must be IFF_UP before IP config can be applied */ ip_ifindex = nm_device_get_ip_ifindex (self); - if (!nm_platform_link_is_up (ip_ifindex)) { + if (!nm_platform_link_is_up (ip_ifindex) && !nm_device_uses_assumed_connection (self)) { nm_platform_link_set_up (ip_ifindex); if (!nm_platform_link_is_up (ip_ifindex)) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); @@ -5287,7 +5287,7 @@ nm_device_activate_ip6_config_commit (gpointer user_data) /* Interface must be IFF_UP before IP config can be applied */ ip_ifindex = nm_device_get_ip_ifindex (self); - if (!nm_platform_link_is_up (ip_ifindex)) { + if (!nm_platform_link_is_up (ip_ifindex) && !nm_device_uses_assumed_connection (self)) { nm_platform_link_set_up (ip_ifindex); if (!nm_platform_link_is_up (ip_ifindex)) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); @@ -7487,21 +7487,23 @@ _set_state_full (NMDevice *self, ip6_managed_setup (self); } - if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { - if (!nm_device_bring_up (self, TRUE, &no_firmware) && no_firmware) - _LOGW (LOGD_HW, "firmware may be missing."); - nm_device_set_firmware_missing (self, no_firmware ? TRUE : FALSE); - } - /* Ensure the device gets deactivated in response to stuff like - * carrier changes or rfkill. But don't deactivate devices that are - * about to assume a connection since that defeats the purpose of - * assuming the device's existing connection. - * - * Note that we "deactivate" the device even when coming from - * UNMANAGED, to ensure that it's in a clean state. - */ - if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { + if (!nm_device_bring_up (self, TRUE, &no_firmware) && no_firmware) + _LOGW (LOGD_HW, "firmware may be missing."); + nm_device_set_firmware_missing (self, no_firmware ? TRUE : FALSE); + } + + /* Ensure the device gets deactivated in response to stuff like + * carrier changes or rfkill. But don't deactivate devices that are + * about to assume a connection since that defeats the purpose of + * assuming the device's existing connection. + * + * Note that we "deactivate" the device even when coming from + * UNMANAGED, to ensure that it's in a clean state. + */ nm_device_cleanup (self, reason); + } break; case NM_DEVICE_STATE_DISCONNECTED: if (old_state > NM_DEVICE_STATE_DISCONNECTED) { -- cgit v1.2.1