Skip to content

Commit a58ce43

Browse files
jmberglinvjw
authored andcommitted
mac80211: avoid spurious deauth frames/messages
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>
1 parent 7351c6b commit a58ce43

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

include/net/cfg80211.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,18 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
18381838
*/
18391839
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
18401840

1841+
/**
1842+
* __cfg80211_auth_canceled - notify cfg80211 that authentication was canceled
1843+
* @dev: network device
1844+
* @addr: The MAC address of the device with which the authentication timed out
1845+
*
1846+
* When a pending authentication had no action yet, the driver may decide
1847+
* to not send a deauth frame, but in that case must calls this function
1848+
* to tell cfg80211 about this decision. It is only valid to call this
1849+
* function within the deauth() callback.
1850+
*/
1851+
void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr);
1852+
18411853
/**
18421854
* cfg80211_send_rx_assoc - notification of processed association
18431855
* @dev: network device

net/mac80211/mlme.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
25082508
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
25092509
struct ieee80211_mgd_work *wk;
25102510
const u8 *bssid = NULL;
2511+
bool not_auth_yet = false;
25112512

25122513
mutex_lock(&ifmgd->mtx);
25132514

@@ -2517,12 +2518,28 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
25172518
} else list_for_each_entry(wk, &ifmgd->work_list, list) {
25182519
if (&wk->bss->cbss == req->bss) {
25192520
bssid = req->bss->bssid;
2521+
if (wk->state == IEEE80211_MGD_STATE_PROBE)
2522+
not_auth_yet = true;
25202523
list_del(&wk->list);
25212524
kfree(wk);
25222525
break;
25232526
}
25242527
}
25252528

2529+
/*
2530+
* If somebody requests authentication and we haven't
2531+
* sent out an auth frame yet there's no need to send
2532+
* out a deauth frame either. If the state was PROBE,
2533+
* then this is the case. If it's AUTH we have sent a
2534+
* frame, and if it's IDLE we have completed the auth
2535+
* process already.
2536+
*/
2537+
if (not_auth_yet) {
2538+
mutex_unlock(&ifmgd->mtx);
2539+
__cfg80211_auth_canceled(sdata->dev, bssid);
2540+
return 0;
2541+
}
2542+
25262543
/*
25272544
* cfg80211 should catch this ... but it's racy since
25282545
* we can receive a deauth frame, process it, hand it

net/wireless/mlme.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
243243
}
244244
EXPORT_SYMBOL(cfg80211_send_disassoc);
245245

246-
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
246+
static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
247247
{
248-
struct wireless_dev *wdev = dev->ieee80211_ptr;
249-
struct wiphy *wiphy = wdev->wiphy;
250-
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
251248
int i;
252249
bool done = false;
253250

254-
wdev_lock(wdev);
255-
256-
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
257-
if (wdev->sme_state == CFG80211_SME_CONNECTING)
258-
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
259-
WLAN_STATUS_UNSPECIFIED_FAILURE,
260-
false, NULL);
251+
ASSERT_WDEV_LOCK(wdev);
261252

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

274265
WARN_ON(!done);
266+
}
267+
268+
void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
269+
{
270+
__cfg80211_auth_remove(dev->ieee80211_ptr, addr);
271+
}
272+
EXPORT_SYMBOL(__cfg80211_auth_canceled);
273+
274+
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
275+
{
276+
struct wireless_dev *wdev = dev->ieee80211_ptr;
277+
struct wiphy *wiphy = wdev->wiphy;
278+
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
279+
280+
wdev_lock(wdev);
281+
282+
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
283+
if (wdev->sme_state == CFG80211_SME_CONNECTING)
284+
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
285+
WLAN_STATUS_UNSPECIFIED_FAILURE,
286+
false, NULL);
287+
288+
__cfg80211_auth_remove(wdev, addr);
275289

276290
wdev_unlock(wdev);
277291
}

0 commit comments

Comments
 (0)