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