diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0cb4edee6af5..61c621e9273f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -60,7 +60,9 @@ static inline int should_drop_frame(struct sk_buff *skb, | |||
60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
62 | 62 | ||
63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
64 | RX_FLAG_FAILED_PLCP_CRC | | ||
65 | RX_FLAG_AMPDU_IS_ZEROLEN)) | ||
64 | return 1; | 66 | return 1; |
65 | if (unlikely(skb->len < 16 + present_fcs_len)) | 67 | if (unlikely(skb->len < 16 + present_fcs_len)) |
66 | return 1; | 68 | return 1; |
@@ -91,10 +93,17 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
91 | if (status->flag & RX_FLAG_HT) /* HT info */ | 93 | if (status->flag & RX_FLAG_HT) /* HT info */ |
92 | len += 3; | 94 | len += 3; |
93 | 95 | ||
96 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | ||
97 | /* padding */ | ||
98 | while (len & 3) | ||
99 | len++; | ||
100 | len += 8; | ||
101 | } | ||
102 | |||
94 | return len; | 103 | return len; |
95 | } | 104 | } |
96 | 105 | ||
97 | /** | 106 | /* |
98 | * ieee80211_add_rx_radiotap_header - add radiotap header | 107 | * ieee80211_add_rx_radiotap_header - add radiotap header |
99 | * | 108 | * |
100 | * add a radiotap header containing all the fields which the hardware provided. | 109 | * add a radiotap header containing all the fields which the hardware provided. |
@@ -215,6 +224,37 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
215 | pos++; | 224 | pos++; |
216 | *pos++ = status->rate_idx; | 225 | *pos++ = status->rate_idx; |
217 | } | 226 | } |
227 | |||
228 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | ||
229 | u16 flags = 0; | ||
230 | |||
231 | /* ensure 4 byte alignment */ | ||
232 | while ((pos - (u8 *)rthdr) & 3) | ||
233 | pos++; | ||
234 | rthdr->it_present |= | ||
235 | cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); | ||
236 | put_unaligned_le32(status->ampdu_reference, pos); | ||
237 | pos += 4; | ||
238 | if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN) | ||
239 | flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN; | ||
240 | if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN) | ||
241 | flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN; | ||
242 | if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN) | ||
243 | flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN; | ||
244 | if (status->flag & RX_FLAG_AMPDU_IS_LAST) | ||
245 | flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; | ||
246 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) | ||
247 | flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; | ||
248 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) | ||
249 | flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; | ||
250 | put_unaligned_le16(flags, pos); | ||
251 | pos += 2; | ||
252 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) | ||
253 | *pos++ = status->ampdu_delimiter_crc; | ||
254 | else | ||
255 | *pos++ = 0; | ||
256 | *pos++ = 0; | ||
257 | } | ||
218 | } | 258 | } |
219 | 259 | ||
220 | /* | 260 | /* |
@@ -2268,7 +2308,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2268 | 2308 | ||
2269 | goto queue; | 2309 | goto queue; |
2270 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 2310 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
2271 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 2311 | if (status->band != IEEE80211_BAND_5GHZ) |
2272 | break; | 2312 | break; |
2273 | 2313 | ||
2274 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2314 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
@@ -2772,8 +2812,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2772 | if (!bssid) { | 2812 | if (!bssid) { |
2773 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | 2813 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) |
2774 | return 0; | 2814 | return 0; |
2775 | } else if (!ieee80211_bssid_match(bssid, | 2815 | } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { |
2776 | sdata->vif.addr)) { | ||
2777 | /* | 2816 | /* |
2778 | * Accept public action frames even when the | 2817 | * Accept public action frames even when the |
2779 | * BSSID doesn't match, this is used for P2P | 2818 | * BSSID doesn't match, this is used for P2P |
@@ -2793,9 +2832,18 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2793 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) | 2832 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) |
2794 | return 0; | 2833 | return 0; |
2795 | break; | 2834 | break; |
2835 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2836 | if (!ieee80211_is_public_action(hdr, skb->len) && | ||
2837 | !ieee80211_is_probe_req(hdr->frame_control) && | ||
2838 | !ieee80211_is_probe_resp(hdr->frame_control) && | ||
2839 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2840 | return 0; | ||
2841 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
2842 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
2843 | break; | ||
2796 | default: | 2844 | default: |
2797 | /* should never get here */ | 2845 | /* should never get here */ |
2798 | WARN_ON(1); | 2846 | WARN_ON_ONCE(1); |
2799 | break; | 2847 | break; |
2800 | } | 2848 | } |
2801 | 2849 | ||