diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 33 |
1 files changed, 12 insertions, 21 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 01df328530ad..798fa82b6ae3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -39,11 +39,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
39 | * only useful for monitoring. | 39 | * only useful for monitoring. |
40 | */ | 40 | */ |
41 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 41 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, |
42 | struct sk_buff *skb, | 42 | struct sk_buff *skb) |
43 | int rtap_len) | ||
44 | { | 43 | { |
45 | skb_pull(skb, rtap_len); | ||
46 | |||
47 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 44 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
48 | if (likely(skb->len > FCS_LEN)) | 45 | if (likely(skb->len > FCS_LEN)) |
49 | skb_trim(skb, skb->len - FCS_LEN); | 46 | skb_trim(skb, skb->len - FCS_LEN); |
@@ -59,15 +56,14 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
59 | } | 56 | } |
60 | 57 | ||
61 | static inline int should_drop_frame(struct sk_buff *skb, | 58 | static inline int should_drop_frame(struct sk_buff *skb, |
62 | int present_fcs_len, | 59 | int present_fcs_len) |
63 | int radiotap_len) | ||
64 | { | 60 | { |
65 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 61 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
66 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 62 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
67 | 63 | ||
68 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 64 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
69 | return 1; | 65 | return 1; |
70 | if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len)) | 66 | if (unlikely(skb->len < 16 + present_fcs_len)) |
71 | return 1; | 67 | return 1; |
72 | if (ieee80211_is_ctl(hdr->frame_control) && | 68 | if (ieee80211_is_ctl(hdr->frame_control) && |
73 | !ieee80211_is_pspoll(hdr->frame_control) && | 69 | !ieee80211_is_pspoll(hdr->frame_control) && |
@@ -225,7 +221,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
225 | struct sk_buff *skb, *skb2; | 221 | struct sk_buff *skb, *skb2; |
226 | struct net_device *prev_dev = NULL; | 222 | struct net_device *prev_dev = NULL; |
227 | int present_fcs_len = 0; | 223 | int present_fcs_len = 0; |
228 | int rtap_len = 0; | ||
229 | 224 | ||
230 | /* | 225 | /* |
231 | * First, we may need to make a copy of the skb because | 226 | * First, we may need to make a copy of the skb because |
@@ -235,25 +230,23 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
235 | * We don't need to, of course, if we aren't going to return | 230 | * We don't need to, of course, if we aren't going to return |
236 | * the SKB because it has a bad FCS/PLCP checksum. | 231 | * the SKB because it has a bad FCS/PLCP checksum. |
237 | */ | 232 | */ |
238 | if (status->flag & RX_FLAG_RADIOTAP) | 233 | |
239 | rtap_len = ieee80211_get_radiotap_len(origskb->data); | 234 | /* room for the radiotap header based on driver features */ |
240 | else | 235 | needed_headroom = ieee80211_rx_radiotap_len(local, status); |
241 | /* room for the radiotap header based on driver features */ | ||
242 | needed_headroom = ieee80211_rx_radiotap_len(local, status); | ||
243 | 236 | ||
244 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 237 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
245 | present_fcs_len = FCS_LEN; | 238 | present_fcs_len = FCS_LEN; |
246 | 239 | ||
247 | if (!local->monitors) { | 240 | if (!local->monitors) { |
248 | if (should_drop_frame(origskb, present_fcs_len, rtap_len)) { | 241 | if (should_drop_frame(origskb, present_fcs_len)) { |
249 | dev_kfree_skb(origskb); | 242 | dev_kfree_skb(origskb); |
250 | return NULL; | 243 | return NULL; |
251 | } | 244 | } |
252 | 245 | ||
253 | return remove_monitor_info(local, origskb, rtap_len); | 246 | return remove_monitor_info(local, origskb); |
254 | } | 247 | } |
255 | 248 | ||
256 | if (should_drop_frame(origskb, present_fcs_len, rtap_len)) { | 249 | if (should_drop_frame(origskb, present_fcs_len)) { |
257 | /* only need to expand headroom if necessary */ | 250 | /* only need to expand headroom if necessary */ |
258 | skb = origskb; | 251 | skb = origskb; |
259 | origskb = NULL; | 252 | origskb = NULL; |
@@ -277,16 +270,14 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
277 | */ | 270 | */ |
278 | skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); | 271 | skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); |
279 | 272 | ||
280 | origskb = remove_monitor_info(local, origskb, rtap_len); | 273 | origskb = remove_monitor_info(local, origskb); |
281 | 274 | ||
282 | if (!skb) | 275 | if (!skb) |
283 | return origskb; | 276 | return origskb; |
284 | } | 277 | } |
285 | 278 | ||
286 | /* if necessary, prepend radiotap information */ | 279 | /* prepend radiotap information */ |
287 | if (!(status->flag & RX_FLAG_RADIOTAP)) | 280 | ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); |
288 | ieee80211_add_rx_radiotap_header(local, skb, rate, | ||
289 | needed_headroom); | ||
290 | 281 | ||
291 | skb_reset_mac_header(skb); | 282 | skb_reset_mac_header(skb); |
292 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 283 | skb->ip_summed = CHECKSUM_UNNECESSARY; |