diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7fa8c6be7bf..a961003ffa2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -140,8 +140,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
140 | pos++; | 140 | pos++; |
141 | 141 | ||
142 | /* IEEE80211_RADIOTAP_RATE */ | 142 | /* IEEE80211_RADIOTAP_RATE */ |
143 | if (status->flag & RX_FLAG_HT) { | 143 | if (!rate || status->flag & RX_FLAG_HT) { |
144 | /* | 144 | /* |
145 | * Without rate information don't add it. If we have, | ||
145 | * MCS information is a separate field in radiotap, | 146 | * MCS information is a separate field in radiotap, |
146 | * added below. The byte here is needed as padding | 147 | * added below. The byte here is needed as padding |
147 | * for the channel though, so initialise it to 0. | 148 | * for the channel though, so initialise it to 0. |
@@ -162,12 +163,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
162 | else if (status->flag & RX_FLAG_HT) | 163 | else if (status->flag & RX_FLAG_HT) |
163 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | 164 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, |
164 | pos); | 165 | pos); |
165 | else if (rate->flags & IEEE80211_RATE_ERP_G) | 166 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
166 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, | 167 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, |
167 | pos); | 168 | pos); |
168 | else | 169 | else if (rate) |
169 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, | 170 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, |
170 | pos); | 171 | pos); |
172 | else | ||
173 | put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos); | ||
171 | pos += 2; | 174 | pos += 2; |
172 | 175 | ||
173 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | 176 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ |
@@ -331,15 +334,18 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
331 | { | 334 | { |
332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 335 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
333 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 336 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
334 | int tid; | 337 | int tid, seqno_idx, security_idx; |
335 | 338 | ||
336 | /* does the frame have a qos control field? */ | 339 | /* does the frame have a qos control field? */ |
337 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 340 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
338 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 341 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
339 | /* frame has qos control */ | 342 | /* frame has qos control */ |
340 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 343 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
341 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | 344 | if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) |
342 | status->rx_flags |= IEEE80211_RX_AMSDU; | 345 | status->rx_flags |= IEEE80211_RX_AMSDU; |
346 | |||
347 | seqno_idx = tid; | ||
348 | security_idx = tid; | ||
343 | } else { | 349 | } else { |
344 | /* | 350 | /* |
345 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): | 351 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): |
@@ -352,10 +358,15 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
352 | * | 358 | * |
353 | * We also use that counter for non-QoS STAs. | 359 | * We also use that counter for non-QoS STAs. |
354 | */ | 360 | */ |
355 | tid = NUM_RX_DATA_QUEUES - 1; | 361 | seqno_idx = NUM_RX_DATA_QUEUES; |
362 | security_idx = 0; | ||
363 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
364 | security_idx = NUM_RX_DATA_QUEUES; | ||
365 | tid = 0; | ||
356 | } | 366 | } |
357 | 367 | ||
358 | rx->queue = tid; | 368 | rx->seqno_idx = seqno_idx; |
369 | rx->security_idx = security_idx; | ||
359 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. | 370 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. |
360 | * For now, set skb->priority to 0 for other cases. */ | 371 | * For now, set skb->priority to 0 for other cases. */ |
361 | rx->skb->priority = (tid > 7) ? 0 : tid; | 372 | rx->skb->priority = (tid > 7) ? 0 : tid; |
@@ -810,7 +821,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
810 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ | 821 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ |
811 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { | 822 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { |
812 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | 823 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
813 | rx->sta->last_seq_ctrl[rx->queue] == | 824 | rx->sta->last_seq_ctrl[rx->seqno_idx] == |
814 | hdr->seq_ctrl)) { | 825 | hdr->seq_ctrl)) { |
815 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { | 826 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { |
816 | rx->local->dot11FrameDuplicateCount++; | 827 | rx->local->dot11FrameDuplicateCount++; |
@@ -818,7 +829,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
818 | } | 829 | } |
819 | return RX_DROP_UNUSABLE; | 830 | return RX_DROP_UNUSABLE; |
820 | } else | 831 | } else |
821 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; | 832 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; |
822 | } | 833 | } |
823 | 834 | ||
824 | if (unlikely(rx->skb->len < 16)) { | 835 | if (unlikely(rx->skb->len < 16)) { |
@@ -1011,6 +1022,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1011 | } | 1022 | } |
1012 | 1023 | ||
1013 | if (rx->key) { | 1024 | if (rx->key) { |
1025 | if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) | ||
1026 | return RX_DROP_MONITOR; | ||
1027 | |||
1014 | rx->key->tx_rx_count++; | 1028 | rx->key->tx_rx_count++; |
1015 | /* TODO: add threshold stuff again */ | 1029 | /* TODO: add threshold stuff again */ |
1016 | } else { | 1030 | } else { |
@@ -1374,11 +1388,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1374 | if (frag == 0) { | 1388 | if (frag == 0) { |
1375 | /* This is the first fragment of a new frame. */ | 1389 | /* This is the first fragment of a new frame. */ |
1376 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1390 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1377 | rx->queue, &(rx->skb)); | 1391 | rx->seqno_idx, &(rx->skb)); |
1378 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && | 1392 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && |
1379 | ieee80211_has_protected(fc)) { | 1393 | ieee80211_has_protected(fc)) { |
1380 | int queue = ieee80211_is_mgmt(fc) ? | 1394 | int queue = rx->security_idx; |
1381 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1382 | /* Store CCMP PN so that we can verify that the next | 1395 | /* Store CCMP PN so that we can verify that the next |
1383 | * fragment has a sequential PN value. */ | 1396 | * fragment has a sequential PN value. */ |
1384 | entry->ccmp = 1; | 1397 | entry->ccmp = 1; |
@@ -1392,7 +1405,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1392 | /* This is a fragment for a frame that should already be pending in | 1405 | /* This is a fragment for a frame that should already be pending in |
1393 | * fragment cache. Add this fragment to the end of the pending entry. | 1406 | * fragment cache. Add this fragment to the end of the pending entry. |
1394 | */ | 1407 | */ |
1395 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); | 1408 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, |
1409 | rx->seqno_idx, hdr); | ||
1396 | if (!entry) { | 1410 | if (!entry) { |
1397 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 1411 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
1398 | return RX_DROP_MONITOR; | 1412 | return RX_DROP_MONITOR; |
@@ -1412,8 +1426,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1412 | if (pn[i]) | 1426 | if (pn[i]) |
1413 | break; | 1427 | break; |
1414 | } | 1428 | } |
1415 | queue = ieee80211_is_mgmt(fc) ? | 1429 | queue = rx->security_idx; |
1416 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1417 | rpn = rx->key->u.ccmp.rx_pn[queue]; | 1430 | rpn = rx->key->u.ccmp.rx_pn[queue]; |
1418 | if (memcmp(pn, rpn, CCMP_PN_LEN)) | 1431 | if (memcmp(pn, rpn, CCMP_PN_LEN)) |
1419 | return RX_DROP_UNUSABLE; | 1432 | return RX_DROP_UNUSABLE; |
@@ -2590,7 +2603,9 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2590 | .sta = sta, | 2603 | .sta = sta, |
2591 | .sdata = sta->sdata, | 2604 | .sdata = sta->sdata, |
2592 | .local = sta->local, | 2605 | .local = sta->local, |
2593 | .queue = tid, | 2606 | /* This is OK -- must be QoS data frame */ |
2607 | .security_idx = tid, | ||
2608 | .seqno_idx = tid, | ||
2594 | .flags = 0, | 2609 | .flags = 0, |
2595 | }; | 2610 | }; |
2596 | struct tid_ampdu_rx *tid_agg_rx; | 2611 | struct tid_ampdu_rx *tid_agg_rx; |