summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-12-03 12:47:30 -0600
committerThomas Haller <thaller@redhat.com>2014-12-16 21:55:13 +0100
commiteeb2374cd2c2ddf4a49c8d792033afa3fddb36e0 (patch)
tree7db2b8175018538ac9e364cb0bd8af814a8dc457
parent94091e31db803b4874b921db04f53c76bc75fb86 (diff)
downloadNetworkManager-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.c87
-rw-r--r--src/devices/nm-device.h13
-rw-r--r--src/nm-manager.c2
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);