summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-06-01 08:10:09 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-06-01 08:10:27 -0400
commitc9c99f8938e41b878802d5d8481d6f7a212515b0 (patch)
treeead781c43f5d93626e2394b6df6555543c5375f4 /net/mac80211
parentf7959e9c73200f2ae361d0d311aa501f2c6a05c7 (diff)
mac80211: act upon and report deauth while associating
When trying to associate, the AP could send a deauth frame instead. Currently mac80211 drops that frame and doesn't report it to the supplicant, which, in some versions and/or in certain circumstances will simply keep trying to associate over and over again instead of trying authentication again. Fix this by reacting to deauth frames while associating, reporting them to the supplicant and dropping the association attempt (which is bound to fail.) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/mlme.c92
1 files changed, 53 insertions, 39 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 387fe70ab126..853cfa71b96a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2521,6 +2521,34 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
2521 sdata->u.mgd.auth_data = NULL; 2521 sdata->u.mgd.auth_data = NULL;
2522} 2522}
2523 2523
2524static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2525 bool assoc)
2526{
2527 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
2528
2529 sdata_assert_lock(sdata);
2530
2531 if (!assoc) {
2532 /*
2533 * we are not associated yet, the only timer that could be
2534 * running is the timeout for the association response which
2535 * which is not relevant anymore.
2536 */
2537 del_timer_sync(&sdata->u.mgd.timer);
2538 sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
2539
2540 eth_zero_addr(sdata->u.mgd.bssid);
2541 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2542 sdata->u.mgd.flags = 0;
2543 mutex_lock(&sdata->local->mtx);
2544 ieee80211_vif_release_channel(sdata);
2545 mutex_unlock(&sdata->local->mtx);
2546 }
2547
2548 kfree(assoc_data);
2549 sdata->u.mgd.assoc_data = NULL;
2550}
2551
2524static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, 2552static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
2525 struct ieee80211_mgmt *mgmt, size_t len) 2553 struct ieee80211_mgmt *mgmt, size_t len)
2526{ 2554{
@@ -2713,28 +2741,42 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
2713 struct ieee80211_mgmt *mgmt, size_t len) 2741 struct ieee80211_mgmt *mgmt, size_t len)
2714{ 2742{
2715 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2743 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2716 const u8 *bssid = NULL; 2744 u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
2717 u16 reason_code;
2718 2745
2719 sdata_assert_lock(sdata); 2746 sdata_assert_lock(sdata);
2720 2747
2721 if (len < 24 + 2) 2748 if (len < 24 + 2)
2722 return; 2749 return;
2723 2750
2724 if (!ifmgd->associated || 2751 if (ifmgd->associated &&
2725 !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) 2752 ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
2726 return; 2753 const u8 *bssid = ifmgd->associated->bssid;
2727 2754
2728 bssid = ifmgd->associated->bssid; 2755 sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
2756 bssid, reason_code,
2757 ieee80211_get_reason_code_string(reason_code));
2729 2758
2730 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); 2759 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2731 2760
2732 sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n", 2761 ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false,
2733 bssid, reason_code, ieee80211_get_reason_code_string(reason_code)); 2762 reason_code);
2763 return;
2764 }
2734 2765
2735 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2766 if (ifmgd->assoc_data &&
2767 ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
2768 const u8 *bssid = ifmgd->assoc_data->bss->bssid;
2736 2769
2737 ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code); 2770 sdata_info(sdata,
2771 "deauthenticated from %pM while associating (Reason: %u=%s)\n",
2772 bssid, reason_code,
2773 ieee80211_get_reason_code_string(reason_code));
2774
2775 ieee80211_destroy_assoc_data(sdata, false);
2776
2777 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2778 return;
2779 }
2738} 2780}
2739 2781
2740 2782
@@ -2814,34 +2856,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
2814 } 2856 }
2815} 2857}
2816 2858
2817static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2818 bool assoc)
2819{
2820 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
2821
2822 sdata_assert_lock(sdata);
2823
2824 if (!assoc) {
2825 /*
2826 * we are not associated yet, the only timer that could be
2827 * running is the timeout for the association response which
2828 * which is not relevant anymore.
2829 */
2830 del_timer_sync(&sdata->u.mgd.timer);
2831 sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
2832
2833 eth_zero_addr(sdata->u.mgd.bssid);
2834 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2835 sdata->u.mgd.flags = 0;
2836 mutex_lock(&sdata->local->mtx);
2837 ieee80211_vif_release_channel(sdata);
2838 mutex_unlock(&sdata->local->mtx);
2839 }
2840
2841 kfree(assoc_data);
2842 sdata->u.mgd.assoc_data = NULL;
2843}
2844
2845static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, 2859static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2846 struct cfg80211_bss *cbss, 2860 struct cfg80211_bss *cbss,
2847 struct ieee80211_mgmt *mgmt, size_t len) 2861 struct ieee80211_mgmt *mgmt, size_t len)