Skip to content

Commit

Permalink
cfg80211: sme: deauthenticate on assoc failure
Browse files Browse the repository at this point in the history
When the in-kernel SME gets an association failure from
the AP we don't deauthenticate, and thus get into a very
confused state which will lead to warnings later on. Fix
this by actually deauthenticating when the AP indicates
an association failure.

(Brought to you by the hacking session at Kernel Summit 2009 in Tokyo,
Japan. -- JWL)

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Oct 27, 2009
1 parent 2ef6e44 commit 7d930bc
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 2 deletions.
1 change: 1 addition & 0 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);

void cfg80211_conn_work(struct work_struct *work);
void cfg80211_sme_failed_assoc(struct wireless_dev *wdev);
bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);

/* internal helpers */
Expand Down
9 changes: 9 additions & 0 deletions net/wireless/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
u8 *ie = mgmt->u.assoc_resp.variable;
int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
struct cfg80211_internal_bss *bss = NULL;
bool need_connect_result = true;

wdev_lock(wdev);

Expand Down Expand Up @@ -94,6 +95,14 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
}

WARN_ON(!bss);
} else if (wdev->conn) {
cfg80211_sme_failed_assoc(wdev);
need_connect_result = false;
/*
* do not call connect_result() now because the
* sme will schedule work that does it later.
*/
goto out;
}

if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
Expand Down
21 changes: 19 additions & 2 deletions net/wireless/sme.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct cfg80211_conn {
CFG80211_CONN_AUTHENTICATING,
CFG80211_CONN_ASSOCIATE_NEXT,
CFG80211_CONN_ASSOCIATING,
CFG80211_CONN_DEAUTH_ASSOC_FAIL,
} state;
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
u8 *ie;
Expand Down Expand Up @@ -148,6 +149,12 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
NULL, 0,
WLAN_REASON_DEAUTH_LEAVING);
return err;
case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0,
WLAN_REASON_DEAUTH_LEAVING);
/* return an error so that we call __cfg80211_connect_result() */
return -EINVAL;
default:
return 0;
}
Expand All @@ -158,6 +165,7 @@ void cfg80211_conn_work(struct work_struct *work)
struct cfg80211_registered_device *rdev =
container_of(work, struct cfg80211_registered_device, conn_work);
struct wireless_dev *wdev;
u8 bssid[ETH_ALEN];

rtnl_lock();
cfg80211_lock_rdev(rdev);
Expand All @@ -173,10 +181,10 @@ void cfg80211_conn_work(struct work_struct *work)
wdev_unlock(wdev);
continue;
}
memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN);
if (cfg80211_conn_do_work(wdev))
__cfg80211_connect_result(
wdev->netdev,
wdev->conn->params.bssid,
wdev->netdev, bssid,
NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);
Expand Down Expand Up @@ -337,6 +345,15 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
return true;
}

void cfg80211_sme_failed_assoc(struct wireless_dev *wdev)
{
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);

wdev->conn->state = CFG80211_CONN_DEAUTH_ASSOC_FAIL;
schedule_work(&rdev->conn_work);
}

void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
Expand Down

0 comments on commit 7d930bc

Please sign in to comment.