nl80211: Work around mac80211 limitation on (re)auth when authenticated
mac80211 does not currently allow (re)authentication when we are already authenticated. In order to work around this, force deauthentication if nl80211 authentication command fails with EALREADY. Unfortunately, the workaround code in driver_nl80211.c alone is not enough since the following disconnection event would clear wpa_supplicant authentication state. To handle this, add some code to restore authentication state when using userspace SME. This workaround will hopefully become unnecessary in some point should mac80211 start accepting new authentication requests even when in authenticated state.
This commit is contained in:
parent
786c4fee9d
commit
6d6f4bb87f
2 changed files with 38 additions and 0 deletions
|
@ -2063,9 +2063,11 @@ static int wpa_driver_nl80211_authenticate(
|
||||||
int ret = -1, i;
|
int ret = -1, i;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
enum nl80211_auth_type type;
|
enum nl80211_auth_type type;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
drv->associated = 0;
|
drv->associated = 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2133,6 +2135,21 @@ static int wpa_driver_nl80211_authenticate(
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d "
|
wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d "
|
||||||
"(%s)", ret, strerror(-ret));
|
"(%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;
|
goto nla_put_failure;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
|
@ -1065,6 +1065,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
|
||||||
static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
|
static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
const u8 *bssid;
|
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) {
|
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
|
||||||
/*
|
/*
|
||||||
|
@ -1097,6 +1104,20 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
|
||||||
}
|
}
|
||||||
wpa_supplicant_mark_disassoc(wpa_s);
|
wpa_supplicant_mark_disassoc(wpa_s);
|
||||||
bgscan_deinit(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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue