summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-19 12:45:42 +0100
committerJohn W. Linville <linville@tuxdriver.com>2009-11-19 11:09:02 -0500
commita58ce43f2fb17b728395ff530f019ca53c80145f (patch)
tree1de5d2680d42de12902ccb85e99bc86f63eebf58
parent7351c6bd482712e5e3ec9dffc547de0e0863efb0 (diff)
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>
-rw-r--r--include/net/cfg80211.h12
-rw-r--r--net/mac80211/mlme.c17
-rw-r--r--net/wireless/mlme.c36
3 files changed, 54 insertions, 11 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d1e05aeb0c0..a6492e9bca9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1839,6 +1839,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
* @buf: (re)association response frame (header + body)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f399547306c..6dc7b5ad9a4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -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);
@@ -2517,6 +2518,8 @@ 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;
@@ -2524,6 +2527,20 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
}
/*
+ * 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
* to cfg80211 while that's in a locked section already
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 622af5649b9..1001db4912f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -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] &&
@@ -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);
}