diff options
author | Dan Williams <dcbw@redhat.com> | 2014-12-03 12:47:30 -0600 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2014-12-16 21:55:13 +0100 |
commit | eeb2374cd2c2ddf4a49c8d792033afa3fddb36e0 (patch) | |
tree | 7db2b8175018538ac9e364cb0bd8af814a8dc457 | |
parent | 94091e31db803b4874b921db04f53c76bc75fb86 (diff) | |
download | NetworkManager-eeb2374cd2c2ddf4a49c8d792033afa3fddb36e0.tar.gz |
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
(cherry picked from commit f6a9898f626b8b366b686e4c43d134366d9c6129)
-rw-r--r-- | src/devices/nm-device.c | 87 | ||||
-rw-r--r-- | src/devices/nm-device.h | 13 | ||||
-rw-r--r-- | src/nm-manager.c | 2 |
3 files changed, 87 insertions, 15 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c04a973877..6805175d47 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1153,6 +1153,14 @@ update_for_ip_ifname_change (NMDevice *self) } } +static gboolean +is_software_external (NMDevice *self) +{ + return nm_device_is_software (self) + && !nm_device_get_is_nm_owned (self) + && NM_DEVICE_GET_PRIVATE (self)->ifindex > 0; +} + static void device_set_master (NMDevice *self, int ifindex) { @@ -1228,10 +1236,35 @@ 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)) { + gboolean external_down = nm_device_get_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN); + + if (external_down && info->up) { + /* 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); + nm_device_queue_recheck_assume (self); + } 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_UNKNOWN); + } + } } static void @@ -6607,7 +6640,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); } /** @@ -6699,6 +6732,28 @@ nm_device_set_initial_unmanaged_flag (NMDevice *self, priv->unmanaged_flags &= ~flag; } +/** + * nm_device_update_initial_unmanaged_flags(): + * @self: the #NMDevice + * + * Called before device export to allow the device to set any additional + * unmanaged flags. + */ +void +nm_device_update_initial_unmanaged_flags (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->path == NULL); + + /* Do not manage externally created software devices until they are IFF_UP */ + if (is_software_external (self) && !nm_platform_link_is_up (priv->ifindex)) + nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); +} + void nm_device_set_dhcp_timeout (NMDevice *self, guint32 timeout) { @@ -7353,6 +7408,17 @@ notify_ip_properties (NMDevice *self) } 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, NMDeviceStateReason reason, @@ -7428,14 +7494,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 +7522,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..794693f28b 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, @@ -327,6 +329,7 @@ void nm_device_set_unmanaged_quitting (NMDevice *device); void nm_device_set_initial_unmanaged_flag (NMDevice *device, NMUnmanagedFlags flag, gboolean unmanaged); +void nm_device_update_initial_unmanaged_flags (NMDevice *device); gboolean nm_device_get_is_nm_owned (NMDevice *device); void nm_device_set_nm_owned (NMDevice *device); diff --git a/src/nm-manager.c b/src/nm-manager.c index bed07e4162..4c5fff5d76 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1820,6 +1820,8 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume) sleeping = manager_sleeping (self); nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_INTERNAL, sleeping); + nm_device_update_initial_unmanaged_flags (device); + nm_device_dbus_export (device); nm_device_finish_init (device); |