aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorGuy Eilam <guy@wizery.com>2011-08-17 08:18:15 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-26 10:47:55 -0400
commit2a33bee2753bf28411de8822e3e3c7501966eb1b (patch)
treedac6419b65bdd79da56c6855bbf4a439f424e05c /net/mac80211/rx.c
parent8c71df7a2f6a5345d6cad34e810c50edeca81521 (diff)
mac80211: fix race condition between assoc_done and first EAP packet
When associating to an AP, the station might miss the first EAP packet that the AP sends due to a race condition between the association success procedure and the rx flow in mac80211. In such cases, the packet might fall in ieee80211_rx_h_check due to the fact that the relevant rx->sta wasn't allocated yet. Allocation of the relevant station info struct before actually sending the association request and setting it with a new dummy_sta flag solve this problem. The station will accept only EAP packets from the AP while it is in the pre-association/dummy state. This dummy station entry is not seen by normal sta_info_get() calls, only by sta_info_get_bss_rx(). The driver is not notified for the first insertion of the dummy station. The driver is notified only after the association is complete and the dummy flag is removed from the station entry. That way, all the rest of the code flow should be untouched by this change. Signed-off-by: Guy Eilam <guy@wizery.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c4453fdd6e11..edd46193af6f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -850,8 +850,21 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
850 ieee80211_is_pspoll(hdr->frame_control)) && 850 ieee80211_is_pspoll(hdr->frame_control)) &&
851 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && 851 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
852 rx->sdata->vif.type != NL80211_IFTYPE_WDS && 852 rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
853 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) 853 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
854 if (rx->sta && rx->sta->dummy &&
855 ieee80211_is_data_present(hdr->frame_control)) {
856 u16 ethertype;
857 u8 *payload;
858
859 payload = rx->skb->data +
860 ieee80211_hdrlen(hdr->frame_control);
861 ethertype = (payload[6] << 8) | payload[7];
862 if (cpu_to_be16(ethertype) ==
863 rx->sdata->control_port_protocol)
864 return RX_CONTINUE;
865 }
854 return RX_DROP_MONITOR; 866 return RX_DROP_MONITOR;
867 }
855 868
856 return RX_CONTINUE; 869 return RX_CONTINUE;
857} 870}
@@ -2808,7 +2821,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2808 if (ieee80211_is_data(fc)) { 2821 if (ieee80211_is_data(fc)) {
2809 prev_sta = NULL; 2822 prev_sta = NULL;
2810 2823
2811 for_each_sta_info(local, hdr->addr2, sta, tmp) { 2824 for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {
2812 if (!prev_sta) { 2825 if (!prev_sta) {
2813 prev_sta = sta; 2826 prev_sta = sta;
2814 continue; 2827 continue;
@@ -2852,7 +2865,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2852 continue; 2865 continue;
2853 } 2866 }
2854 2867
2855 rx.sta = sta_info_get_bss(prev, hdr->addr2); 2868 rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
2856 rx.sdata = prev; 2869 rx.sdata = prev;
2857 ieee80211_prepare_and_rx_handle(&rx, skb, false); 2870 ieee80211_prepare_and_rx_handle(&rx, skb, false);
2858 2871
@@ -2860,7 +2873,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2860 } 2873 }
2861 2874
2862 if (prev) { 2875 if (prev) {
2863 rx.sta = sta_info_get_bss(prev, hdr->addr2); 2876 rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
2864 rx.sdata = prev; 2877 rx.sdata = prev;
2865 2878
2866 if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) 2879 if (ieee80211_prepare_and_rx_handle(&rx, skb, true))