diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 298 |
1 files changed, 257 insertions, 41 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7175ae80c36a..19ffc8ef1d1d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -102,7 +102,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
102 | return len; | 102 | return len; |
103 | } | 103 | } |
104 | 104 | ||
105 | /** | 105 | /* |
106 | * ieee80211_add_rx_radiotap_header - add radiotap header | 106 | * ieee80211_add_rx_radiotap_header - add radiotap header |
107 | * | 107 | * |
108 | * add a radiotap header containing all the fields which the hardware provided. | 108 | * add a radiotap header containing all the fields which the hardware provided. |
@@ -158,7 +158,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
158 | */ | 158 | */ |
159 | *pos = 0; | 159 | *pos = 0; |
160 | } else { | 160 | } else { |
161 | rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE); | 161 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); |
162 | *pos = rate->bitrate / 5; | 162 | *pos = rate->bitrate / 5; |
163 | } | 163 | } |
164 | pos++; | 164 | pos++; |
@@ -371,39 +371,50 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
371 | rx->skb->priority = (tid > 7) ? 0 : tid; | 371 | rx->skb->priority = (tid > 7) ? 0 : tid; |
372 | } | 372 | } |
373 | 373 | ||
374 | static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) | 374 | /** |
375 | * DOC: Packet alignment | ||
376 | * | ||
377 | * Drivers always need to pass packets that are aligned to two-byte boundaries | ||
378 | * to the stack. | ||
379 | * | ||
380 | * Additionally, should, if possible, align the payload data in a way that | ||
381 | * guarantees that the contained IP header is aligned to a four-byte | ||
382 | * boundary. In the case of regular frames, this simply means aligning the | ||
383 | * payload to a four-byte boundary (because either the IP header is directly | ||
384 | * contained, or IV/RFC1042 headers that have a length divisible by four are | ||
385 | * in front of it). | ||
386 | * | ||
387 | * With A-MSDU frames, however, the payload data address must yield two modulo | ||
388 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that | ||
389 | * push the IP header further back to a multiple of four again. Thankfully, the | ||
390 | * specs were sane enough this time around to require padding each A-MSDU | ||
391 | * subframe to a length that is a multiple of four. | ||
392 | * | ||
393 | * Padding like Atheros hardware adds which is inbetween the 802.11 header and | ||
394 | * the payload is not supported, the driver is required to move the 802.11 | ||
395 | * header to be directly in front of the payload in that case. | ||
396 | */ | ||
397 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | ||
375 | { | 398 | { |
376 | #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | ||
377 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 399 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
378 | int hdrlen; | 400 | int hdrlen; |
379 | 401 | ||
402 | #ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | ||
403 | return; | ||
404 | #endif | ||
405 | |||
406 | if (WARN_ONCE((unsigned long)rx->skb->data & 1, | ||
407 | "unaligned packet at 0x%p\n", rx->skb->data)) | ||
408 | return; | ||
409 | |||
380 | if (!ieee80211_is_data_present(hdr->frame_control)) | 410 | if (!ieee80211_is_data_present(hdr->frame_control)) |
381 | return; | 411 | return; |
382 | 412 | ||
383 | /* | ||
384 | * Drivers are required to align the payload data in a way that | ||
385 | * guarantees that the contained IP header is aligned to a four- | ||
386 | * byte boundary. In the case of regular frames, this simply means | ||
387 | * aligning the payload to a four-byte boundary (because either | ||
388 | * the IP header is directly contained, or IV/RFC1042 headers that | ||
389 | * have a length divisible by four are in front of it. | ||
390 | * | ||
391 | * With A-MSDU frames, however, the payload data address must | ||
392 | * yield two modulo four because there are 14-byte 802.3 headers | ||
393 | * within the A-MSDU frames that push the IP header further back | ||
394 | * to a multiple of four again. Thankfully, the specs were sane | ||
395 | * enough this time around to require padding each A-MSDU subframe | ||
396 | * to a length that is a multiple of four. | ||
397 | * | ||
398 | * Padding like atheros hardware adds which is inbetween the 802.11 | ||
399 | * header and the payload is not supported, the driver is required | ||
400 | * to move the 802.11 header further back in that case. | ||
401 | */ | ||
402 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 413 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
403 | if (rx->flags & IEEE80211_RX_AMSDU) | 414 | if (rx->flags & IEEE80211_RX_AMSDU) |
404 | hdrlen += ETH_HLEN; | 415 | hdrlen += ETH_HLEN; |
405 | WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); | 416 | WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, |
406 | #endif | 417 | "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); |
407 | } | 418 | } |
408 | 419 | ||
409 | 420 | ||
@@ -435,6 +446,52 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
435 | return RX_CONTINUE; | 446 | return RX_CONTINUE; |
436 | } | 447 | } |
437 | 448 | ||
449 | |||
450 | static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | ||
451 | { | ||
452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
453 | |||
454 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | ||
455 | return 0; | ||
456 | |||
457 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
458 | } | ||
459 | |||
460 | |||
461 | static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | ||
462 | { | ||
463 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
464 | |||
465 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | ||
466 | return 0; | ||
467 | |||
468 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
469 | } | ||
470 | |||
471 | |||
472 | /* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */ | ||
473 | static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | ||
474 | { | ||
475 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; | ||
476 | struct ieee80211_mmie *mmie; | ||
477 | |||
478 | if (skb->len < 24 + sizeof(*mmie) || | ||
479 | !is_multicast_ether_addr(hdr->da)) | ||
480 | return -1; | ||
481 | |||
482 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | ||
483 | return -1; /* not a robust management frame */ | ||
484 | |||
485 | mmie = (struct ieee80211_mmie *) | ||
486 | (skb->data + skb->len - sizeof(*mmie)); | ||
487 | if (mmie->element_id != WLAN_EID_MMIE || | ||
488 | mmie->length != sizeof(*mmie) - 2) | ||
489 | return -1; | ||
490 | |||
491 | return le16_to_cpu(mmie->key_id); | ||
492 | } | ||
493 | |||
494 | |||
438 | static ieee80211_rx_result | 495 | static ieee80211_rx_result |
439 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 496 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
440 | { | 497 | { |
@@ -550,21 +607,23 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
550 | int hdrlen; | 607 | int hdrlen; |
551 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 608 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
552 | struct ieee80211_key *stakey = NULL; | 609 | struct ieee80211_key *stakey = NULL; |
610 | int mmie_keyidx = -1; | ||
553 | 611 | ||
554 | /* | 612 | /* |
555 | * Key selection 101 | 613 | * Key selection 101 |
556 | * | 614 | * |
557 | * There are three types of keys: | 615 | * There are four types of keys: |
558 | * - GTK (group keys) | 616 | * - GTK (group keys) |
617 | * - IGTK (group keys for management frames) | ||
559 | * - PTK (pairwise keys) | 618 | * - PTK (pairwise keys) |
560 | * - STK (station-to-station pairwise keys) | 619 | * - STK (station-to-station pairwise keys) |
561 | * | 620 | * |
562 | * When selecting a key, we have to distinguish between multicast | 621 | * When selecting a key, we have to distinguish between multicast |
563 | * (including broadcast) and unicast frames, the latter can only | 622 | * (including broadcast) and unicast frames, the latter can only |
564 | * use PTKs and STKs while the former always use GTKs. Unless, of | 623 | * use PTKs and STKs while the former always use GTKs and IGTKs. |
565 | * course, actual WEP keys ("pre-RSNA") are used, then unicast | 624 | * Unless, of course, actual WEP keys ("pre-RSNA") are used, then |
566 | * frames can also use key indizes like GTKs. Hence, if we don't | 625 | * unicast frames can also use key indices like GTKs. Hence, if we |
567 | * have a PTK/STK we check the key index for a WEP key. | 626 | * don't have a PTK/STK we check the key index for a WEP key. |
568 | * | 627 | * |
569 | * Note that in a regular BSS, multicast frames are sent by the | 628 | * Note that in a regular BSS, multicast frames are sent by the |
570 | * AP only, associated stations unicast the frame to the AP first | 629 | * AP only, associated stations unicast the frame to the AP first |
@@ -577,8 +636,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
577 | * possible. | 636 | * possible. |
578 | */ | 637 | */ |
579 | 638 | ||
580 | if (!ieee80211_has_protected(hdr->frame_control)) | 639 | if (!ieee80211_has_protected(hdr->frame_control)) { |
581 | return RX_CONTINUE; | 640 | if (!ieee80211_is_mgmt(hdr->frame_control) || |
641 | rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) | ||
642 | return RX_CONTINUE; | ||
643 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
644 | if (mmie_keyidx < 0) | ||
645 | return RX_CONTINUE; | ||
646 | } | ||
582 | 647 | ||
583 | /* | 648 | /* |
584 | * No point in finding a key and decrypting if the frame is neither | 649 | * No point in finding a key and decrypting if the frame is neither |
@@ -592,6 +657,16 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
592 | 657 | ||
593 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 658 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
594 | rx->key = stakey; | 659 | rx->key = stakey; |
660 | } else if (mmie_keyidx >= 0) { | ||
661 | /* Broadcast/multicast robust management frame / BIP */ | ||
662 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | ||
663 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | ||
664 | return RX_CONTINUE; | ||
665 | |||
666 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | ||
667 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
668 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||
669 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
595 | } else { | 670 | } else { |
596 | /* | 671 | /* |
597 | * The device doesn't give us the IV so we won't be | 672 | * The device doesn't give us the IV so we won't be |
@@ -654,6 +729,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
654 | case ALG_CCMP: | 729 | case ALG_CCMP: |
655 | result = ieee80211_crypto_ccmp_decrypt(rx); | 730 | result = ieee80211_crypto_ccmp_decrypt(rx); |
656 | break; | 731 | break; |
732 | case ALG_AES_CMAC: | ||
733 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | ||
734 | break; | ||
657 | } | 735 | } |
658 | 736 | ||
659 | /* either the frame has been decrypted or will be dropped */ | 737 | /* either the frame has been decrypted or will be dropped */ |
@@ -1101,6 +1179,15 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1101 | /* Drop unencrypted frames if key is set. */ | 1179 | /* Drop unencrypted frames if key is set. */ |
1102 | if (unlikely(!ieee80211_has_protected(fc) && | 1180 | if (unlikely(!ieee80211_has_protected(fc) && |
1103 | !ieee80211_is_nullfunc(fc) && | 1181 | !ieee80211_is_nullfunc(fc) && |
1182 | (!ieee80211_is_mgmt(fc) || | ||
1183 | (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1184 | rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && | ||
1185 | (rx->key || rx->sdata->drop_unencrypted))) | ||
1186 | return -EACCES; | ||
1187 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1188 | if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && | ||
1189 | ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | ||
1190 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1104 | (rx->key || rx->sdata->drop_unencrypted))) | 1191 | (rx->key || rx->sdata->drop_unencrypted))) |
1105 | return -EACCES; | 1192 | return -EACCES; |
1106 | 1193 | ||
@@ -1267,10 +1354,37 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1267 | } | 1354 | } |
1268 | 1355 | ||
1269 | if (skb) { | 1356 | if (skb) { |
1270 | /* deliver to local stack */ | 1357 | int align __maybe_unused; |
1271 | skb->protocol = eth_type_trans(skb, dev); | 1358 | |
1272 | memset(skb->cb, 0, sizeof(skb->cb)); | 1359 | #if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
1273 | netif_rx(skb); | 1360 | /* |
1361 | * 'align' will only take the values 0 or 2 here | ||
1362 | * since all frames are required to be aligned | ||
1363 | * to 2-byte boundaries when being passed to | ||
1364 | * mac80211. That also explains the __skb_push() | ||
1365 | * below. | ||
1366 | */ | ||
1367 | align = (unsigned long)skb->data & 4; | ||
1368 | if (align) { | ||
1369 | if (WARN_ON(skb_headroom(skb) < 3)) { | ||
1370 | dev_kfree_skb(skb); | ||
1371 | skb = NULL; | ||
1372 | } else { | ||
1373 | u8 *data = skb->data; | ||
1374 | size_t len = skb->len; | ||
1375 | u8 *new = __skb_push(skb, align); | ||
1376 | memmove(new, data, len); | ||
1377 | __skb_trim(skb, len); | ||
1378 | } | ||
1379 | } | ||
1380 | #endif | ||
1381 | |||
1382 | if (skb) { | ||
1383 | /* deliver to local stack */ | ||
1384 | skb->protocol = eth_type_trans(skb, dev); | ||
1385 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
1386 | netif_rx(skb); | ||
1387 | } | ||
1274 | } | 1388 | } |
1275 | 1389 | ||
1276 | if (xmit_skb) { | 1390 | if (xmit_skb) { |
@@ -1339,14 +1453,20 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1339 | if (remaining <= subframe_len + padding) | 1453 | if (remaining <= subframe_len + padding) |
1340 | frame = skb; | 1454 | frame = skb; |
1341 | else { | 1455 | else { |
1342 | frame = dev_alloc_skb(local->hw.extra_tx_headroom + | 1456 | /* |
1343 | subframe_len); | 1457 | * Allocate and reserve two bytes more for payload |
1458 | * alignment since sizeof(struct ethhdr) is 14. | ||
1459 | */ | ||
1460 | frame = dev_alloc_skb( | ||
1461 | ALIGN(local->hw.extra_tx_headroom, 4) + | ||
1462 | subframe_len + 2); | ||
1344 | 1463 | ||
1345 | if (frame == NULL) | 1464 | if (frame == NULL) |
1346 | return RX_DROP_UNUSABLE; | 1465 | return RX_DROP_UNUSABLE; |
1347 | 1466 | ||
1348 | skb_reserve(frame, local->hw.extra_tx_headroom + | 1467 | skb_reserve(frame, |
1349 | sizeof(struct ethhdr)); | 1468 | ALIGN(local->hw.extra_tx_headroom, 4) + |
1469 | sizeof(struct ethhdr) + 2); | ||
1350 | memcpy(skb_put(frame, ntohs(len)), skb->data, | 1470 | memcpy(skb_put(frame, ntohs(len)), skb->data, |
1351 | ntohs(len)); | 1471 | ntohs(len)); |
1352 | 1472 | ||
@@ -1547,12 +1667,65 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1547 | return RX_CONTINUE; | 1667 | return RX_CONTINUE; |
1548 | } | 1668 | } |
1549 | 1669 | ||
1670 | static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | ||
1671 | struct ieee80211_mgmt *mgmt, | ||
1672 | size_t len) | ||
1673 | { | ||
1674 | struct ieee80211_local *local = sdata->local; | ||
1675 | struct sk_buff *skb; | ||
1676 | struct ieee80211_mgmt *resp; | ||
1677 | |||
1678 | if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) { | ||
1679 | /* Not to own unicast address */ | ||
1680 | return; | ||
1681 | } | ||
1682 | |||
1683 | if (compare_ether_addr(mgmt->sa, sdata->u.sta.bssid) != 0 || | ||
1684 | compare_ether_addr(mgmt->bssid, sdata->u.sta.bssid) != 0) { | ||
1685 | /* Not from the current AP. */ | ||
1686 | return; | ||
1687 | } | ||
1688 | |||
1689 | if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATE) { | ||
1690 | /* Association in progress; ignore SA Query */ | ||
1691 | return; | ||
1692 | } | ||
1693 | |||
1694 | if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) { | ||
1695 | /* Too short SA Query request frame */ | ||
1696 | return; | ||
1697 | } | ||
1698 | |||
1699 | skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom); | ||
1700 | if (skb == NULL) | ||
1701 | return; | ||
1702 | |||
1703 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1704 | resp = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
1705 | memset(resp, 0, 24); | ||
1706 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | ||
1707 | memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
1708 | memcpy(resp->bssid, sdata->u.sta.bssid, ETH_ALEN); | ||
1709 | resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
1710 | IEEE80211_STYPE_ACTION); | ||
1711 | skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query)); | ||
1712 | resp->u.action.category = WLAN_CATEGORY_SA_QUERY; | ||
1713 | resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE; | ||
1714 | memcpy(resp->u.action.u.sa_query.trans_id, | ||
1715 | mgmt->u.action.u.sa_query.trans_id, | ||
1716 | WLAN_SA_QUERY_TR_ID_LEN); | ||
1717 | |||
1718 | ieee80211_tx_skb(sdata, skb, 1); | ||
1719 | } | ||
1720 | |||
1550 | static ieee80211_rx_result debug_noinline | 1721 | static ieee80211_rx_result debug_noinline |
1551 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1722 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1552 | { | 1723 | { |
1553 | struct ieee80211_local *local = rx->local; | 1724 | struct ieee80211_local *local = rx->local; |
1554 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1725 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1726 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1555 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1727 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1728 | struct ieee80211_bss *bss; | ||
1556 | int len = rx->skb->len; | 1729 | int len = rx->skb->len; |
1557 | 1730 | ||
1558 | if (!ieee80211_is_action(mgmt->frame_control)) | 1731 | if (!ieee80211_is_action(mgmt->frame_control)) |
@@ -1564,6 +1737,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1564 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1737 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1565 | return RX_DROP_MONITOR; | 1738 | return RX_DROP_MONITOR; |
1566 | 1739 | ||
1740 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | ||
1741 | return RX_DROP_MONITOR; | ||
1742 | |||
1567 | /* all categories we currently handle have action_code */ | 1743 | /* all categories we currently handle have action_code */ |
1568 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1744 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
1569 | return RX_DROP_MONITOR; | 1745 | return RX_DROP_MONITOR; |
@@ -1601,6 +1777,42 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1601 | return RX_DROP_MONITOR; | 1777 | return RX_DROP_MONITOR; |
1602 | ieee80211_process_measurement_req(sdata, mgmt, len); | 1778 | ieee80211_process_measurement_req(sdata, mgmt, len); |
1603 | break; | 1779 | break; |
1780 | case WLAN_ACTION_SPCT_CHL_SWITCH: | ||
1781 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1782 | sizeof(mgmt->u.action.u.chan_switch))) | ||
1783 | return RX_DROP_MONITOR; | ||
1784 | |||
1785 | if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0) | ||
1786 | return RX_DROP_MONITOR; | ||
1787 | |||
1788 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, | ||
1789 | local->hw.conf.channel->center_freq, | ||
1790 | ifsta->ssid, ifsta->ssid_len); | ||
1791 | if (!bss) | ||
1792 | return RX_DROP_MONITOR; | ||
1793 | |||
1794 | ieee80211_process_chanswitch(sdata, | ||
1795 | &mgmt->u.action.u.chan_switch.sw_elem, bss); | ||
1796 | ieee80211_rx_bss_put(local, bss); | ||
1797 | break; | ||
1798 | } | ||
1799 | break; | ||
1800 | case WLAN_CATEGORY_SA_QUERY: | ||
1801 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1802 | sizeof(mgmt->u.action.u.sa_query))) | ||
1803 | return RX_DROP_MONITOR; | ||
1804 | switch (mgmt->u.action.u.sa_query.action) { | ||
1805 | case WLAN_ACTION_SA_QUERY_REQUEST: | ||
1806 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1807 | return RX_DROP_MONITOR; | ||
1808 | ieee80211_process_sa_query_req(sdata, mgmt, len); | ||
1809 | break; | ||
1810 | case WLAN_ACTION_SA_QUERY_RESPONSE: | ||
1811 | /* | ||
1812 | * SA Query response is currently only used in AP mode | ||
1813 | * and it is processed in user space. | ||
1814 | */ | ||
1815 | return RX_CONTINUE; | ||
1604 | } | 1816 | } |
1605 | break; | 1817 | break; |
1606 | default: | 1818 | default: |
@@ -1616,10 +1828,14 @@ static ieee80211_rx_result debug_noinline | |||
1616 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1828 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1617 | { | 1829 | { |
1618 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1830 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1831 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1619 | 1832 | ||
1620 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1833 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1621 | return RX_DROP_MONITOR; | 1834 | return RX_DROP_MONITOR; |
1622 | 1835 | ||
1836 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | ||
1837 | return RX_DROP_MONITOR; | ||
1838 | |||
1623 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1839 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1624 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); | 1840 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); |
1625 | 1841 | ||
@@ -1956,7 +2172,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1956 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2172 | rx.flags |= IEEE80211_RX_IN_SCAN; |
1957 | 2173 | ||
1958 | ieee80211_parse_qos(&rx); | 2174 | ieee80211_parse_qos(&rx); |
1959 | ieee80211_verify_ip_alignment(&rx); | 2175 | ieee80211_verify_alignment(&rx); |
1960 | 2176 | ||
1961 | skb = rx.skb; | 2177 | skb = rx.skb; |
1962 | 2178 | ||