summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c85
1 files changed, 54 insertions, 31 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b03f1f3ef2ed..f7a390ff9679 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -415,8 +415,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
ieee80211_sta_send_associnfo(sdata, ifsta);
} else {
- netif_carrier_off(sdata->dev);
- ieee80211_sta_tear_down_BA_sessions(sdata, ifsta->bssid);
ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
changed |= ieee80211_reset_erp_info(sdata);
@@ -439,18 +437,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
}
-static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_if_sta *ifsta, int deauth)
-{
- if (deauth) {
- ifsta->direct_probe_tries = 0;
- ifsta->auth_tries = 0;
- }
- ifsta->assoc_scan_tries = 0;
- ifsta->assoc_tries = 0;
- ieee80211_set_associated(sdata, ifsta, 0);
-}
-
void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
int encrypt)
{
@@ -844,6 +830,50 @@ static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_tx(sdata, skb, 0);
}
+static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_if_sta *ifsta, bool deauth,
+ bool self_disconnected, u16 reason)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta;
+
+ rcu_read_lock();
+
+ sta = sta_info_get(local, ifsta->bssid);
+ if (!sta) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (deauth) {
+ ifsta->direct_probe_tries = 0;
+ ifsta->auth_tries = 0;
+ }
+ ifsta->assoc_scan_tries = 0;
+ ifsta->assoc_tries = 0;
+
+ netif_carrier_off(sdata->dev);
+
+ ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr);
+
+ if (self_disconnected) {
+ if (deauth)
+ ieee80211_send_deauth(sdata, ifsta, reason);
+ else
+ ieee80211_send_disassoc(sdata, ifsta, reason);
+ }
+
+ ieee80211_set_associated(sdata, ifsta, 0);
+
+ if (self_disconnected)
+ ifsta->state = IEEE80211_STA_MLME_DISABLED;
+
+ sta_info_unlink(&sta);
+
+ rcu_read_unlock();
+
+ sta_info_destroy(sta);
+}
static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_sta *ifsta)
@@ -938,7 +968,6 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata,
"range\n",
sdata->dev->name, print_mac(mac, ifsta->bssid));
disassoc = 1;
- sta_info_unlink(&sta);
} else
ieee80211_send_probe_req(sdata, ifsta->bssid,
local->scan_ssid,
@@ -958,16 +987,12 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
- if (disassoc && sta)
- sta_info_destroy(sta);
-
- if (disassoc) {
- ifsta->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_set_associated(sdata, ifsta, 0);
- } else {
+ if (disassoc)
+ ieee80211_set_disassoc(sdata, ifsta, true, true,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ else
mod_timer(&ifsta->timer, jiffies +
IEEE80211_MONITORING_INTERVAL);
- }
}
@@ -1832,7 +1857,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
IEEE80211_RETRY_AUTH_INTERVAL);
}
- ieee80211_set_disassoc(sdata, ifsta, 1);
+ ieee80211_set_disassoc(sdata, ifsta, true, false, 0);
ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
}
@@ -1862,7 +1887,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
IEEE80211_RETRY_AUTH_INTERVAL);
}
- ieee80211_set_disassoc(sdata, ifsta, 0);
+ ieee80211_set_disassoc(sdata, ifsta, false, false, 0);
}
@@ -3200,8 +3225,8 @@ void ieee80211_sta_work(struct work_struct *work)
printk(KERN_DEBUG "%s: privacy configuration mismatch and "
"mixed-cell disabled - disassociate\n", sdata->dev->name);
- ieee80211_send_disassoc(sdata, ifsta, WLAN_REASON_UNSPECIFIED);
- ieee80211_set_disassoc(sdata, ifsta, 0);
+ ieee80211_set_disassoc(sdata, ifsta, false, true,
+ WLAN_REASON_UNSPECIFIED);
}
}
@@ -4236,8 +4261,7 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason
sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
return -EINVAL;
- ieee80211_send_deauth(sdata, ifsta, reason);
- ieee80211_set_disassoc(sdata, ifsta, 1);
+ ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
return 0;
}
@@ -4255,8 +4279,7 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
return -1;
- ieee80211_send_disassoc(sdata, ifsta, reason);
- ieee80211_set_disassoc(sdata, ifsta, 0);
+ ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
return 0;
}