diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 683b10f46505..1101563357ea 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -272,7 +272,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; |
274 | else if (rate) | 274 | else if (rate) |
275 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 275 | channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; |
276 | else | 276 | else |
277 | channel_flags |= IEEE80211_CHAN_2GHZ; | 277 | channel_flags |= IEEE80211_CHAN_2GHZ; |
278 | put_unaligned_le16(channel_flags, pos); | 278 | put_unaligned_le16(channel_flags, pos); |
@@ -361,9 +361,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
361 | u16 known = local->hw.radiotap_vht_details; | 361 | u16 known = local->hw.radiotap_vht_details; |
362 | 362 | ||
363 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); | 363 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); |
364 | /* known field - how to handle 80+80? */ | ||
365 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) | ||
366 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | ||
367 | put_unaligned_le16(known, pos); | 364 | put_unaligned_le16(known, pos); |
368 | pos += 2; | 365 | pos += 2; |
369 | /* flags */ | 366 | /* flags */ |
@@ -378,8 +375,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
378 | /* bandwidth */ | 375 | /* bandwidth */ |
379 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) | 376 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
380 | *pos++ = 4; | 377 | *pos++ = 4; |
381 | else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) | ||
382 | *pos++ = 0; /* marked not known above */ | ||
383 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) | 378 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
384 | *pos++ = 11; | 379 | *pos++ = 11; |
385 | else if (status->flag & RX_FLAG_40MHZ) | 380 | else if (status->flag & RX_FLAG_40MHZ) |
@@ -652,6 +647,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
652 | { | 647 | { |
653 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; | 648 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; |
654 | struct ieee80211_mmie *mmie; | 649 | struct ieee80211_mmie *mmie; |
650 | struct ieee80211_mmie_16 *mmie16; | ||
655 | 651 | ||
656 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) | 652 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) |
657 | return -1; | 653 | return -1; |
@@ -661,11 +657,18 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
661 | 657 | ||
662 | mmie = (struct ieee80211_mmie *) | 658 | mmie = (struct ieee80211_mmie *) |
663 | (skb->data + skb->len - sizeof(*mmie)); | 659 | (skb->data + skb->len - sizeof(*mmie)); |
664 | if (mmie->element_id != WLAN_EID_MMIE || | 660 | if (mmie->element_id == WLAN_EID_MMIE && |
665 | mmie->length != sizeof(*mmie) - 2) | 661 | mmie->length == sizeof(*mmie) - 2) |
666 | return -1; | 662 | return le16_to_cpu(mmie->key_id); |
667 | 663 | ||
668 | return le16_to_cpu(mmie->key_id); | 664 | mmie16 = (struct ieee80211_mmie_16 *) |
665 | (skb->data + skb->len - sizeof(*mmie16)); | ||
666 | if (skb->len >= 24 + sizeof(*mmie16) && | ||
667 | mmie16->element_id == WLAN_EID_MMIE && | ||
668 | mmie16->length == sizeof(*mmie16) - 2) | ||
669 | return le16_to_cpu(mmie16->key_id); | ||
670 | |||
671 | return -1; | ||
669 | } | 672 | } |
670 | 673 | ||
671 | static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, | 674 | static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, |
@@ -1655,11 +1658,27 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1655 | result = ieee80211_crypto_tkip_decrypt(rx); | 1658 | result = ieee80211_crypto_tkip_decrypt(rx); |
1656 | break; | 1659 | break; |
1657 | case WLAN_CIPHER_SUITE_CCMP: | 1660 | case WLAN_CIPHER_SUITE_CCMP: |
1658 | result = ieee80211_crypto_ccmp_decrypt(rx); | 1661 | result = ieee80211_crypto_ccmp_decrypt( |
1662 | rx, IEEE80211_CCMP_MIC_LEN); | ||
1663 | break; | ||
1664 | case WLAN_CIPHER_SUITE_CCMP_256: | ||
1665 | result = ieee80211_crypto_ccmp_decrypt( | ||
1666 | rx, IEEE80211_CCMP_256_MIC_LEN); | ||
1659 | break; | 1667 | break; |
1660 | case WLAN_CIPHER_SUITE_AES_CMAC: | 1668 | case WLAN_CIPHER_SUITE_AES_CMAC: |
1661 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | 1669 | result = ieee80211_crypto_aes_cmac_decrypt(rx); |
1662 | break; | 1670 | break; |
1671 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: | ||
1672 | result = ieee80211_crypto_aes_cmac_256_decrypt(rx); | ||
1673 | break; | ||
1674 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: | ||
1675 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: | ||
1676 | result = ieee80211_crypto_aes_gmac_decrypt(rx); | ||
1677 | break; | ||
1678 | case WLAN_CIPHER_SUITE_GCMP: | ||
1679 | case WLAN_CIPHER_SUITE_GCMP_256: | ||
1680 | result = ieee80211_crypto_gcmp_decrypt(rx); | ||
1681 | break; | ||
1663 | default: | 1682 | default: |
1664 | result = ieee80211_crypto_hw_decrypt(rx); | 1683 | result = ieee80211_crypto_hw_decrypt(rx); |
1665 | } | 1684 | } |
@@ -1786,7 +1805,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1786 | /* This is the first fragment of a new frame. */ | 1805 | /* This is the first fragment of a new frame. */ |
1787 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1806 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1788 | rx->seqno_idx, &(rx->skb)); | 1807 | rx->seqno_idx, &(rx->skb)); |
1789 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && | 1808 | if (rx->key && |
1809 | (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || | ||
1810 | rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) && | ||
1790 | ieee80211_has_protected(fc)) { | 1811 | ieee80211_has_protected(fc)) { |
1791 | int queue = rx->security_idx; | 1812 | int queue = rx->security_idx; |
1792 | /* Store CCMP PN so that we can verify that the next | 1813 | /* Store CCMP PN so that we can verify that the next |
@@ -1815,7 +1836,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1815 | int i; | 1836 | int i; |
1816 | u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; | 1837 | u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; |
1817 | int queue; | 1838 | int queue; |
1818 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) | 1839 | if (!rx->key || |
1840 | (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP && | ||
1841 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256)) | ||
1819 | return RX_DROP_UNUSABLE; | 1842 | return RX_DROP_UNUSABLE; |
1820 | memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); | 1843 | memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); |
1821 | for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { | 1844 | for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { |
@@ -2314,6 +2337,15 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2314 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 2337 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
2315 | return RX_DROP_MONITOR; | 2338 | return RX_DROP_MONITOR; |
2316 | 2339 | ||
2340 | if (rx->sta) { | ||
2341 | /* The seqno index has the same property as needed | ||
2342 | * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS | ||
2343 | * for non-QoS-data frames. Here we know it's a data | ||
2344 | * frame, so count MSDUs. | ||
2345 | */ | ||
2346 | rx->sta->rx_msdu[rx->seqno_idx]++; | ||
2347 | } | ||
2348 | |||
2317 | /* | 2349 | /* |
2318 | * Send unexpected-4addr-frame event to hostapd. For older versions, | 2350 | * Send unexpected-4addr-frame event to hostapd. For older versions, |
2319 | * also drop the frame to cooked monitor interfaces. | 2351 | * also drop the frame to cooked monitor interfaces. |
@@ -2598,7 +2630,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2598 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { | 2630 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { |
2599 | struct ieee80211_supported_band *sband; | 2631 | struct ieee80211_supported_band *sband; |
2600 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; | 2632 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; |
2601 | enum ieee80211_sta_rx_bandwidth new_bw; | 2633 | enum ieee80211_sta_rx_bandwidth max_bw, new_bw; |
2602 | 2634 | ||
2603 | /* If it doesn't support 40 MHz it can't change ... */ | 2635 | /* If it doesn't support 40 MHz it can't change ... */ |
2604 | if (!(rx->sta->sta.ht_cap.cap & | 2636 | if (!(rx->sta->sta.ht_cap.cap & |
@@ -2606,13 +2638,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2606 | goto handled; | 2638 | goto handled; |
2607 | 2639 | ||
2608 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) | 2640 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) |
2609 | new_bw = IEEE80211_STA_RX_BW_20; | 2641 | max_bw = IEEE80211_STA_RX_BW_20; |
2610 | else | 2642 | else |
2611 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | 2643 | max_bw = ieee80211_sta_cap_rx_bw(rx->sta); |
2644 | |||
2645 | /* set cur_max_bandwidth and recalc sta bw */ | ||
2646 | rx->sta->cur_max_bandwidth = max_bw; | ||
2647 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | ||
2612 | 2648 | ||
2613 | if (rx->sta->sta.bandwidth == new_bw) | 2649 | if (rx->sta->sta.bandwidth == new_bw) |
2614 | goto handled; | 2650 | goto handled; |
2615 | 2651 | ||
2652 | rx->sta->sta.bandwidth = new_bw; | ||
2616 | sband = rx->local->hw.wiphy->bands[status->band]; | 2653 | sband = rx->local->hw.wiphy->bands[status->band]; |
2617 | 2654 | ||
2618 | rate_control_rate_update(local, sband, rx->sta, | 2655 | rate_control_rate_update(local, sband, rx->sta, |