diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 108 |
1 files changed, 74 insertions, 34 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 13fcd2d17c6b..8fa99554f4e2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -38,7 +38,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
38 | { | 38 | { |
39 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 39 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
40 | if (likely(skb->len > FCS_LEN)) | 40 | if (likely(skb->len > FCS_LEN)) |
41 | skb_trim(skb, skb->len - FCS_LEN); | 41 | __pskb_trim(skb, skb->len - FCS_LEN); |
42 | else { | 42 | else { |
43 | /* driver bug */ | 43 | /* driver bug */ |
44 | WARN_ON(1); | 44 | WARN_ON(1); |
@@ -80,8 +80,6 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
80 | len += 8; | 80 | len += 8; |
81 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 81 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
82 | len += 1; | 82 | len += 1; |
83 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | ||
84 | len += 1; | ||
85 | 83 | ||
86 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 84 | if (len & 1) /* padding for RX_FLAGS if necessary */ |
87 | len++; | 85 | len++; |
@@ -178,14 +176,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
178 | pos++; | 176 | pos++; |
179 | } | 177 | } |
180 | 178 | ||
181 | /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ | ||
182 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { | ||
183 | *pos = status->noise; | ||
184 | rthdr->it_present |= | ||
185 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); | ||
186 | pos++; | ||
187 | } | ||
188 | |||
189 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ | 179 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ |
190 | 180 | ||
191 | /* IEEE80211_RADIOTAP_ANTENNA */ | 181 | /* IEEE80211_RADIOTAP_ANTENNA */ |
@@ -235,6 +225,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
235 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 225 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
236 | present_fcs_len = FCS_LEN; | 226 | present_fcs_len = FCS_LEN; |
237 | 227 | ||
228 | /* make sure hdr->frame_control is on the linear part */ | ||
229 | if (!pskb_may_pull(origskb, 2)) { | ||
230 | dev_kfree_skb(origskb); | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
238 | if (!local->monitors) { | 234 | if (!local->monitors) { |
239 | if (should_drop_frame(origskb, present_fcs_len)) { | 235 | if (should_drop_frame(origskb, present_fcs_len)) { |
240 | dev_kfree_skb(origskb); | 236 | dev_kfree_skb(origskb); |
@@ -492,7 +488,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
492 | 488 | ||
493 | if (ieee80211_is_action(hdr->frame_control)) { | 489 | if (ieee80211_is_action(hdr->frame_control)) { |
494 | mgmt = (struct ieee80211_mgmt *)hdr; | 490 | mgmt = (struct ieee80211_mgmt *)hdr; |
495 | if (mgmt->u.action.category != MESH_PLINK_CATEGORY) | 491 | if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK) |
496 | return RX_DROP_MONITOR; | 492 | return RX_DROP_MONITOR; |
497 | return RX_CONTINUE; | 493 | return RX_CONTINUE; |
498 | } | 494 | } |
@@ -722,14 +718,16 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
722 | 718 | ||
723 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 719 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
724 | 720 | ||
725 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 721 | spin_lock(&sta->lock); |
726 | goto dont_reorder; | 722 | |
723 | if (!sta->ampdu_mlme.tid_active_rx[tid]) | ||
724 | goto dont_reorder_unlock; | ||
727 | 725 | ||
728 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 726 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
729 | 727 | ||
730 | /* qos null data frames are excluded */ | 728 | /* qos null data frames are excluded */ |
731 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 729 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
732 | goto dont_reorder; | 730 | goto dont_reorder_unlock; |
733 | 731 | ||
734 | /* new, potentially un-ordered, ampdu frame - process it */ | 732 | /* new, potentially un-ordered, ampdu frame - process it */ |
735 | 733 | ||
@@ -741,15 +739,20 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
741 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 739 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
742 | sc = le16_to_cpu(hdr->seq_ctrl); | 740 | sc = le16_to_cpu(hdr->seq_ctrl); |
743 | if (sc & IEEE80211_SCTL_FRAG) { | 741 | if (sc & IEEE80211_SCTL_FRAG) { |
744 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 742 | spin_unlock(&sta->lock); |
745 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 743 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
744 | WLAN_REASON_QSTA_REQUIRE_SETUP); | ||
746 | dev_kfree_skb(skb); | 745 | dev_kfree_skb(skb); |
747 | return; | 746 | return; |
748 | } | 747 | } |
749 | 748 | ||
750 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | 749 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) { |
750 | spin_unlock(&sta->lock); | ||
751 | return; | 751 | return; |
752 | } | ||
752 | 753 | ||
754 | dont_reorder_unlock: | ||
755 | spin_unlock(&sta->lock); | ||
753 | dont_reorder: | 756 | dont_reorder: |
754 | __skb_queue_tail(frames, skb); | 757 | __skb_queue_tail(frames, skb); |
755 | } | 758 | } |
@@ -896,6 +899,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
896 | rx->key = key; | 899 | rx->key = key; |
897 | return RX_CONTINUE; | 900 | return RX_CONTINUE; |
898 | } else { | 901 | } else { |
902 | u8 keyid; | ||
899 | /* | 903 | /* |
900 | * The device doesn't give us the IV so we won't be | 904 | * The device doesn't give us the IV so we won't be |
901 | * able to look up the key. That's ok though, we | 905 | * able to look up the key. That's ok though, we |
@@ -918,7 +922,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
918 | * no need to call ieee80211_wep_get_keyidx, | 922 | * no need to call ieee80211_wep_get_keyidx, |
919 | * it verifies a bunch of things we've done already | 923 | * it verifies a bunch of things we've done already |
920 | */ | 924 | */ |
921 | keyidx = rx->skb->data[hdrlen + 3] >> 6; | 925 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); |
926 | keyidx = keyid >> 6; | ||
922 | 927 | ||
923 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | 928 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); |
924 | 929 | ||
@@ -939,6 +944,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
939 | return RX_DROP_MONITOR; | 944 | return RX_DROP_MONITOR; |
940 | } | 945 | } |
941 | 946 | ||
947 | if (skb_linearize(rx->skb)) | ||
948 | return RX_DROP_UNUSABLE; | ||
949 | |||
950 | hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
951 | |||
942 | /* Check for weak IVs if possible */ | 952 | /* Check for weak IVs if possible */ |
943 | if (rx->sta && rx->key->conf.alg == ALG_WEP && | 953 | if (rx->sta && rx->key->conf.alg == ALG_WEP && |
944 | ieee80211_is_data(hdr->frame_control) && | 954 | ieee80211_is_data(hdr->frame_control) && |
@@ -1077,7 +1087,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1077 | sta->rx_fragments++; | 1087 | sta->rx_fragments++; |
1078 | sta->rx_bytes += rx->skb->len; | 1088 | sta->rx_bytes += rx->skb->len; |
1079 | sta->last_signal = status->signal; | 1089 | sta->last_signal = status->signal; |
1080 | sta->last_noise = status->noise; | ||
1081 | 1090 | ||
1082 | /* | 1091 | /* |
1083 | * Change STA power saving mode only at the end of a frame | 1092 | * Change STA power saving mode only at the end of a frame |
@@ -1240,6 +1249,15 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1240 | } | 1249 | } |
1241 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); | 1250 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); |
1242 | 1251 | ||
1252 | if (skb_linearize(rx->skb)) | ||
1253 | return RX_DROP_UNUSABLE; | ||
1254 | |||
1255 | /* | ||
1256 | * skb_linearize() might change the skb->data and | ||
1257 | * previously cached variables (in this case, hdr) need to | ||
1258 | * be refreshed with the new data. | ||
1259 | */ | ||
1260 | hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
1243 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | 1261 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; |
1244 | 1262 | ||
1245 | if (frag == 0) { | 1263 | if (frag == 0) { |
@@ -1405,21 +1423,24 @@ static int | |||
1405 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | 1423 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) |
1406 | { | 1424 | { |
1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1425 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1426 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
1408 | __le16 fc = hdr->frame_control; | 1427 | __le16 fc = hdr->frame_control; |
1409 | int res; | ||
1410 | 1428 | ||
1411 | res = ieee80211_drop_unencrypted(rx, fc); | 1429 | /* |
1412 | if (unlikely(res)) | 1430 | * Pass through unencrypted frames if the hardware has |
1413 | return res; | 1431 | * decrypted them already. |
1432 | */ | ||
1433 | if (status->flag & RX_FLAG_DECRYPTED) | ||
1434 | return 0; | ||
1414 | 1435 | ||
1415 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1436 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1416 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1437 | if (unlikely(!ieee80211_has_protected(fc) && |
1438 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1417 | rx->key)) | 1439 | rx->key)) |
1418 | return -EACCES; | 1440 | return -EACCES; |
1419 | /* BIP does not use Protected field, so need to check MMIE */ | 1441 | /* BIP does not use Protected field, so need to check MMIE */ |
1420 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1442 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1421 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | 1443 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) |
1422 | rx->key)) | ||
1423 | return -EACCES; | 1444 | return -EACCES; |
1424 | /* | 1445 | /* |
1425 | * When using MFP, Action frames are not allowed prior to | 1446 | * When using MFP, Action frames are not allowed prior to |
@@ -1597,6 +1618,9 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1597 | skb->dev = dev; | 1618 | skb->dev = dev; |
1598 | __skb_queue_head_init(&frame_list); | 1619 | __skb_queue_head_init(&frame_list); |
1599 | 1620 | ||
1621 | if (skb_linearize(skb)) | ||
1622 | return RX_DROP_UNUSABLE; | ||
1623 | |||
1600 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, | 1624 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1601 | rx->sdata->vif.type, | 1625 | rx->sdata->vif.type, |
1602 | rx->local->hw.extra_tx_headroom); | 1626 | rx->local->hw.extra_tx_headroom); |
@@ -1795,10 +1819,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1795 | if (ieee80211_is_back_req(bar->frame_control)) { | 1819 | if (ieee80211_is_back_req(bar->frame_control)) { |
1796 | if (!rx->sta) | 1820 | if (!rx->sta) |
1797 | return RX_DROP_MONITOR; | 1821 | return RX_DROP_MONITOR; |
1822 | spin_lock(&rx->sta->lock); | ||
1798 | tid = le16_to_cpu(bar->control) >> 12; | 1823 | tid = le16_to_cpu(bar->control) >> 12; |
1799 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] | 1824 | if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) { |
1800 | != HT_AGG_STATE_OPERATIONAL) | 1825 | spin_unlock(&rx->sta->lock); |
1801 | return RX_DROP_MONITOR; | 1826 | return RX_DROP_MONITOR; |
1827 | } | ||
1802 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | 1828 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1803 | 1829 | ||
1804 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1830 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
@@ -1812,6 +1838,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1812 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1838 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1813 | frames); | 1839 | frames); |
1814 | kfree_skb(skb); | 1840 | kfree_skb(skb); |
1841 | spin_unlock(&rx->sta->lock); | ||
1815 | return RX_QUEUED; | 1842 | return RX_QUEUED; |
1816 | } | 1843 | } |
1817 | 1844 | ||
@@ -1973,8 +2000,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1973 | goto handled; | 2000 | goto handled; |
1974 | } | 2001 | } |
1975 | break; | 2002 | break; |
1976 | case MESH_PLINK_CATEGORY: | 2003 | case WLAN_CATEGORY_MESH_PLINK: |
1977 | case MESH_PATH_SEL_CATEGORY: | 2004 | case WLAN_CATEGORY_MESH_PATH_SEL: |
1978 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2005 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1979 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 2006 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); |
1980 | break; | 2007 | break; |
@@ -2371,29 +2398,42 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2371 | struct ieee80211_local *local = hw_to_local(hw); | 2398 | struct ieee80211_local *local = hw_to_local(hw); |
2372 | struct ieee80211_sub_if_data *sdata; | 2399 | struct ieee80211_sub_if_data *sdata; |
2373 | struct ieee80211_hdr *hdr; | 2400 | struct ieee80211_hdr *hdr; |
2401 | __le16 fc; | ||
2374 | struct ieee80211_rx_data rx; | 2402 | struct ieee80211_rx_data rx; |
2375 | int prepares; | 2403 | int prepares; |
2376 | struct ieee80211_sub_if_data *prev = NULL; | 2404 | struct ieee80211_sub_if_data *prev = NULL; |
2377 | struct sk_buff *skb_new; | 2405 | struct sk_buff *skb_new; |
2378 | struct sta_info *sta, *tmp; | 2406 | struct sta_info *sta, *tmp; |
2379 | bool found_sta = false; | 2407 | bool found_sta = false; |
2408 | int err = 0; | ||
2380 | 2409 | ||
2381 | hdr = (struct ieee80211_hdr *)skb->data; | 2410 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; |
2382 | memset(&rx, 0, sizeof(rx)); | 2411 | memset(&rx, 0, sizeof(rx)); |
2383 | rx.skb = skb; | 2412 | rx.skb = skb; |
2384 | rx.local = local; | 2413 | rx.local = local; |
2385 | 2414 | ||
2386 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) | 2415 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2387 | local->dot11ReceivedFragmentCount++; | 2416 | local->dot11ReceivedFragmentCount++; |
2388 | 2417 | ||
2389 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2418 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2390 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2419 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) |
2391 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2420 | rx.flags |= IEEE80211_RX_IN_SCAN; |
2392 | 2421 | ||
2422 | if (ieee80211_is_mgmt(fc)) | ||
2423 | err = skb_linearize(skb); | ||
2424 | else | ||
2425 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | ||
2426 | |||
2427 | if (err) { | ||
2428 | dev_kfree_skb(skb); | ||
2429 | return; | ||
2430 | } | ||
2431 | |||
2432 | hdr = (struct ieee80211_hdr *)skb->data; | ||
2393 | ieee80211_parse_qos(&rx); | 2433 | ieee80211_parse_qos(&rx); |
2394 | ieee80211_verify_alignment(&rx); | 2434 | ieee80211_verify_alignment(&rx); |
2395 | 2435 | ||
2396 | if (ieee80211_is_data(hdr->frame_control)) { | 2436 | if (ieee80211_is_data(fc)) { |
2397 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2437 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2398 | rx.sta = sta; | 2438 | rx.sta = sta; |
2399 | found_sta = true; | 2439 | found_sta = true; |