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