Commit 23a5ae2f authored by Dan Williams's avatar Dan Williams
Browse files

wifi: bypass available check for hidden APs during activation (rh #1069844)

Because not all clients set the 'hidden' property in a connection for
hidden/non-SSID-broadcasting networks, they may not show up in
the device's available-connections property.  After the
PendingActivation object removal, all activations require the
connection to be in available-connections, and thus hidden SSID
networks could not be activated.

Unfortunately check_connection_available() is used both during
activation and to populate the available-connections array, but we
only want to special-case activation paths, and still ensure that
SSIDs not found in the scan list are not in available-connections.

To make it clear this is a WiFi only hack, and that we should
remove it at some point in the future, create another class method
specifically for hidden WiFi and use that in activation paths to
special-case hidden WiFi connection activation.
parent 787455ba
......@@ -1050,9 +1050,10 @@ check_connection_compatible (NMDevice *device,
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
const char *specific_object)
_internal_check_connection_available (NMDevice *device,
NMConnection *connection,
const char *specific_object,
gboolean ignore_ap_list)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
NMSettingWireless *s_wifi;
......@@ -1077,7 +1078,7 @@ check_connection_available (NMDevice *device,
return TRUE;
/* Hidden SSIDs obviously don't always appear in the scan list either */
if (nm_setting_wireless_get_hidden (s_wifi))
if (nm_setting_wireless_get_hidden (s_wifi) || ignore_ap_list)
return TRUE;
/* check if its visible */
......@@ -1089,6 +1090,24 @@ 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.
*
......@@ -3629,6 +3648,7 @@ 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;
......
......@@ -1643,7 +1643,7 @@ can_auto_connect (NMDevice *device,
if (!nm_setting_connection_get_autoconnect (s_con))
return FALSE;
return nm_device_connection_is_available (device, connection);
return nm_device_connection_is_available (device, connection, FALSE);
}
static gboolean
......@@ -7046,10 +7046,26 @@ nm_device_get_autoconnect (NMDevice *device)
return NM_DEVICE_GET_PRIVATE (device)->autoconnect;
}
/**
* nm_device_connection_is_available():
* @device: the #NMDevice
* @connection: the #NMConnection to check for availability
* @allow_device_override: set to %TRUE to let the device do specific checks
*
* Check if @connection is available to be activated on @device. Normally this
* only checks if the connection is in @device's AvailableConnections property.
* If @allow_device_override is %TRUE then the device is asked to do specific
* checks that may bypass the AvailableConnections property.
*
* Returns: %TRUE if @connection can be activated on @device
*/
gboolean
nm_device_connection_is_available (NMDevice *device, NMConnection *connection)
nm_device_connection_is_available (NMDevice *device,
NMConnection *connection,
gboolean allow_device_override)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
gboolean available = FALSE;
if (priv->default_unmanaged && (priv->state == NM_DEVICE_STATE_UNMANAGED)) {
/* default-unmanaged devices in UNMANAGED state have no available connections
......@@ -7060,7 +7076,18 @@ nm_device_connection_is_available (NMDevice *device, NMConnection *connection)
return TRUE;
}
return !!g_hash_table_lookup (priv->available_connections, connection);
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_GET_CLASS (device)->check_connection_available_wifi_hidden)
available = NM_DEVICE_GET_CLASS (device)->check_connection_available_wifi_hidden (device, connection);
}
return available;
}
static void
......
......@@ -153,6 +153,14 @@ typedef struct {
NMConnection *connection,
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,
......@@ -331,7 +339,9 @@ const char *nm_device_get_physical_port_id (NMDevice *device);
guint32 nm_device_get_mtu (NMDevice *device);
gboolean nm_device_connection_is_available (NMDevice *device, NMConnection *connection);
gboolean nm_device_connection_is_available (NMDevice *device,
NMConnection *connection,
gboolean allow_device_override);
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
......
......@@ -2501,7 +2501,7 @@ ensure_master_active_connection (NMManager *self,
if (!is_compatible_with_slave (candidate, connection))
continue;
if (nm_device_connection_is_available (master_device, candidate)) {
if (nm_device_connection_is_available (master_device, candidate, TRUE)) {
master_ac = nm_manager_activate_connection (self,
candidate,
NULL,
......@@ -2542,7 +2542,7 @@ ensure_master_active_connection (NMManager *self,
continue;
}
if (!nm_device_connection_is_available (candidate, master_connection))
if (!nm_device_connection_is_available (candidate, master_connection, TRUE))
continue;
found_device = TRUE;
......@@ -2658,7 +2658,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
}
/* Final connection must be available on device */
if (!nm_device_connection_is_available (device, connection)) {
if (!nm_device_connection_is_available (device, connection, TRUE)) {
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));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment