diff options
author | Thomas Haller <thaller@redhat.com> | 2015-02-24 11:50:38 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-02-24 17:49:44 +0100 |
commit | 2edd2730969b6463912a1b894872f08c19b70137 (patch) | |
tree | bb110306ac15dc355701863f2927363226b085e4 | |
parent | da32e0a841a99f9f461cc38ebf4af313c1b713e8 (diff) | |
parent | b8f40f969b20524f3fefa3ca5284d70c868329d6 (diff) | |
download | NetworkManager-2edd2730969b6463912a1b894872f08c19b70137.tar.gz |
core: merge branch 'th/queue_act_request_no_carrier_rh1079353'
https://bugzilla.redhat.com/show_bug.cgi?id=1079353
(cherry picked from commit 1f5b9ffc3d89e1e87f256e0913b536577e1369a9)
-rw-r--r-- | src/devices/bluetooth/nm-device-bt.c | 7 | ||||
-rw-r--r-- | src/devices/nm-device-bond.c | 3 | ||||
-rw-r--r-- | src/devices/nm-device-bridge.c | 3 | ||||
-rw-r--r-- | src/devices/nm-device.c | 232 | ||||
-rw-r--r-- | src/devices/nm-device.h | 56 | ||||
-rw-r--r-- | src/devices/team/nm-device-team.c | 3 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-olpc-mesh.c | 2 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 57 | ||||
-rw-r--r-- | src/devices/wimax/nm-device-wimax.c | 31 | ||||
-rw-r--r-- | src/devices/wwan/nm-device-modem.c | 18 | ||||
-rw-r--r-- | src/nm-manager.c | 8 |
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 9d9fe426b2..0b2c97d148 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -67,7 +67,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); @@ -77,6 +77,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 dd8fd8f380..2704531c1f 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -209,6 +209,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; @@ -337,6 +338,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, @@ -1137,6 +1140,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"); @@ -1726,16 +1730,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, @@ -1751,14 +1763,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 @@ -1882,7 +1894,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); } /** @@ -5579,6 +5591,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; @@ -5680,26 +5701,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); + } } /* @@ -6241,6 +6333,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; } @@ -6305,12 +6400,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 */ @@ -6798,48 +6892,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 @@ -6859,17 +6950,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; } @@ -6883,15 +6967,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 @@ -6943,8 +7040,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); } } @@ -7489,7 +7586,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 */ @@ -7585,7 +7682,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 { @@ -7616,7 +7713,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; @@ -8201,7 +8299,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 b3855c7446..ccdade9b13 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -85,10 +85,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; @@ -116,7 +143,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); @@ -136,19 +163,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, @@ -257,7 +283,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); @@ -316,7 +342,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); @@ -360,9 +387,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 ab58c9daec..2d0e6e0af3 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -75,7 +75,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); @@ -85,6 +85,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 dd7754b33e..9633175f48 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -863,10 +863,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; @@ -876,6 +876,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; @@ -891,8 +894,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 */ @@ -904,24 +914,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. * @@ -1143,28 +1135,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; } @@ -2169,7 +2155,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); @@ -3335,7 +3321,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 0ca1056edf..8fbbb9a455 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); @@ -539,24 +540,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 7f4e0b02b4..bf99ffc57a 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2526,7 +2526,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, @@ -2567,7 +2567,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; @@ -2684,7 +2684,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, @@ -2718,7 +2718,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)); |