wifi: only remove AP on link timeout if not found by supplicant

If for some reason the connection is disrupted and the AP rejects
reconnection attempts (perhaps the driver has a bug, you get
disconnected, and the AP rejects association because it thinks
you're already associated), the AP object was being removed from
the scan list by code meant to handle out-of-range or turned-off
APs.  Thus even though the AP was in-range, it wouldn't be
found and the connection retried until the next scan.

Instead, only remove the AP object from the scan list if the
supplicant hasn't been able to exchange any frames with the
AP.  This preserves the out-of-range handling, becuase the
supplicant wouldn't be able to talk to the AP and thus
'ssid_found' will be FALSE, and also ensures that an in-range
but confused AP says in the scan list and will be retried
immediately.
This commit is contained in:
Dan Williams 2013-05-11 08:04:14 -05:00
parent 406a1912ca
commit 448fd7c2aa

View file

@ -2171,7 +2171,7 @@ link_timeout_cb (gpointer user_data)
nm_log_warn (LOGD_WIFI, "(%s): link timed out.", nm_device_get_iface (dev));
NM_DEVICE_WIFI_GET_PRIVATE (dev)->link_timeout_id = 0;
priv->link_timeout_id = 0;
/* Disconnect event while activated; the supplicant hasn't been able
* to reassociate within the timeout period, so the connection must
@ -2180,18 +2180,21 @@ link_timeout_cb (gpointer user_data)
if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
return FALSE;
/* Remove whatever access point we used to be connected to from the list
* since it failed and might no longer be visible. If it's actually still
* there, we'll find it in the next scan.
/* If the access point failed, and wasn't found by the supplicant when it
* attempted to reconnect, then it's probably out of range or turned off.
* Remove it from the list and if it's actually still present, it'll be
* found in the next scan.
*/
if (priv->current_ap) {
ap = priv->current_ap;
priv->current_ap = NULL;
} else
ap = nm_device_wifi_get_activation_ap (self);
if (priv->ssid_found == FALSE) {
if (priv->current_ap) {
ap = priv->current_ap;
priv->current_ap = NULL;
} else
ap = nm_device_wifi_get_activation_ap (self);
if (ap)
remove_access_point (self, ap, TRUE);
if (ap)
remove_access_point (self, ap, TRUE);
}
nm_device_state_changed (dev,
NM_DEVICE_STATE_FAILED,