diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 165 |
1 files changed, 62 insertions, 103 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f59f6f51e39c..13311f8960ab 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2443,18 +2443,13 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2443 | } | 2443 | } |
2444 | } | 2444 | } |
2445 | 2445 | ||
2446 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | 2446 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) |
2447 | struct ieee80211_rx_data *rx, | ||
2448 | struct sk_buff *skb) | ||
2449 | { | 2447 | { |
2450 | struct sk_buff_head reorder_release; | 2448 | struct sk_buff_head reorder_release; |
2451 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2449 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2452 | 2450 | ||
2453 | __skb_queue_head_init(&reorder_release); | 2451 | __skb_queue_head_init(&reorder_release); |
2454 | 2452 | ||
2455 | rx->skb = skb; | ||
2456 | rx->sdata = sdata; | ||
2457 | |||
2458 | #define CALL_RXH(rxh) \ | 2453 | #define CALL_RXH(rxh) \ |
2459 | do { \ | 2454 | do { \ |
2460 | res = rxh(rx); \ | 2455 | res = rxh(rx); \ |
@@ -2598,21 +2593,63 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2598 | } | 2593 | } |
2599 | 2594 | ||
2600 | /* | 2595 | /* |
2596 | * This function returns whether or not the SKB | ||
2597 | * was destined for RX processing or not, which, | ||
2598 | * if consume is true, is equivalent to whether | ||
2599 | * or not the skb was consumed. | ||
2600 | */ | ||
2601 | static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, | ||
2602 | struct sk_buff *skb, bool consume) | ||
2603 | { | ||
2604 | struct ieee80211_local *local = rx->local; | ||
2605 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
2606 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2607 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
2608 | int prepares; | ||
2609 | |||
2610 | rx->skb = skb; | ||
2611 | rx->flags |= IEEE80211_RX_RA_MATCH; | ||
2612 | prepares = prepare_for_handlers(rx, hdr); | ||
2613 | |||
2614 | if (!prepares) | ||
2615 | return false; | ||
2616 | |||
2617 | if (status->flag & RX_FLAG_MMIC_ERROR) { | ||
2618 | if (rx->flags & IEEE80211_RX_RA_MATCH) | ||
2619 | ieee80211_rx_michael_mic_report(hdr, rx); | ||
2620 | return false; | ||
2621 | } | ||
2622 | |||
2623 | if (!consume) { | ||
2624 | skb = skb_copy(skb, GFP_ATOMIC); | ||
2625 | if (!skb) { | ||
2626 | if (net_ratelimit()) | ||
2627 | wiphy_debug(local->hw.wiphy, | ||
2628 | "failed to copy multicast frame for %s\n", | ||
2629 | sdata->name); | ||
2630 | return true; | ||
2631 | } | ||
2632 | |||
2633 | rx->skb = skb; | ||
2634 | } | ||
2635 | |||
2636 | ieee80211_invoke_rx_handlers(rx); | ||
2637 | return true; | ||
2638 | } | ||
2639 | |||
2640 | /* | ||
2601 | * This is the actual Rx frames handler. as it blongs to Rx path it must | 2641 | * This is the actual Rx frames handler. as it blongs to Rx path it must |
2602 | * be called with rcu_read_lock protection. | 2642 | * be called with rcu_read_lock protection. |
2603 | */ | 2643 | */ |
2604 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2644 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
2605 | struct sk_buff *skb) | 2645 | struct sk_buff *skb) |
2606 | { | 2646 | { |
2607 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2608 | struct ieee80211_local *local = hw_to_local(hw); | 2647 | struct ieee80211_local *local = hw_to_local(hw); |
2609 | struct ieee80211_sub_if_data *sdata; | 2648 | struct ieee80211_sub_if_data *sdata; |
2610 | struct ieee80211_hdr *hdr; | 2649 | struct ieee80211_hdr *hdr; |
2611 | __le16 fc; | 2650 | __le16 fc; |
2612 | struct ieee80211_rx_data rx; | 2651 | struct ieee80211_rx_data rx; |
2613 | int prepares; | 2652 | struct ieee80211_sub_if_data *prev; |
2614 | struct ieee80211_sub_if_data *prev = NULL; | ||
2615 | struct sk_buff *skb_new; | ||
2616 | struct sta_info *sta, *tmp, *prev_sta; | 2653 | struct sta_info *sta, *tmp, *prev_sta; |
2617 | bool found_sta = false; | 2654 | bool found_sta = false; |
2618 | int err = 0; | 2655 | int err = 0; |
@@ -2645,8 +2682,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2645 | 2682 | ||
2646 | if (ieee80211_is_data(fc)) { | 2683 | if (ieee80211_is_data(fc)) { |
2647 | prev_sta = NULL; | 2684 | prev_sta = NULL; |
2685 | |||
2648 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2686 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2649 | found_sta = true; | 2687 | found_sta = true; |
2688 | |||
2650 | if (!prev_sta) { | 2689 | if (!prev_sta) { |
2651 | prev_sta = sta; | 2690 | prev_sta = sta; |
2652 | continue; | 2691 | continue; |
@@ -2654,65 +2693,23 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2654 | 2693 | ||
2655 | rx.sta = prev_sta; | 2694 | rx.sta = prev_sta; |
2656 | rx.sdata = prev_sta->sdata; | 2695 | rx.sdata = prev_sta->sdata; |
2696 | ieee80211_prepare_and_rx_handle(&rx, skb, false); | ||
2657 | 2697 | ||
2658 | rx.flags |= IEEE80211_RX_RA_MATCH; | ||
2659 | prepares = prepare_for_handlers(&rx, hdr); | ||
2660 | if (!prepares) | ||
2661 | goto next_sta; | ||
2662 | |||
2663 | if (status->flag & RX_FLAG_MMIC_ERROR) { | ||
2664 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2665 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2666 | goto next_sta; | ||
2667 | } | ||
2668 | |||
2669 | /* | ||
2670 | * frame was destined for the previous interface | ||
2671 | * so invoke RX handlers for it | ||
2672 | */ | ||
2673 | skb_new = skb_copy(skb, GFP_ATOMIC); | ||
2674 | if (!skb_new) { | ||
2675 | if (net_ratelimit()) | ||
2676 | wiphy_debug(local->hw.wiphy, | ||
2677 | "failed to copy multicast" | ||
2678 | " frame for %s\n", | ||
2679 | prev_sta->sdata->name); | ||
2680 | goto next_sta; | ||
2681 | } | ||
2682 | ieee80211_invoke_rx_handlers(prev_sta->sdata, &rx, | ||
2683 | skb_new); | ||
2684 | next_sta: | ||
2685 | prev_sta = sta; | 2698 | prev_sta = sta; |
2686 | } /* for all STA info */ | 2699 | } |
2687 | 2700 | ||
2688 | if (prev_sta) { | 2701 | if (prev_sta) { |
2689 | rx.sta = prev_sta; | 2702 | rx.sta = prev_sta; |
2690 | rx.sdata = prev_sta->sdata; | 2703 | rx.sdata = prev_sta->sdata; |
2691 | 2704 | ||
2692 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2705 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
2693 | prepares = prepare_for_handlers(&rx, hdr); | ||
2694 | if (!prepares) | ||
2695 | prev_sta = NULL; | ||
2696 | |||
2697 | if (prev_sta && status->flag & RX_FLAG_MMIC_ERROR) { | ||
2698 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2699 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2700 | prev_sta = NULL; | ||
2701 | } | ||
2702 | } | ||
2703 | |||
2704 | |||
2705 | if (prev_sta) { | ||
2706 | ieee80211_invoke_rx_handlers(prev_sta->sdata, &rx, skb); | ||
2707 | return; | ||
2708 | } else { | ||
2709 | if (found_sta) { | ||
2710 | dev_kfree_skb(skb); | ||
2711 | return; | 2706 | return; |
2712 | } | ||
2713 | } | 2707 | } |
2714 | } /* if data frame */ | 2708 | } |
2709 | |||
2715 | if (!found_sta) { | 2710 | if (!found_sta) { |
2711 | prev = NULL; | ||
2712 | |||
2716 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2713 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2717 | if (!ieee80211_sdata_running(sdata)) | 2714 | if (!ieee80211_sdata_running(sdata)) |
2718 | continue; | 2715 | continue; |
@@ -2734,35 +2731,8 @@ next_sta: | |||
2734 | 2731 | ||
2735 | rx.sta = sta_info_get_bss(prev, hdr->addr2); | 2732 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
2736 | rx.sdata = prev; | 2733 | rx.sdata = prev; |
2734 | ieee80211_prepare_and_rx_handle(&rx, skb, false); | ||
2737 | 2735 | ||
2738 | rx.flags |= IEEE80211_RX_RA_MATCH; | ||
2739 | prepares = prepare_for_handlers(&rx, hdr); | ||
2740 | |||
2741 | if (!prepares) | ||
2742 | goto next; | ||
2743 | |||
2744 | if (status->flag & RX_FLAG_MMIC_ERROR) { | ||
2745 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2746 | ieee80211_rx_michael_mic_report(hdr, | ||
2747 | &rx); | ||
2748 | goto next; | ||
2749 | } | ||
2750 | |||
2751 | /* | ||
2752 | * frame was destined for the previous interface | ||
2753 | * so invoke RX handlers for it | ||
2754 | */ | ||
2755 | |||
2756 | skb_new = skb_copy(skb, GFP_ATOMIC); | ||
2757 | if (!skb_new) { | ||
2758 | if (net_ratelimit()) | ||
2759 | wiphy_debug(local->hw.wiphy, | ||
2760 | "failed to copy multicast frame for %s\n", | ||
2761 | prev->name); | ||
2762 | goto next; | ||
2763 | } | ||
2764 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); | ||
2765 | next: | ||
2766 | prev = sdata; | 2736 | prev = sdata; |
2767 | } | 2737 | } |
2768 | 2738 | ||
@@ -2770,24 +2740,13 @@ next: | |||
2770 | rx.sta = sta_info_get_bss(prev, hdr->addr2); | 2740 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
2771 | rx.sdata = prev; | 2741 | rx.sdata = prev; |
2772 | 2742 | ||
2773 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2743 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
2774 | prepares = prepare_for_handlers(&rx, hdr); | 2744 | return; |
2775 | |||
2776 | if (!prepares) | ||
2777 | prev = NULL; | ||
2778 | |||
2779 | if (prev && status->flag & RX_FLAG_MMIC_ERROR) { | ||
2780 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2781 | ieee80211_rx_michael_mic_report(hdr, | ||
2782 | &rx); | ||
2783 | prev = NULL; | ||
2784 | } | ||
2785 | } | 2745 | } |
2746 | |||
2786 | } | 2747 | } |
2787 | if (prev) | 2748 | |
2788 | ieee80211_invoke_rx_handlers(prev, &rx, skb); | 2749 | dev_kfree_skb(skb); |
2789 | else | ||
2790 | dev_kfree_skb(skb); | ||
2791 | } | 2750 | } |
2792 | 2751 | ||
2793 | /* | 2752 | /* |