diff options
-rw-r--r-- | net/mac80211/rx.c | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 308e502a80eb..50c0803a63ba 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2609,7 +2609,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2609 | int prepares; | 2609 | int prepares; |
2610 | struct ieee80211_sub_if_data *prev = NULL; | 2610 | struct ieee80211_sub_if_data *prev = NULL; |
2611 | struct sk_buff *skb_new; | 2611 | struct sk_buff *skb_new; |
2612 | struct sta_info *sta, *tmp; | 2612 | struct sta_info *sta, *tmp, *prev_sta; |
2613 | bool found_sta = false; | 2613 | bool found_sta = false; |
2614 | int err = 0; | 2614 | int err = 0; |
2615 | 2615 | ||
@@ -2640,22 +2640,74 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2640 | ieee80211_verify_alignment(&rx); | 2640 | ieee80211_verify_alignment(&rx); |
2641 | 2641 | ||
2642 | if (ieee80211_is_data(fc)) { | 2642 | if (ieee80211_is_data(fc)) { |
2643 | prev_sta = NULL; | ||
2643 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2644 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2644 | rx.sta = sta; | ||
2645 | found_sta = true; | 2645 | found_sta = true; |
2646 | rx.sdata = sta->sdata; | 2646 | if (!prev_sta) { |
2647 | prev_sta = sta; | ||
2648 | continue; | ||
2649 | } | ||
2650 | |||
2651 | rx.sta = prev_sta; | ||
2652 | rx.sdata = prev_sta->sdata; | ||
2647 | 2653 | ||
2648 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2654 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2649 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); | 2655 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); |
2650 | if (prepares) { | 2656 | if (!prepares) |
2651 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2657 | goto next_sta; |
2652 | if (rx.flags & IEEE80211_RX_RA_MATCH) | 2658 | |
2653 | ieee80211_rx_michael_mic_report(hdr, &rx); | 2659 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2654 | } else | 2660 | if (rx.flags & IEEE80211_RX_RA_MATCH) |
2655 | prev = rx.sdata; | 2661 | ieee80211_rx_michael_mic_report(hdr, &rx); |
2662 | goto next_sta; | ||
2663 | } | ||
2664 | |||
2665 | /* | ||
2666 | * frame was destined for the previous interface | ||
2667 | * so invoke RX handlers for it | ||
2668 | */ | ||
2669 | skb_new = skb_copy(skb, GFP_ATOMIC); | ||
2670 | if (!skb_new) { | ||
2671 | if (net_ratelimit()) | ||
2672 | wiphy_debug(local->hw.wiphy, | ||
2673 | "failed to copy multicast" | ||
2674 | " frame for %s\n", | ||
2675 | prev_sta->sdata->name); | ||
2676 | goto next_sta; | ||
2677 | } | ||
2678 | ieee80211_invoke_rx_handlers(prev_sta->sdata, &rx, | ||
2679 | skb_new); | ||
2680 | next_sta: | ||
2681 | prev_sta = sta; | ||
2682 | } /* for all STA info */ | ||
2683 | |||
2684 | if (prev_sta) { | ||
2685 | rx.sta = prev_sta; | ||
2686 | rx.sdata = prev_sta->sdata; | ||
2687 | |||
2688 | rx.flags |= IEEE80211_RX_RA_MATCH; | ||
2689 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); | ||
2690 | if (!prepares) | ||
2691 | prev_sta = NULL; | ||
2692 | |||
2693 | if (prev_sta && status->flag & RX_FLAG_MMIC_ERROR) { | ||
2694 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2695 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2696 | prev_sta = NULL; | ||
2656 | } | 2697 | } |
2657 | } | 2698 | } |
2658 | } | 2699 | |
2700 | |||
2701 | if (prev_sta) { | ||
2702 | ieee80211_invoke_rx_handlers(prev_sta->sdata, &rx, skb); | ||
2703 | return; | ||
2704 | } else { | ||
2705 | if (found_sta) { | ||
2706 | dev_kfree_skb(skb); | ||
2707 | return; | ||
2708 | } | ||
2709 | } | ||
2710 | } /* if data frame */ | ||
2659 | if (!found_sta) { | 2711 | if (!found_sta) { |
2660 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2712 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2661 | if (!ieee80211_sdata_running(sdata)) | 2713 | if (!ieee80211_sdata_running(sdata)) |
@@ -2718,6 +2770,14 @@ next: | |||
2718 | 2770 | ||
2719 | if (!prepares) | 2771 | if (!prepares) |
2720 | prev = NULL; | 2772 | prev = NULL; |
2773 | |||
2774 | if (prev && status->flag & RX_FLAG_MMIC_ERROR) { | ||
2775 | rx.sdata = prev; | ||
2776 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2777 | ieee80211_rx_michael_mic_report(hdr, | ||
2778 | &rx); | ||
2779 | prev = NULL; | ||
2780 | } | ||
2721 | } | 2781 | } |
2722 | } | 2782 | } |
2723 | if (prev) | 2783 | if (prev) |