aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-12-15 17:52:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-16 15:22:30 -0500
commitcf4e594ea7e55555e81647b74a3a8e8b2826a529 (patch)
tree794013429d9613ef253111fb50f993600ab14a55 /net
parent5928b91acae97622a6f2e679eb7a9f19bed68e3e (diff)
nl80211: Add notification for dropped Deauth/Disassoc
Add a new notification to indicate that a received, unprotected Deauthentication or Disassociation frame was dropped due to management frame protection being in use. This notification is needed to allow user space (e.g., wpa_supplicant) to implement SA Query procedure to recover from association state mismatch between an AP and STA. This is needed to avoid getting stuck in non-working state when MFP (IEEE 802.11w) is used and a protected Deauthentication or Disassociation frame is dropped for any reason. After that, the station would silently discard any unprotected Deauthentication or Disassociation frame that could be indicating that the AP does not have association for the STA (when the Reason Code would be 6 or 7). IEEE Std 802.11w-2009, 11.13 describes this recovery mechanism. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/rx.c22
-rw-r--r--net/wireless/mlme.c22
-rw-r--r--net/wireless/nl80211.c16
-rw-r--r--net/wireless/nl80211.h6
4 files changed, 64 insertions, 2 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 052789ef4745..4573ce1e1d15 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1540,12 +1540,30 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
1540 if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { 1540 if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
1541 if (unlikely(!ieee80211_has_protected(fc) && 1541 if (unlikely(!ieee80211_has_protected(fc) &&
1542 ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && 1542 ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
1543 rx->key)) 1543 rx->key)) {
1544 if (ieee80211_is_deauth(fc))
1545 cfg80211_send_unprot_deauth(rx->sdata->dev,
1546 rx->skb->data,
1547 rx->skb->len);
1548 else if (ieee80211_is_disassoc(fc))
1549 cfg80211_send_unprot_disassoc(rx->sdata->dev,
1550 rx->skb->data,
1551 rx->skb->len);
1544 return -EACCES; 1552 return -EACCES;
1553 }
1545 /* BIP does not use Protected field, so need to check MMIE */ 1554 /* BIP does not use Protected field, so need to check MMIE */
1546 if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && 1555 if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
1547 ieee80211_get_mmie_keyidx(rx->skb) < 0)) 1556 ieee80211_get_mmie_keyidx(rx->skb) < 0)) {
1557 if (ieee80211_is_deauth(fc))
1558 cfg80211_send_unprot_deauth(rx->sdata->dev,
1559 rx->skb->data,
1560 rx->skb->len);
1561 else if (ieee80211_is_disassoc(fc))
1562 cfg80211_send_unprot_disassoc(rx->sdata->dev,
1563 rx->skb->data,
1564 rx->skb->len);
1548 return -EACCES; 1565 return -EACCES;
1566 }
1549 /* 1567 /*
1550 * When using MFP, Action frames are not allowed prior to 1568 * When using MFP, Action frames are not allowed prior to
1551 * having configured keys. 1569 * having configured keys.
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index d7680f2a4c5b..aa5df8865ff7 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -263,6 +263,28 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
263} 263}
264EXPORT_SYMBOL(cfg80211_send_disassoc); 264EXPORT_SYMBOL(cfg80211_send_disassoc);
265 265
266void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
267 size_t len)
268{
269 struct wireless_dev *wdev = dev->ieee80211_ptr;
270 struct wiphy *wiphy = wdev->wiphy;
271 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
272
273 nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC);
274}
275EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
276
277void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
278 size_t len)
279{
280 struct wireless_dev *wdev = dev->ieee80211_ptr;
281 struct wiphy *wiphy = wdev->wiphy;
282 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
283
284 nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC);
285}
286EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
287
266static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) 288static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
267{ 289{
268 int i; 290 int i;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 594a6ac8b9d2..aefce54d47e2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5473,6 +5473,22 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
5473 NL80211_CMD_DISASSOCIATE, gfp); 5473 NL80211_CMD_DISASSOCIATE, gfp);
5474} 5474}
5475 5475
5476void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev,
5477 struct net_device *netdev, const u8 *buf,
5478 size_t len, gfp_t gfp)
5479{
5480 nl80211_send_mlme_event(rdev, netdev, buf, len,
5481 NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp);
5482}
5483
5484void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev,
5485 struct net_device *netdev, const u8 *buf,
5486 size_t len, gfp_t gfp)
5487{
5488 nl80211_send_mlme_event(rdev, netdev, buf, len,
5489 NL80211_CMD_UNPROT_DISASSOCIATE, gfp);
5490}
5491
5476static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, 5492static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
5477 struct net_device *netdev, int cmd, 5493 struct net_device *netdev, int cmd,
5478 const u8 *addr, gfp_t gfp) 5494 const u8 *addr, gfp_t gfp)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 16c2f7190768..e3f7fa886966 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -25,6 +25,12 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
25void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, 25void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
26 struct net_device *netdev, 26 struct net_device *netdev,
27 const u8 *buf, size_t len, gfp_t gfp); 27 const u8 *buf, size_t len, gfp_t gfp);
28void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev,
29 struct net_device *netdev,
30 const u8 *buf, size_t len, gfp_t gfp);
31void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev,
32 struct net_device *netdev,
33 const u8 *buf, size_t len, gfp_t gfp);
28void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, 34void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
29 struct net_device *netdev, 35 struct net_device *netdev,
30 const u8 *addr, gfp_t gfp); 36 const u8 *addr, gfp_t gfp);