|
@@ -250,6 +250,7 @@ struct wpa_driver_nl80211_data {
|
|
|
unsigned int scan_for_auth:1;
|
|
|
unsigned int retry_auth:1;
|
|
|
unsigned int use_monitor:1;
|
|
|
+ unsigned int ignore_next_local_disconnect:1;
|
|
|
|
|
|
u64 remain_on_chan_cookie;
|
|
|
u64 send_action_cookie;
|
|
@@ -1191,6 +1192,7 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
|
|
|
struct nlattr *by_ap)
|
|
|
{
|
|
|
union wpa_event_data data;
|
|
|
+ unsigned int locally_generated = by_ap == NULL;
|
|
|
|
|
|
if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
|
|
|
/*
|
|
@@ -1202,6 +1204,18 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ if (drv->ignore_next_local_disconnect) {
|
|
|
+ drv->ignore_next_local_disconnect = 0;
|
|
|
+ if (locally_generated) {
|
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
|
|
|
+ "event triggered during reassociation");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ wpa_printf(MSG_WARNING, "nl80211: Was expecting local "
|
|
|
+ "disconnect but got another disconnect "
|
|
|
+ "event first");
|
|
|
+ }
|
|
|
+
|
|
|
wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
|
|
|
drv->associated = 0;
|
|
|
os_memset(&data, 0, sizeof(data));
|
|
@@ -4509,6 +4523,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
|
|
|
{
|
|
|
wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
|
|
|
drv->associated = 0;
|
|
|
+ drv->ignore_next_local_disconnect = 0;
|
|
|
/* Disconnect command doesn't need BSSID - it uses cached value */
|
|
|
return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
|
|
|
reason_code, 0);
|
|
@@ -6663,7 +6678,7 @@ nla_put_failure:
|
|
|
}
|
|
|
|
|
|
|
|
|
-static int wpa_driver_nl80211_connect(
|
|
|
+static int wpa_driver_nl80211_try_connect(
|
|
|
struct wpa_driver_nl80211_data *drv,
|
|
|
struct wpa_driver_associate_params *params)
|
|
|
{
|
|
@@ -6843,15 +6858,6 @@ skip_auth_type:
|
|
|
if (ret) {
|
|
|
wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
|
|
|
"(%s)", ret, strerror(-ret));
|
|
|
- /*
|
|
|
- * cfg80211 does not currently accept new connection if we are
|
|
|
- * already connected. As a workaround, force disconnection and
|
|
|
- * try again once the driver indicates it completed
|
|
|
- * disconnection.
|
|
|
- */
|
|
|
- if (ret == -EALREADY)
|
|
|
- wpa_driver_nl80211_disconnect(
|
|
|
- drv, WLAN_REASON_PREV_AUTH_NOT_VALID);
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
|
ret = 0;
|
|
@@ -6864,6 +6870,31 @@ nla_put_failure:
|
|
|
}
|
|
|
|
|
|
|
|
|
+static int wpa_driver_nl80211_connect(
|
|
|
+ struct wpa_driver_nl80211_data *drv,
|
|
|
+ struct wpa_driver_associate_params *params)
|
|
|
+{
|
|
|
+ int ret = wpa_driver_nl80211_try_connect(drv, params);
|
|
|
+ if (ret == -EALREADY) {
|
|
|
+ /*
|
|
|
+ * cfg80211 does not currently accept new connections if
|
|
|
+ * we are already connected. As a workaround, force
|
|
|
+ * disconnection and try again.
|
|
|
+ */
|
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
|
|
|
+ "disconnecting before reassociation "
|
|
|
+ "attempt");
|
|
|
+ if (wpa_driver_nl80211_disconnect(
|
|
|
+ drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
|
|
|
+ return -1;
|
|
|
+ /* Ignore the next local disconnect message. */
|
|
|
+ drv->ignore_next_local_disconnect = 1;
|
|
|
+ ret = wpa_driver_nl80211_try_connect(drv, params);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static int wpa_driver_nl80211_associate(
|
|
|
void *priv, struct wpa_driver_associate_params *params)
|
|
|
{
|