summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-10-23 14:57:22 -0500
committerDan Williams <dcbw@redhat.com>2014-10-27 13:46:06 -0500
commitd147c26517141524578850f0187a17bb064ef585 (patch)
treea5ddc0212c552927dd2193d1c647ad8c670f7e2b
parent2bf7d6b5db5093a78a3dbced9ad39a54a3fe907d (diff)
downloadNetworkManager-d147c26517141524578850f0187a17bb064ef585.tar.gz
core: autoconnect fixes for default-unmanaged devices and property notification
Previously the only thing preventing default-unmanaged devices from being auto-activated was luck and the fact that they didn't have any available connections when in the UNMANAGED state. That's no longer true, so we must be more explicit about their behavior. Furthermore it makes no sense to allow default-unmanaged devices to set priv->autoconnect=TRUE since that is never supposed to happen, so enforce that both in NM itself and if the change request comes in over the D-Bus interface. Lastly, internal priv->autoconnect=TRUE changes never emitted a property change notification, meaning the NMPolicy would never schedule an autoconnect check if the device's priv->autoconnect was set to TRUE as a result of re-activating or waking from sleep.
-rw-r--r--introspection/nm-device.xml3
-rw-r--r--src/devices/nm-device.c69
-rw-r--r--src/nm-policy.c2
3 files changed, 65 insertions, 9 deletions
diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml
index 0dca23c37d..0c2a330c00 100644
--- a/introspection/nm-device.xml
+++ b/introspection/nm-device.xml
@@ -106,7 +106,8 @@
If TRUE, indicates the device is allowed to autoconnect. If FALSE,
manual intervention is required before the device will automatically
connect to a known network, such as activating a connection using the
- device, or setting this property to TRUE.
+ device, or setting this property to TRUE. This property cannot be
+ set to TRUE for default-unmanaged devices, since they never autoconnect.
</tp:docstring>
</property>
<property name="FirmwareMissing" type="b" access="read">
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 87bebdb1eb..9f038316c7 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1573,6 +1573,15 @@ nm_device_set_enabled (NMDevice *self, gboolean enabled)
NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled);
}
+/**
+ * nm_device_get_autoconnect:
+ * @self: the #NMDevice
+ *
+ * Returns: %TRUE if the device allows autoconnect connections, or %FALSE if the
+ * device is explicitly blocking all autoconnect connections. Does not take
+ * into account transient conditions like companion devices that may wish to
+ * block the device.
+ */
gboolean
nm_device_get_autoconnect (NMDevice *self)
{
@@ -1581,6 +1590,29 @@ nm_device_get_autoconnect (NMDevice *self)
return NM_DEVICE_GET_PRIVATE (self)->autoconnect;
}
+static void
+nm_device_set_autoconnect (NMDevice *self, gboolean autoconnect)
+{
+ NMDevicePrivate *priv;
+
+ g_return_if_fail (NM_IS_DEVICE (self));
+
+ priv = NM_DEVICE_GET_PRIVATE (self);
+ if (priv->autoconnect == autoconnect)
+ return;
+
+ if (autoconnect) {
+ /* Default-unmanaged devices never autoconnect */
+ if (!nm_device_get_default_unmanaged (self)) {
+ priv->autoconnect = TRUE;
+ g_object_notify (G_OBJECT (self), NM_DEVICE_AUTOCONNECT);
+ }
+ } else {
+ priv->autoconnect = FALSE;
+ g_object_notify (G_OBJECT (self), NM_DEVICE_AUTOCONNECT);
+ }
+}
+
static gboolean
autoconnect_allowed_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
@@ -1591,6 +1623,14 @@ autoconnect_allowed_accumulator (GSignalInvocationHint *ihint,
return TRUE;
}
+/**
+ * nm_device_autoconnect_allowed:
+ * @self: the #NMDevice
+ *
+ * Returns: %TRUE if the device can be auto-connected immediately, taking
+ * transient conditions into account (like companion devices that may wish to
+ * block autoconnect for a time).
+ */
gboolean
nm_device_autoconnect_allowed (NMDevice *self)
{
@@ -1598,6 +1638,16 @@ nm_device_autoconnect_allowed (NMDevice *self)
GValue instance = G_VALUE_INIT;
GValue retval = G_VALUE_INIT;
+ if (priv->state < NM_DEVICE_STATE_DISCONNECTED || !priv->autoconnect)
+ return FALSE;
+
+ /* The 'autoconnect-allowed' signal is emitted on a device to allow
+ * other listeners to block autoconnect on the device if they wish.
+ * This is mainly used by the OLPC Mesh devices to block autoconnect
+ * on their companion WiFi device as they share radio resources and
+ * cannot be connected at the same time.
+ */
+
g_value_init (&instance, G_TYPE_OBJECT);
g_value_set_object (&instance, self);
@@ -1639,8 +1689,9 @@ can_auto_connect (NMDevice *self,
* Checks if @connection can be auto-activated on @self right now.
* This requires, at a minimum, that the connection be compatible with
* @self, and that it have the #NMSettingConnection:autoconnect property
- * set. Some devices impose additional requirements. (Eg, a Wi-Fi connection
- * can only be activated if its SSID was seen in the last scan.)
+ * set, and that the device allow auto connections. Some devices impose
+ * additional requirements. (Eg, a Wi-Fi connection can only be activated
+ * if its SSID was seen in the last scan.)
*
* Returns: %TRUE, if the @connection can be auto-activated.
**/
@@ -1653,7 +1704,9 @@ nm_device_can_auto_connect (NMDevice *self,
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
g_return_val_if_fail (specific_object && !*specific_object, FALSE);
- return NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object);
+ if (nm_device_autoconnect_allowed (self))
+ return NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object);
+ return FALSE;
}
static gboolean
@@ -5076,7 +5129,7 @@ disconnect_cb (NMDevice *self,
dbus_g_method_return_error (context, local);
g_error_free (local);
} else {
- priv->autoconnect = FALSE;
+ nm_device_set_autoconnect (self, FALSE);
nm_device_state_changed (self,
NM_DEVICE_STATE_DEACTIVATING,
@@ -6856,7 +6909,7 @@ _set_state_full (NMDevice *self,
/* Reset autoconnect flag when the device is activating or connected. */
if ( state >= NM_DEVICE_STATE_PREPARE
&& state <= NM_DEVICE_STATE_ACTIVATED)
- priv->autoconnect = TRUE;
+ nm_device_set_autoconnect (self, TRUE);
g_object_notify (G_OBJECT (self), NM_DEVICE_STATE);
g_object_notify (G_OBJECT (self), NM_DEVICE_STATE_REASON);
@@ -7412,8 +7465,10 @@ constructed (GObject *object)
* since they don't transition from UNMANAGED (and thus the state handler
* doesn't run and update them) until something external happens.
*/
- if (nm_device_get_default_unmanaged (self))
+ if (nm_device_get_default_unmanaged (self)) {
+ nm_device_set_autoconnect (self, FALSE);
nm_device_recheck_available_connections (self);
+ }
G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
}
@@ -7561,7 +7616,7 @@ set_property (GObject *object, guint prop_id,
priv->ip4_address = g_value_get_uint (value);
break;
case PROP_AUTOCONNECT:
- priv->autoconnect = g_value_get_boolean (value);
+ nm_device_set_autoconnect (self, g_value_get_boolean (value));
break;
case PROP_FIRMWARE_MISSING:
priv->firmware_missing = g_value_get_boolean (value);
diff --git a/src/nm-policy.c b/src/nm-policy.c
index ff100d069d..ddb85bd96b 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -1658,7 +1658,7 @@ device_autoconnect_changed (NMDevice *device,
GParamSpec *pspec,
gpointer user_data)
{
- if (nm_device_get_autoconnect (device))
+ if (nm_device_autoconnect_allowed (device))
schedule_activate_check ((NMPolicy *) user_data, device);
}