int ret = -1, i;
struct nl_msg *msg;
enum nl80211_auth_type type;
+ int count = 0;
drv->associated = 0;
+retry:
msg = nlmsg_alloc();
if (!msg)
return -1;
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d "
"(%s)", ret, strerror(-ret));
+ count++;
+ if (ret == -EALREADY && count == 1 && params->bssid) {
+ /*
+ * mac80211 does not currently accept new
+ * authentication if we are already authenticated. As a
+ * workaround, force deauthentication and try again.
+ */
+ wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
+ "after forced deauthentication");
+ wpa_driver_nl80211_deauthenticate(
+ drv, params->bssid,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ nlmsg_free(msg);
+ goto retry;
+ }
goto nla_put_failure;
}
ret = 0;
static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
{
const u8 *bssid;
+#ifdef CONFIG_SME
+ int authenticating;
+ u8 prev_pending_bssid[ETH_ALEN];
+
+ authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
+ os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
+#endif /* CONFIG_SME */
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
/*
}
wpa_supplicant_mark_disassoc(wpa_s);
bgscan_deinit(wpa_s);
+#ifdef CONFIG_SME
+ if (authenticating &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
+ /*
+ * mac80211-workaround to force deauth on failed auth cmd,
+ * requires us to remain in authenticating state to allow the
+ * second authentication attempt to be continued properly.
+ */
+ wpa_printf(MSG_DEBUG, "SME: Allow pending authentication to "
+ "proceed after disconnection event");
+ wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
+ os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
+ }
+#endif /* CONFIG_SME */
}