Skip to content

Commit

Permalink
mac80211: avoid spurious deauth frames/messages
Browse files Browse the repository at this point in the history
With WEXT, it happens frequently that the SME
requests an authentication but then deauthenticates
right away because some new parameters came along.
Every time this happens we print a deauth message
and send a deauth frame, but both of that is rather
confusing. Avoid it by aborting the authentication
process silently, and telling cfg80211 about that.

The patch looks larger than it really is:
__cfg80211_auth_remove() is split out from
cfg80211_send_auth_timeout(), there's no new code
except __cfg80211_auth_canceled() (a one-liner) and
the mac80211 bits (7 new lines of code).

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 Nov 19, 2009
1 parent 7351c6b commit a58ce43
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 11 deletions.
12 changes: 12 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,18 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
*/
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);

/**
* __cfg80211_auth_canceled - notify cfg80211 that authentication was canceled
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
*
* When a pending authentication had no action yet, the driver may decide
* to not send a deauth frame, but in that case must calls this function
* to tell cfg80211 about this decision. It is only valid to call this
* function within the deauth() callback.
*/
void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr);

/**
* cfg80211_send_rx_assoc - notification of processed association
* @dev: network device
Expand Down
17 changes: 17 additions & 0 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_work *wk;
const u8 *bssid = NULL;
bool not_auth_yet = false;

mutex_lock(&ifmgd->mtx);

Expand All @@ -2517,12 +2518,28 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
} else list_for_each_entry(wk, &ifmgd->work_list, list) {
if (&wk->bss->cbss == req->bss) {
bssid = req->bss->bssid;
if (wk->state == IEEE80211_MGD_STATE_PROBE)
not_auth_yet = true;
list_del(&wk->list);
kfree(wk);
break;
}
}

/*
* If somebody requests authentication and we haven't
* sent out an auth frame yet there's no need to send
* out a deauth frame either. If the state was PROBE,
* then this is the case. If it's AUTH we have sent a
* frame, and if it's IDLE we have completed the auth
* process already.
*/
if (not_auth_yet) {
mutex_unlock(&ifmgd->mtx);
__cfg80211_auth_canceled(sdata->dev, bssid);
return 0;
}

/*
* cfg80211 should catch this ... but it's racy since
* we can receive a deauth frame, process it, hand it
Expand Down
36 changes: 25 additions & 11 deletions net/wireless/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,21 +243,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
}
EXPORT_SYMBOL(cfg80211_send_disassoc);

void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
int i;
bool done = false;

wdev_lock(wdev);

nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);
ASSERT_WDEV_LOCK(wdev);

for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
if (wdev->authtry_bsses[i] &&
Expand All @@ -272,6 +263,29 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
}

WARN_ON(!done);
}

void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
{
__cfg80211_auth_remove(dev->ieee80211_ptr, addr);
}
EXPORT_SYMBOL(__cfg80211_auth_canceled);

void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);

wdev_lock(wdev);

nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);

__cfg80211_auth_remove(wdev, addr);

wdev_unlock(wdev);
}
Expand Down

0 comments on commit a58ce43

Please sign in to comment.