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; |
