diff options
-rw-r--r-- | include/linux/nl80211.h | 10 | ||||
-rw-r--r-- | include/net/cfg80211.h | 26 | ||||
-rw-r--r-- | net/mac80211/rx.c | 22 | ||||
-rw-r--r-- | net/wireless/mlme.c | 22 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 16 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 6 |
6 files changed, 100 insertions, 2 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 1cee56b3a79a..7483a89cee8f 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -399,6 +399,13 @@ | |||
399 | * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the | 399 | * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the |
400 | * network is determined by the network interface. | 400 | * network is determined by the network interface. |
401 | * | 401 | * |
402 | * @NL80211_CMD_UNPROT_DEAUTHENTICATE: Unprotected deauthentication frame | ||
403 | * notification. This event is used to indicate that an unprotected | ||
404 | * deauthentication frame was dropped when MFP is in use. | ||
405 | * @NL80211_CMD_UNPROT_DISASSOCIATE: Unprotected disassociation frame | ||
406 | * notification. This event is used to indicate that an unprotected | ||
407 | * disassociation frame was dropped when MFP is in use. | ||
408 | * | ||
402 | * @NL80211_CMD_MAX: highest used command number | 409 | * @NL80211_CMD_MAX: highest used command number |
403 | * @__NL80211_CMD_AFTER_LAST: internal use | 410 | * @__NL80211_CMD_AFTER_LAST: internal use |
404 | */ | 411 | */ |
@@ -508,6 +515,9 @@ enum nl80211_commands { | |||
508 | NL80211_CMD_JOIN_MESH, | 515 | NL80211_CMD_JOIN_MESH, |
509 | NL80211_CMD_LEAVE_MESH, | 516 | NL80211_CMD_LEAVE_MESH, |
510 | 517 | ||
518 | NL80211_CMD_UNPROT_DEAUTHENTICATE, | ||
519 | NL80211_CMD_UNPROT_DISASSOCIATE, | ||
520 | |||
511 | /* add new commands above here */ | 521 | /* add new commands above here */ |
512 | 522 | ||
513 | /* used to define NL80211_CMD_MAX below */ | 523 | /* used to define NL80211_CMD_MAX below */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f45e15f12446..3d1c09b777e8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -2360,6 +2360,32 @@ void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, | |||
2360 | size_t len); | 2360 | size_t len); |
2361 | 2361 | ||
2362 | /** | 2362 | /** |
2363 | * cfg80211_send_unprot_deauth - notification of unprotected deauthentication | ||
2364 | * @dev: network device | ||
2365 | * @buf: deauthentication frame (header + body) | ||
2366 | * @len: length of the frame data | ||
2367 | * | ||
2368 | * This function is called whenever a received Deauthentication frame has been | ||
2369 | * dropped in station mode because of MFP being used but the Deauthentication | ||
2370 | * frame was not protected. This function may sleep. | ||
2371 | */ | ||
2372 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, | ||
2373 | size_t len); | ||
2374 | |||
2375 | /** | ||
2376 | * cfg80211_send_unprot_disassoc - notification of unprotected disassociation | ||
2377 | * @dev: network device | ||
2378 | * @buf: disassociation frame (header + body) | ||
2379 | * @len: length of the frame data | ||
2380 | * | ||
2381 | * This function is called whenever a received Disassociation frame has been | ||
2382 | * dropped in station mode because of MFP being used but the Disassociation | ||
2383 | * frame was not protected. This function may sleep. | ||
2384 | */ | ||
2385 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | ||
2386 | size_t len); | ||
2387 | |||
2388 | /** | ||
2363 | * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP) | 2389 | * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP) |
2364 | * @dev: network device | 2390 | * @dev: network device |
2365 | * @addr: The source MAC address of the frame | 2391 | * @addr: The source MAC address of the frame |
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 | } |
264 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 264 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
265 | 265 | ||
266 | void 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 | } | ||
275 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
276 | |||
277 | void 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 | } | ||
286 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
287 | |||
266 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) | 288 | static 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 | ||
5476 | void 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 | |||
5484 | void 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 | |||
5476 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 5492 | static 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, | |||
25 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | 25 | void 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); |
28 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
29 | struct net_device *netdev, | ||
30 | const u8 *buf, size_t len, gfp_t gfp); | ||
31 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
32 | struct net_device *netdev, | ||
33 | const u8 *buf, size_t len, gfp_t gfp); | ||
28 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, | 34 | void 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); |