aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c33
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 */
41static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, 41static 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
61static inline int should_drop_frame(struct sk_buff *skb, 58static 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;