summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-02-24 11:50:38 +0100
committerThomas Haller <thaller@redhat.com>2015-02-24 11:51:01 +0100
commit1f5b9ffc3d89e1e87f256e0913b536577e1369a9 (patch)
tree4d9ec1f07284ae6f88dabbacab0360d15ee14df2
parent45155655f1c2d08ced88e8d8b9b97f1d36a55f2f (diff)
parent0bfe635119facb8514e8f5824f599f4c4c3514e2 (diff)
downloadNetworkManager-1f5b9ffc3d89e1e87f256e0913b536577e1369a9.tar.gz
core: merge branch 'th/queue_act_request_no_carrier_rh1079353'
https://bugzilla.redhat.com/show_bug.cgi?id=1079353
-rw-r--r--src/devices/bluetooth/nm-device-bt.c7
-rw-r--r--src/devices/nm-device-bond.c3
-rw-r--r--src/devices/nm-device-bridge.c3
-rw-r--r--src/devices/nm-device.c232
-rw-r--r--src/devices/nm-device.h56
-rw-r--r--src/devices/team/nm-device-team.c3
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c2
-rw-r--r--src/devices/wifi/nm-device-wifi.c57
-rw-r--r--src/devices/wimax/nm-device-wimax.c31
-rw-r--r--src/devices/wwan/nm-device-modem.c18
-rw-r--r--src/nm-manager.c8
11 files changed, 263 insertions, 157 deletions
diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c
index 689f37c9b4..61371dddec 100644
--- a/src/devices/bluetooth/nm-device-bt.c
+++ b/src/devices/bluetooth/nm-device-bt.c
@@ -187,6 +187,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
@@ -929,7 +930,7 @@ bluez_device_removed (NMBluezDevice *bdev, gpointer user_data)
/*****************************************************************************/
static gboolean
-is_available (NMDevice *dev)
+is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
{
NMDeviceBt *self = NM_DEVICE_BT (dev);
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
@@ -957,7 +958,7 @@ handle_availability_change (NMDeviceBt *self,
return;
}
- available = nm_device_is_available (device);
+ available = nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
if (available == old_available)
return;
@@ -987,7 +988,7 @@ set_mm_running (NMDeviceBt *self, gboolean running)
_LOGD (LOGD_BT, "ModemManager now %s",
running ? "available" : "unavailable");
- old_available = nm_device_is_available (NM_DEVICE (self));
+ old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
priv->mm_running = running;
handle_availability_change (self, old_available, NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE);
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 07f5d0bff7..6b4581082b 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -68,7 +68,7 @@ get_generic_capabilities (NMDevice *dev)
}
static gboolean
-is_available (NMDevice *dev)
+is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
{
if (NM_DEVICE_GET_CLASS (dev)->is_up)
return NM_DEVICE_GET_CLASS (dev)->is_up (dev);
@@ -78,6 +78,7 @@ is_available (NMDevice *dev)
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
/* Connections are always available because the carrier state is determined
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index a70cfd9571..a2ed4b4176 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -66,7 +66,7 @@ get_generic_capabilities (NMDevice *dev)
}
static gboolean
-is_available (NMDevice *dev)
+is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
{
if (NM_DEVICE_GET_CLASS (dev)->is_up)
return NM_DEVICE_GET_CLASS (dev)->is_up (dev);
@@ -76,6 +76,7 @@ is_available (NMDevice *dev)
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
/* Connections are always available because the carrier state is determined
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 64140de7e9..5b3e3c4eed 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -210,6 +210,7 @@ typedef struct {
guint32 ip4_address;
NMActRequest * queued_act_request;
+ gboolean queued_act_request_is_waiting_for_carrier;
NMActRequest * act_request;
guint act_source_id;
gpointer act_source_func;
@@ -338,6 +339,8 @@ static gboolean addrconf6_start_with_link_ready (NMDevice *self);
static gboolean dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection);
static NMActStageReturn linklocal6_start (NMDevice *self);
+static void _carrier_wait_check_queued_act_request (NMDevice *self);
+
static gboolean nm_device_get_default_unmanaged (NMDevice *self);
static void _set_state_full (NMDevice *self,
@@ -1138,6 +1141,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
g_source_remove (priv->carrier_wait_id);
priv->carrier_wait_id = 0;
nm_device_remove_pending_action (self, "carrier wait", TRUE);
+ _carrier_wait_check_queued_act_request (self);
}
} else if (state <= NM_DEVICE_STATE_DISCONNECTED) {
_LOGI (LOGD_DEVICE, "link disconnected");
@@ -1734,16 +1738,24 @@ nm_device_removed (NMDevice *self)
static gboolean
-is_available (NMDevice *self)
+is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- return priv->carrier || priv->ignore_carrier;
+ if (priv->carrier || priv->ignore_carrier)
+ return TRUE;
+
+ if (NM_FLAGS_HAS (flags, NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER))
+ return TRUE;
+
+ return FALSE;
}
/**
* nm_device_is_available:
* @self: the #NMDevice
+ * @flags: additional flags to influence the check. Flags have the
+ * meaning to increase the availability of a device.
*
* Checks if @self would currently be capable of activating a
* connection. In particular, it checks that the device is ready (eg,
@@ -1759,14 +1771,14 @@ is_available (NMDevice *self)
* Returns: %TRUE or %FALSE
*/
gboolean
-nm_device_is_available (NMDevice *self)
+nm_device_is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->firmware_missing)
return FALSE;
- return NM_DEVICE_GET_CLASS (self)->is_available (self);
+ return NM_DEVICE_GET_CLASS (self)->is_available (self, flags);
}
gboolean
@@ -1890,7 +1902,7 @@ can_auto_connect (NMDevice *self,
if (!nm_setting_connection_get_autoconnect (s_con))
return FALSE;
- return nm_device_connection_is_available (self, connection, FALSE);
+ return nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL);
}
/**
@@ -5623,6 +5635,15 @@ disconnect_cb (NMDevice *self,
}
static void
+_clear_queued_act_request (NMDevicePrivate *priv)
+{
+ if (priv->queued_act_request) {
+ nm_active_connection_set_state ((NMActiveConnection *) priv->queued_act_request, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
+ g_clear_object (&priv->queued_act_request);
+ }
+}
+
+static void
impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context)
{
NMConnection *connection;
@@ -5724,26 +5745,97 @@ _device_activate (NMDevice *self, NMActRequest *req)
nm_device_activate_schedule_stage1_device_prepare (self);
}
+static void
+_carrier_wait_check_queued_act_request (NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMActRequest *queued_req;
+
+ if ( !priv->queued_act_request
+ || !priv->queued_act_request_is_waiting_for_carrier)
+ return;
+
+ priv->queued_act_request_is_waiting_for_carrier = FALSE;
+ if (!priv->carrier) {
+ _LOGD (LOGD_DEVICE, "Cancel queued activation request as we have no carrier after timeout");
+ g_clear_object (&priv->queued_act_request);
+ } else {
+ _LOGD (LOGD_DEVICE, "Activate queued activation request as we now have carrier");
+ queued_req = priv->queued_act_request;
+ priv->queued_act_request = NULL;
+ _device_activate (self, queued_req);
+ g_object_unref (queued_req);
+ }
+}
+
+static gboolean
+_carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMConnection *connection;
+
+ /* If we have carrier or if we are not waiting for it, the activation
+ * request is not blocked waiting for carrier. */
+ if (priv->carrier)
+ return FALSE;
+ if (priv->carrier_wait_id == 0)
+ return FALSE;
+
+ connection = nm_act_request_get_connection (req);
+
+ if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL, NULL)) {
+ /* We passed all @flags we have, and no @specific_object.
+ * This equals maximal availability, if a connection is not available
+ * in this case, it is not waiting for carrier.
+ *
+ * Actually, why are we even trying to activate it? Strange, but whatever
+ * the reason, don't wait for carrier.
+ */
+ return FALSE;
+ }
+
+ if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER, NULL)) {
+ /* The connection was available with flags ALL, and it is still available
+ * if we pretend not to wait for carrier. That means that the
+ * connection is available now, and does not wait for carrier.
+ *
+ * Since the flags increase the availability of a connection, when checking
+ * ALL&~WAITING_CARRIER, it means that we certainly would wait for carrier. */
+ return FALSE;
+ }
+
+ /* The activation request must wait for carrier. */
+ return TRUE;
+}
+
void
nm_device_queue_activation (NMDevice *self, NMActRequest *req)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gboolean must_queue;
- if (!priv->act_request) {
+ must_queue = _carrier_wait_check_act_request_must_queue (self, req);
+
+ if (!priv->act_request && !must_queue) {
/* Just activate immediately */
_device_activate (self, req);
return;
}
/* supercede any already-queued request */
- g_clear_object (&priv->queued_act_request);
+ _clear_queued_act_request (priv);
priv->queued_act_request = g_object_ref (req);
+ priv->queued_act_request_is_waiting_for_carrier = must_queue;
- /* Deactivate existing activation request first */
- _LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
- nm_device_state_changed (self,
- NM_DEVICE_STATE_DEACTIVATING,
- NM_DEVICE_STATE_REASON_NONE);
+ _LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect");
+
+ if (priv->act_request) {
+ /* Deactivate existing activation request first */
+ _LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
+ nm_device_state_changed (self,
+ NM_DEVICE_STATE_DEACTIVATING,
+ NM_DEVICE_STATE_REASON_NONE);
+ }
}
/*
@@ -6285,6 +6377,9 @@ carrier_wait_timeout (gpointer user_data)
NM_DEVICE_GET_PRIVATE (self)->carrier_wait_id = 0;
nm_device_remove_pending_action (self, "carrier wait", TRUE);
+
+ _carrier_wait_check_queued_act_request (self);
+
return G_SOURCE_REMOVE;
}
@@ -6349,12 +6444,11 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
* a timeout is reached.
*/
if (device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
- if (priv->carrier_wait_id) {
+ if (priv->carrier_wait_id)
g_source_remove (priv->carrier_wait_id);
- nm_device_remove_pending_action (self, "carrier wait", TRUE);
- }
+ else
+ nm_device_add_pending_action (self, "carrier wait", TRUE);
priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self);
- nm_device_add_pending_action (self, "carrier wait", TRUE);
}
/* Can only get HW address of some devices when they are up */
@@ -6880,48 +6974,45 @@ nm_device_set_dhcp_anycast_address (NMDevice *self, const char *addr)
}
/**
- * nm_device_connection_is_available():
+ * nm_device_check_connection_available():
* @self: the #NMDevice
* @connection: the #NMConnection to check for availability
- * @allow_device_override: set to %TRUE to let the device do specific checks
+ * @flags: flags to affect the decision making of whether a connection
+ * is available. Adding a flag can only make a connection more available,
+ * not less.
+ * @specific_object: a device type dependent argument to further
+ * filter the result. Passing a non %NULL specific object can only reduce
+ * the availability of a connection.
*
- * Check if @connection is available to be activated on @self. Normally this
- * only checks if the connection is in @self's AvailableConnections property.
- * If @allow_device_override is %TRUE then the device is asked to do specific
- * checks that may bypass the AvailableConnections property.
+ * Check if @connection is available to be activated on @self.
*
* Returns: %TRUE if @connection can be activated on @self
*/
gboolean
-nm_device_connection_is_available (NMDevice *self,
- NMConnection *connection,
- gboolean allow_device_override)
+nm_device_check_connection_available (NMDevice *self,
+ NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
+ const char *specific_object)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- gboolean available = FALSE;
+ NMDeviceState state;
- if (nm_device_get_default_unmanaged (self) && (priv->state == NM_DEVICE_STATE_UNMANAGED)) {
- /* default-unmanaged devices in UNMANAGED state have no available connections
- * so we must manually check whether the connection is available here.
- */
- if ( nm_device_check_connection_compatible (self, connection)
- && NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, NULL))
- return TRUE;
- }
+ state = nm_device_get_state (self);
+ if (state < NM_DEVICE_STATE_UNMANAGED)
+ return FALSE;
+ if ( state < NM_DEVICE_STATE_UNAVAILABLE
+ && nm_device_get_unmanaged_flag (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
+ return FALSE;
+ if ( state < NM_DEVICE_STATE_DISCONNECTED
+ && ( ( !NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
+ && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
+ || ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
+ && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER))))
+ return FALSE;
- available = !!g_hash_table_lookup (priv->available_connections, connection);
- if (!available && allow_device_override) {
- /* FIXME: hack for hidden WiFi becuase clients didn't consistently
- * set the 'hidden' property to indicate hidden SSID networks. If
- * activating but the network isn't available let the device recheck
- * availability.
- */
- if ( nm_device_check_connection_compatible (self, connection)
- && NM_DEVICE_GET_CLASS (self)->check_connection_available_wifi_hidden)
- available = NM_DEVICE_GET_CLASS (self)->check_connection_available_wifi_hidden (self, connection);
- }
+ if (!nm_device_check_connection_compatible (self, connection))
+ return FALSE;
- return available;
+ return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object);
}
static void
@@ -6941,17 +7032,10 @@ _clear_available_connections (NMDevice *self, gboolean do_signal)
static gboolean
_try_add_available_connection (NMDevice *self, NMConnection *connection)
{
- if ( nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED
- && !nm_device_get_default_unmanaged (self))
- return FALSE;
-
- if (nm_device_check_connection_compatible (self, connection)) {
- if (NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, NULL)) {
- g_hash_table_insert (NM_DEVICE_GET_PRIVATE (self)->available_connections,
- g_object_ref (connection),
- GUINT_TO_POINTER (1));
- return TRUE;
- }
+ if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL)) {
+ g_hash_table_add (NM_DEVICE_GET_PRIVATE (self)->available_connections,
+ g_object_ref (connection));
+ return TRUE;
}
return FALSE;
}
@@ -6965,15 +7049,28 @@ _del_available_connection (NMDevice *self, NMConnection *connection)
static gboolean
check_connection_available (NMDevice *self,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
/* Connections which require a network connection are not available when
* the device has no carrier, even with ignore-carrer=TRUE.
*/
- if (NM_DEVICE_GET_PRIVATE (self)->carrier == FALSE)
- return connection_requires_carrier (connection) ? FALSE : TRUE;
+ if ( priv->carrier
+ || !connection_requires_carrier (connection))
+ return TRUE;
- return TRUE;
+ if ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
+ && priv->carrier_wait_id != 0) {
+ /* The device has no carrier though the connection requires it.
+ *
+ * If we are still waiting for carrier, the connection is available
+ * for an explicit user-request. */
+ return TRUE;
+ }
+
+ return FALSE;
}
void
@@ -7025,8 +7122,8 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object
/* If a specific object is given, only include connections that are
* compatible with it.
*/
- if ( !specific_object
- || NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, specific_object))
+ if ( !specific_object /* << Optimization: we know that the connection is available without @specific_object. */
+ || nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, specific_object))
g_ptr_array_add (array, connection);
}
}
@@ -7635,7 +7732,7 @@ _set_state_full (NMDevice *self,
if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
_clear_available_connections (self, TRUE);
- g_clear_object (&priv->queued_act_request);
+ _clear_queued_act_request (priv);
}
/* Update the available connections list when a device first becomes available */
@@ -7731,7 +7828,7 @@ _set_state_full (NMDevice *self,
* we can't change states again from the state handler for a variety of
* reasons.
*/
- if (nm_device_is_available (self)) {
+ if (nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
_LOGD (LOGD_DEVICE, "device is available, will transition to DISCONNECTED");
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
} else {
@@ -7762,7 +7859,8 @@ _set_state_full (NMDevice *self,
}
break;
case NM_DEVICE_STATE_DISCONNECTED:
- if (priv->queued_act_request) {
+ if ( priv->queued_act_request
+ && !priv->queued_act_request_is_waiting_for_carrier) {
NMActRequest *queued_req;
queued_req = priv->queued_act_request;
@@ -8352,7 +8450,7 @@ dispose (GObject *object)
priv->carrier_wait_id = 0;
}
- g_clear_object (&priv->queued_act_request);
+ _clear_queued_act_request (priv);
platform = nm_platform_get ();
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ip_changed), self);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index d3b4139d36..edc50a608f 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -86,10 +86,37 @@ G_BEGIN_DECLS
typedef enum NMActStageReturn NMActStageReturn;
+/* These flags affect whether a connection is considered available on a device
+ * (check_connection_available()). The flags should have the meaning of relaxing
+ * a condition, so that adding a flag might make a connection available that would
+ * not be available otherwise. Adding a flag should never make a connection
+ * not available if it would be available otherwise. */
+typedef enum {
+ NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0,
+
+ _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 0),
+ _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 1),
+ NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER
+ | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP,
+
+ __NM_DEVICE_CHECK_CON_AVAILABLE_ALL,
+ NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (((__NM_DEVICE_CHECK_CON_AVAILABLE_ALL - 1) << 1) - 1),
+} NMDeviceCheckConAvailableFlags;
+
struct _NMDevice {
GObject parent;
};
+/* The flags have an relaxing meaning, that means, specifying more flags, can make
+ * a device appear more available. It can never make a device less available. */
+typedef enum {
+ NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0,
+ NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0),
+
+ __NM_DEVICE_CHECK_DEV_AVAILABLE_ALL,
+ NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (((__NM_DEVICE_CHECK_DEV_AVAILABLE_ALL - 1) << 1) - 1),
+} NMDeviceCheckDevAvailableFlags;
+
typedef struct {
GObjectClass parent;
@@ -117,7 +144,7 @@ typedef struct {
guint32 (* get_generic_capabilities) (NMDevice *self);
- gboolean (* is_available) (NMDevice *self);
+ gboolean (* is_available) (NMDevice *self, NMDeviceCheckDevAvailableFlags flags);
gboolean (* get_enabled) (NMDevice *self);
@@ -137,19 +164,18 @@ typedef struct {
* including any live network information like scan lists. The connection
* is checked against the object defined by @specific_object, if given.
* Returns TRUE if the connection is available; FALSE if not.
+ *
+ * The passed @flags affect whether a connection is considered
+ * available or not. Adding more flags, means the connection is
+ * *more* available.
+ *
+ * Specifying @specific_object can only reduce the availability of a connection.
*/
gboolean (* check_connection_available) (NMDevice *self,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object);
- /* Same as check_connection_available() but called if the connection
- * is not present in the activating-connections array during activation,
- * to give the device a chance to allow/deny the activation. This is a
- * hack only meant for hidden WiFi networks.
- */
- gboolean (* check_connection_available_wifi_hidden) (NMDevice *self,
- NMConnection *connection);
-
gboolean (* complete_connection) (NMDevice *self,
NMConnection *connection,
const char *specific_object,
@@ -268,7 +294,7 @@ NMConnection * nm_device_get_connection (NMDevice *dev);
void nm_device_removed (NMDevice *dev);
-gboolean nm_device_is_available (NMDevice *dev);
+gboolean nm_device_is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags);
gboolean nm_device_has_carrier (NMDevice *dev);
NMConnection * nm_device_generate_connection (NMDevice *self, NMDevice *master);
@@ -327,7 +353,8 @@ typedef enum {
/* Boundary value */
__NM_UNMANAGED_LAST,
- NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1,
+ NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1,
+ NM_UNMANAGED_ALL = ((NM_UNMANAGED_LAST << 1) - 1),
} NMUnmanagedFlags;
gboolean nm_device_get_managed (NMDevice *device);
@@ -371,9 +398,10 @@ gboolean nm_device_has_pending_action (NMDevice *device);
GPtrArray *nm_device_get_available_connections (NMDevice *device,
const char *specific_object);
-gboolean nm_device_connection_is_available (NMDevice *device,
- NMConnection *connection,
- gboolean allow_device_override);
+gboolean nm_device_check_connection_available (NMDevice *device,
+ NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
+ const char *specific_object);
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index 88b1d0cb01..c8f510b9b5 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -74,7 +74,7 @@ get_generic_capabilities (NMDevice *device)
}
static gboolean
-is_available (NMDevice *device)
+is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
if (NM_DEVICE_GET_CLASS (device)->is_up)
return NM_DEVICE_GET_CLASS (device)->is_up (device);
@@ -84,6 +84,7 @@ is_available (NMDevice *device)
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
/* Connections are always available because the carrier state is determined
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index 0f5aa16487..dc3dfbc659 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -235,7 +235,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
}
static gboolean
-is_available (NMDevice *device)
+is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 85e376dc43..f694549960 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -864,10 +864,10 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
static gboolean
-_internal_check_connection_available (NMDevice *device,
- NMConnection *connection,
- const char *specific_object,
- gboolean ignore_ap_list)
+check_connection_available (NMDevice *device,
+ NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
+ const char *specific_object)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
NMSettingWireless *s_wifi;
@@ -877,6 +877,9 @@ _internal_check_connection_available (NMDevice *device,
s_wifi = nm_connection_get_setting_wireless (connection);
g_return_val_if_fail (s_wifi, FALSE);
+ /* a connection that is available for a certain @specific_object, MUST
+ * also be available in general (without @specific_object). */
+
if (specific_object) {
NMAccessPoint *ap;
@@ -892,8 +895,15 @@ _internal_check_connection_available (NMDevice *device,
|| g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0)
return TRUE;
- /* Hidden SSIDs obviously don't always appear in the scan list either */
- if (nm_setting_wireless_get_hidden (s_wifi) || ignore_ap_list)
+ /* Hidden SSIDs obviously don't always appear in the scan list either.
+ *
+ * For an explict user-activation-request, a connection is considered
+ * available because for hidden Wi-Fi, clients didn't consistently
+ * set the 'hidden' property to indicate hidden SSID networks. If
+ * activating but the network isn't available let the device recheck
+ * availability.
+ */
+ if (nm_setting_wireless_get_hidden (s_wifi) || NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
return TRUE;
/* check if its visible */
@@ -905,24 +915,6 @@ _internal_check_connection_available (NMDevice *device,
return FALSE;
}
-static gboolean
-check_connection_available (NMDevice *device,
- NMConnection *connection,
- const char *specific_object)
-{
- return _internal_check_connection_available (device, connection, specific_object, FALSE);
-}
-
-/* FIXME: remove this function when we require the 'hidden' property to be
- * set before a hidden connection can be activated.
- */
-static gboolean
-check_connection_available_wifi_hidden (NMDevice *device,
- NMConnection *connection)
-{
- return _internal_check_connection_available (device, connection, NULL, TRUE);
-}
-
/*
* List of manufacturer default SSIDs that are often unchanged by users.
*
@@ -1144,28 +1136,22 @@ complete_connection (NMDevice *device,
}
static gboolean
-is_available (NMDevice *device)
+is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
guint32 state;
- if (!priv->enabled) {
- _LOGD (LOGD_WIFI, "not available because not enabled");
+ if (!priv->enabled)
return FALSE;
- }
- if (!priv->sup_iface) {
- _LOGD (LOGD_WIFI, "not available because supplicant not running");
+ if (!priv->sup_iface)
return FALSE;
- }
state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( state < NM_SUPPLICANT_INTERFACE_STATE_READY
- || state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) {
- _LOGD (LOGD_WIFI, "not available because supplicant interface not ready");
+ || state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)
return FALSE;
- }
return TRUE;
}
@@ -2170,7 +2156,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
/* If the interface can now be activated because the supplicant is now
* available, transition to DISCONNECTED.
*/
- if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
+ if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE);
@@ -3341,7 +3327,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
parent_class->is_available = is_available;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->check_connection_available = check_connection_available;
- parent_class->check_connection_available_wifi_hidden = check_connection_available_wifi_hidden;
parent_class->complete_connection = complete_connection;
parent_class->set_enabled = set_enabled;
diff --git a/src/devices/wimax/nm-device-wimax.c b/src/devices/wimax/nm-device-wimax.c
index 466cd97930..0c8f1cbbe3 100644
--- a/src/devices/wimax/nm-device-wimax.c
+++ b/src/devices/wimax/nm-device-wimax.c
@@ -239,7 +239,7 @@ update_availability (NMDeviceWimax *self, gboolean old_available)
NMDeviceState state;
gboolean new_available, changed = FALSE;
- new_available = nm_device_is_available (device);
+ new_available = nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
if (new_available == old_available)
return FALSE;
@@ -281,7 +281,7 @@ set_enabled (NMDevice *device, gboolean enabled)
if (priv->enabled == enabled)
return;
- old_available = nm_device_is_available (NM_DEVICE (device));
+ old_available = nm_device_is_available (NM_DEVICE (device), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
priv->enabled = enabled;
nm_log_dbg (LOGD_WIMAX, "(%s): radio now %s",
@@ -334,12 +334,16 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
const GSList *ns_iter = NULL;
NMWimaxNsp *nsp;
+ /* a connection that is available for a certain @specific_object, MUST
+ * also be available in general (without @specific_object). */
+
if (specific_object) {
nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object);
return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE;
@@ -484,30 +488,21 @@ can_auto_connect (NMDevice *device,
}
static gboolean
-is_available (NMDevice *device)
+is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
- const char *iface = nm_device_get_iface (device);
- if (!priv->enabled) {
- nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled", iface);
+ if (!priv->enabled)
return FALSE;
- }
- if (!priv->wimaxd_enabled) {
- nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled in wimaxd", iface);
+ if (!priv->wimaxd_enabled)
return FALSE;
- }
- if (!nm_wimax_util_sdk_is_initialized ()) {
- nm_log_dbg (LOGD_WIMAX, "(%s): not available because WiMAX SDK not initialized", iface);
+ if (!nm_wimax_util_sdk_is_initialized ())
return FALSE;
- }
- if (!priv->sdk) {
- nm_log_dbg (LOGD_WIMAX, "(%s): not available because not known to WiMAX SDK", iface);
+ if (!priv->sdk)
return FALSE;
- }
return iwmxsdk_status_get (priv->sdk) >= WIMAX_API_DEVICE_STATUS_Ready;
}
@@ -712,7 +707,7 @@ wmx_state_change_cb (struct wmxsdk *wmxsdk,
return;
state = nm_device_get_state (NM_DEVICE (self));
- old_available = nm_device_is_available (NM_DEVICE (self));
+ old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
priv->status = new_status;
if (priv->current_nsp)
@@ -1153,7 +1148,7 @@ static gboolean
sdk_action_defer_cb (gpointer user_data)
{
NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
- gboolean old_available = nm_device_is_available (NM_DEVICE (self));
+ gboolean old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
NM_DEVICE_WIMAX_GET_PRIVATE (self)->sdk_action_defer_id = 0;
update_availability (self, old_available);
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index 0a9dc1ea0d..e4250bbb76 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -300,14 +300,14 @@ modem_state_cb (NMModem *modem,
nm_device_recheck_available_connections (device);
}
- if ((dev_state >= NM_DEVICE_STATE_DISCONNECTED) && !nm_device_is_available (device)) {
+ if ((dev_state >= NM_DEVICE_STATE_DISCONNECTED) && !nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_MODEM_FAILED);
return;
}
- if ((dev_state == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
+ if ((dev_state == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_MODEM_AVAILABLE);
@@ -394,6 +394,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
+ NMDeviceCheckConAvailableFlags flags,
const char *specific_object)
{
NMDeviceModem *self = NM_DEVICE_MODEM (device);
@@ -583,24 +584,19 @@ set_enabled (NMDevice *device, gboolean enabled)
}
static gboolean
-is_available (NMDevice *device)
+is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
NMDeviceModem *self = NM_DEVICE_MODEM (device);
- NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
NMModemState modem_state;
- if (!priv->rf_enabled) {
- _LOGD (LOGD_MB, "not available because WWAN airplane mode is on");
+ if (!priv->rf_enabled)
return FALSE;
- }
g_assert (priv->modem);
modem_state = nm_modem_get_state (priv->modem);
- if (modem_state <= NM_MODEM_STATE_INITIALIZING) {
- _LOGD (LOGD_MB, "not available because modem is not ready (%s)",
- nm_modem_state_to_string (modem_state));
+ if (modem_state <= NM_MODEM_STATE_INITIALIZING)
return FALSE;
- }
return TRUE;
}
diff --git a/src/nm-manager.c b/src/nm-manager.c
index c6f87cb983..a42f89e5d3 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -2538,7 +2538,7 @@ ensure_master_active_connection (NMManager *self,
if (!is_compatible_with_slave (candidate, connection))
continue;
- if (nm_device_connection_is_available (master_device, candidate, TRUE)) {
+ if (nm_device_check_connection_available (master_device, candidate, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
master_ac = nm_manager_activate_connection (self,
candidate,
NULL,
@@ -2579,7 +2579,7 @@ ensure_master_active_connection (NMManager *self,
continue;
}
- if (!nm_device_connection_is_available (candidate, master_connection, TRUE))
+ if (!nm_device_check_connection_available (candidate, master_connection, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL))
continue;
found_device = TRUE;
@@ -2696,7 +2696,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
* in the UNAVAILABLE state here. To ensure it can be activated
* immediately, we transition it to DISCONNECTED.
*/
- if ( nm_device_is_available (device)
+ if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)
&& (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
@@ -2729,7 +2729,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
}
/* Final connection must be available on device */
- if (!nm_device_connection_is_available (device, connection, TRUE)) {
+ if (!nm_device_check_connection_available (device, connection, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
"Connection '%s' is not available on the device %s at this time.",
nm_connection_get_id (connection), nm_device_get_iface (device));