diff options
author | Dan Williams <dcbw@redhat.com> | 2014-12-03 12:47:30 -0600 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2014-12-16 16:11:02 -0600 |
commit | fa41627152df08216dc21a85a9412c83b0a5dcb8 (patch) | |
tree | 876fbd9f206428dd907de8e373222fd96b169684 | |
parent | dc4d39a2d4582eb5092651f5a86f6e77488dafa0 (diff) | |
download | NetworkManager-fa41627152df08216dc21a85a9412c83b0a5dcb8.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
-rw-r--r-- | src/devices/nm-device.c | 76 | ||||
-rw-r--r-- | 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); } /** @@ -7353,6 +7397,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 +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, |