diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 119 |
1 files changed, 64 insertions, 55 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f237df408378..5bae28693da8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1472,7 +1472,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1472 | { | 1472 | { |
1473 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1473 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1474 | struct net_device *dev = sdata->dev; | 1474 | struct net_device *dev = sdata->dev; |
1475 | struct ieee80211_local *local = rx->local; | ||
1476 | struct sk_buff *skb, *xmit_skb; | 1475 | struct sk_buff *skb, *xmit_skb; |
1477 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 1476 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
1478 | struct sta_info *dsta; | 1477 | struct sta_info *dsta; |
@@ -1495,8 +1494,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1495 | printk(KERN_DEBUG "%s: failed to clone " | 1494 | printk(KERN_DEBUG "%s: failed to clone " |
1496 | "multicast frame\n", dev->name); | 1495 | "multicast frame\n", dev->name); |
1497 | } else { | 1496 | } else { |
1498 | dsta = sta_info_get(local, skb->data); | 1497 | dsta = sta_info_get(sdata, skb->data); |
1499 | if (dsta && dsta->sdata->dev == dev) { | 1498 | if (dsta) { |
1500 | /* | 1499 | /* |
1501 | * The destination station is associated to | 1500 | * The destination station is associated to |
1502 | * this AP (in this VLAN), so send the frame | 1501 | * this AP (in this VLAN), so send the frame |
@@ -2363,6 +2362,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2363 | int prepares; | 2362 | int prepares; |
2364 | struct ieee80211_sub_if_data *prev = NULL; | 2363 | struct ieee80211_sub_if_data *prev = NULL; |
2365 | struct sk_buff *skb_new; | 2364 | struct sk_buff *skb_new; |
2365 | struct sta_info *sta, *tmp; | ||
2366 | bool found_sta = false; | ||
2366 | 2367 | ||
2367 | hdr = (struct ieee80211_hdr *)skb->data; | 2368 | hdr = (struct ieee80211_hdr *)skb->data; |
2368 | memset(&rx, 0, sizeof(rx)); | 2369 | memset(&rx, 0, sizeof(rx)); |
@@ -2379,68 +2380,76 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2379 | ieee80211_parse_qos(&rx); | 2380 | ieee80211_parse_qos(&rx); |
2380 | ieee80211_verify_alignment(&rx); | 2381 | ieee80211_verify_alignment(&rx); |
2381 | 2382 | ||
2382 | rx.sta = sta_info_get(local, hdr->addr2); | 2383 | if (ieee80211_is_data(hdr->frame_control)) { |
2383 | if (rx.sta) | 2384 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2384 | rx.sdata = rx.sta->sdata; | 2385 | rx.sta = sta; |
2385 | 2386 | found_sta = true; | |
2386 | if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { | 2387 | rx.sdata = sta->sdata; |
2387 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2388 | |
2388 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); | 2389 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2389 | if (prepares) { | 2390 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); |
2390 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2391 | if (prepares) { |
2391 | if (rx.flags & IEEE80211_RX_RA_MATCH) | 2392 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2392 | ieee80211_rx_michael_mic_report(hdr, &rx); | 2393 | if (rx.flags & IEEE80211_RX_RA_MATCH) |
2393 | } else | 2394 | ieee80211_rx_michael_mic_report(hdr, &rx); |
2394 | prev = rx.sdata; | 2395 | } else |
2396 | prev = rx.sdata; | ||
2397 | } | ||
2395 | } | 2398 | } |
2396 | } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2399 | } |
2397 | if (!netif_running(sdata->dev)) | 2400 | if (!found_sta) { |
2398 | continue; | 2401 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2402 | if (!netif_running(sdata->dev)) | ||
2403 | continue; | ||
2399 | 2404 | ||
2400 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 2405 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
2401 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2406 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
2402 | continue; | 2407 | continue; |
2403 | 2408 | ||
2404 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2409 | rx.sta = sta_info_get(sdata, hdr->addr2); |
2405 | prepares = prepare_for_handlers(sdata, &rx, hdr); | ||
2406 | 2410 | ||
2407 | if (!prepares) | 2411 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2408 | continue; | 2412 | prepares = prepare_for_handlers(sdata, &rx, hdr); |
2409 | 2413 | ||
2410 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2414 | if (!prepares) |
2411 | rx.sdata = sdata; | 2415 | continue; |
2412 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2413 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2414 | continue; | ||
2415 | } | ||
2416 | 2416 | ||
2417 | /* | 2417 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2418 | * frame is destined for this interface, but if it's not | 2418 | rx.sdata = sdata; |
2419 | * also for the previous one we handle that after the | 2419 | if (rx.flags & IEEE80211_RX_RA_MATCH) |
2420 | * loop to avoid copying the SKB once too much | 2420 | ieee80211_rx_michael_mic_report(hdr, |
2421 | */ | 2421 | &rx); |
2422 | continue; | ||
2423 | } | ||
2422 | 2424 | ||
2423 | if (!prev) { | 2425 | /* |
2424 | prev = sdata; | 2426 | * frame is destined for this interface, but if it's |
2425 | continue; | 2427 | * not also for the previous one we handle that after |
2426 | } | 2428 | * the loop to avoid copying the SKB once too much |
2429 | */ | ||
2427 | 2430 | ||
2428 | /* | 2431 | if (!prev) { |
2429 | * frame was destined for the previous interface | 2432 | prev = sdata; |
2430 | * so invoke RX handlers for it | 2433 | continue; |
2431 | */ | 2434 | } |
2432 | 2435 | ||
2433 | skb_new = skb_copy(skb, GFP_ATOMIC); | 2436 | /* |
2434 | if (!skb_new) { | 2437 | * frame was destined for the previous interface |
2435 | if (net_ratelimit()) | 2438 | * so invoke RX handlers for it |
2436 | printk(KERN_DEBUG "%s: failed to copy " | 2439 | */ |
2437 | "multicast frame for %s\n", | 2440 | |
2438 | wiphy_name(local->hw.wiphy), | 2441 | skb_new = skb_copy(skb, GFP_ATOMIC); |
2439 | prev->dev->name); | 2442 | if (!skb_new) { |
2440 | continue; | 2443 | if (net_ratelimit()) |
2444 | printk(KERN_DEBUG "%s: failed to copy " | ||
2445 | "multicast frame for %s\n", | ||
2446 | wiphy_name(local->hw.wiphy), | ||
2447 | prev->dev->name); | ||
2448 | continue; | ||
2449 | } | ||
2450 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | ||
2451 | prev = sdata; | ||
2441 | } | 2452 | } |
2442 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | ||
2443 | prev = sdata; | ||
2444 | } | 2453 | } |
2445 | if (prev) | 2454 | if (prev) |
2446 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); | 2455 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); |