]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/mac80211/rx.c
Merge tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[karo-tx-linux.git] / net / mac80211 / rx.c
index d69ca513848e7eda2227a18d0f98b164591532a1..1101563357eae365f1e1a1df926ecf36fdc0570b 100644 (file)
@@ -361,9 +361,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                u16 known = local->hw.radiotap_vht_details;
 
                rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
-               /* known field - how to handle 80+80? */
-               if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
-                       known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
                put_unaligned_le16(known, pos);
                pos += 2;
                /* flags */
@@ -378,8 +375,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                /* bandwidth */
                if (status->vht_flag & RX_VHT_FLAG_80MHZ)
                        *pos++ = 4;
-               else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
-                       *pos++ = 0; /* marked not known above */
                else if (status->vht_flag & RX_VHT_FLAG_160MHZ)
                        *pos++ = 11;
                else if (status->flag & RX_FLAG_40MHZ)
@@ -652,6 +647,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
 {
        struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data;
        struct ieee80211_mmie *mmie;
+       struct ieee80211_mmie_16 *mmie16;
 
        if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
                return -1;
@@ -661,11 +657,18 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
 
        mmie = (struct ieee80211_mmie *)
                (skb->data + skb->len - sizeof(*mmie));
-       if (mmie->element_id != WLAN_EID_MMIE ||
-           mmie->length != sizeof(*mmie) - 2)
-               return -1;
-
-       return le16_to_cpu(mmie->key_id);
+       if (mmie->element_id == WLAN_EID_MMIE &&
+           mmie->length == sizeof(*mmie) - 2)
+               return le16_to_cpu(mmie->key_id);
+
+       mmie16 = (struct ieee80211_mmie_16 *)
+               (skb->data + skb->len - sizeof(*mmie16));
+       if (skb->len >= 24 + sizeof(*mmie16) &&
+           mmie16->element_id == WLAN_EID_MMIE &&
+           mmie16->length == sizeof(*mmie16) - 2)
+               return le16_to_cpu(mmie16->key_id);
+
+       return -1;
 }
 
 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)
                result = ieee80211_crypto_tkip_decrypt(rx);
                break;
        case WLAN_CIPHER_SUITE_CCMP:
-               result = ieee80211_crypto_ccmp_decrypt(rx);
+               result = ieee80211_crypto_ccmp_decrypt(
+                       rx, IEEE80211_CCMP_MIC_LEN);
+               break;
+       case WLAN_CIPHER_SUITE_CCMP_256:
+               result = ieee80211_crypto_ccmp_decrypt(
+                       rx, IEEE80211_CCMP_256_MIC_LEN);
                break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
                result = ieee80211_crypto_aes_cmac_decrypt(rx);
                break;
+       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+               result = ieee80211_crypto_aes_cmac_256_decrypt(rx);
+               break;
+       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+       case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+               result = ieee80211_crypto_aes_gmac_decrypt(rx);
+               break;
+       case WLAN_CIPHER_SUITE_GCMP:
+       case WLAN_CIPHER_SUITE_GCMP_256:
+               result = ieee80211_crypto_gcmp_decrypt(rx);
+               break;
        default:
                result = ieee80211_crypto_hw_decrypt(rx);
        }
@@ -1786,7 +1805,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                /* This is the first fragment of a new frame. */
                entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
                                                 rx->seqno_idx, &(rx->skb));
-               if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP &&
+               if (rx->key &&
+                   (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
                    ieee80211_has_protected(fc)) {
                        int queue = rx->security_idx;
                        /* Store CCMP PN so that we can verify that the next
@@ -1815,7 +1836,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                int i;
                u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
                int queue;
-               if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
+               if (!rx->key ||
+                   (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
                        return RX_DROP_UNUSABLE;
                memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
                for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
@@ -2314,6 +2337,15 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
                return RX_DROP_MONITOR;
 
+       if (rx->sta) {
+               /* The seqno index has the same property as needed
+                * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS
+                * for non-QoS-data frames. Here we know it's a data
+                * frame, so count MSDUs.
+                */
+               rx->sta->rx_msdu[rx->seqno_idx]++;
+       }
+
        /*
         * Send unexpected-4addr-frame event to hostapd. For older versions,
         * also drop the frame to cooked monitor interfaces.
@@ -2598,7 +2630,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
                        struct ieee80211_supported_band *sband;
                        u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
-                       enum ieee80211_sta_rx_bandwidth new_bw;
+                       enum ieee80211_sta_rx_bandwidth max_bw, new_bw;
 
                        /* If it doesn't support 40 MHz it can't change ... */
                        if (!(rx->sta->sta.ht_cap.cap &
@@ -2606,13 +2638,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                                goto handled;
 
                        if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ)
-                               new_bw = IEEE80211_STA_RX_BW_20;
+                               max_bw = IEEE80211_STA_RX_BW_20;
                        else
-                               new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
+                               max_bw = ieee80211_sta_cap_rx_bw(rx->sta);
+
+                       /* set cur_max_bandwidth and recalc sta bw */
+                       rx->sta->cur_max_bandwidth = max_bw;
+                       new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
 
                        if (rx->sta->sta.bandwidth == new_bw)
                                goto handled;
 
+                       rx->sta->sta.bandwidth = new_bw;
                        sband = rx->local->hw.wiphy->bands[status->band];
 
                        rate_control_rate_update(local, sband, rx->sta,