Skip to content

Commit

Permalink
mac80211: act upon and report deauth while associating
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg committed Jun 1, 2015
1 parent f7959e9 commit c9c99f8
Showing 1 changed file with 53 additions and 39 deletions.
92 changes: 53 additions & 39 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -2521,6 +2521,34 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
sdata->u.mgd.auth_data = NULL;
}

static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
bool assoc)
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;

sdata_assert_lock(sdata);

if (!assoc) {
/*
* we are not associated yet, the only timer that could be
* running is the timeout for the association response which
* which is not relevant anymore.
*/
del_timer_sync(&sdata->u.mgd.timer);
sta_info_destroy_addr(sdata, assoc_data->bss->bssid);

eth_zero_addr(sdata->u.mgd.bssid);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
sdata->u.mgd.flags = 0;
mutex_lock(&sdata->local->mtx);
ieee80211_vif_release_channel(sdata);
mutex_unlock(&sdata->local->mtx);
}

kfree(assoc_data);
sdata->u.mgd.assoc_data = NULL;
}

static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len)
{
Expand Down Expand Up @@ -2713,28 +2741,42 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
const u8 *bssid = NULL;
u16 reason_code;
u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);

sdata_assert_lock(sdata);

if (len < 24 + 2)
return;

if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
return;
if (ifmgd->associated &&
ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
const u8 *bssid = ifmgd->associated->bssid;

bssid = ifmgd->associated->bssid;
sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
bssid, reason_code,
ieee80211_get_reason_code_string(reason_code));

reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);

sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
bssid, reason_code, ieee80211_get_reason_code_string(reason_code));
ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false,
reason_code);
return;
}

ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
if (ifmgd->assoc_data &&
ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
const u8 *bssid = ifmgd->assoc_data->bss->bssid;

ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code);
sdata_info(sdata,
"deauthenticated from %pM while associating (Reason: %u=%s)\n",
bssid, reason_code,
ieee80211_get_reason_code_string(reason_code));

ieee80211_destroy_assoc_data(sdata, false);

cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
return;
}
}


Expand Down Expand Up @@ -2814,34 +2856,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
}
}

static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
bool assoc)
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;

sdata_assert_lock(sdata);

if (!assoc) {
/*
* we are not associated yet, the only timer that could be
* running is the timeout for the association response which
* which is not relevant anymore.
*/
del_timer_sync(&sdata->u.mgd.timer);
sta_info_destroy_addr(sdata, assoc_data->bss->bssid);

eth_zero_addr(sdata->u.mgd.bssid);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
sdata->u.mgd.flags = 0;
mutex_lock(&sdata->local->mtx);
ieee80211_vif_release_channel(sdata);
mutex_unlock(&sdata->local->mtx);
}

kfree(assoc_data);
sdata->u.mgd.assoc_data = NULL;
}

static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
struct cfg80211_bss *cbss,
struct ieee80211_mgmt *mgmt, size_t len)
Expand Down

0 comments on commit c9c99f8

Please sign in to comment.