summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-04-04 09:37:19 +0300
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:37:56 -0400
commitd5cdfacb35ed886271d1ccfffbded98d3447da17 (patch)
tree8233a713949c4c8da8c98e75868efc74d5613c3d /net/mac80211/mlme.c
parent7590a550b88b8c3cb025f0a8ed58e279ad62e4c1 (diff)
downloadlinux-d5cdfacb35ed886271d1ccfffbded98d3447da17.tar.bz2
cfg80211: Add local-state-change-only auth/deauth/disassoc
cfg80211 is quite strict on allowing authentication and association commands only in certain states. In order to meet these requirements, user space applications may need to clear authentication or association state in some cases. Currently, this can be done with deauth/disassoc command, but that ends up sending out Deauthentication or Disassociation frame unnecessarily. Add a new nl80211 attribute to allow this sending of the frame be skipped, but with all other deauth/disassoc operations being completed. Similar state change is also needed for IEEE 802.11r FT protocol in the FT-over-DS case which does not use Authentication frame exchange in a transition to another BSS. For this to work with cfg80211, an authentication entry needs to be created for the target BSS without sending out an Authentication frame. The nl80211 authentication command can be used for this purpose, too, with the new attribute to indicate that the command is only for changing local state. This enables wpa_supplicant to complete FT-over-DS transition successfully. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 57a3c62139e2..4c189d0be4a3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -210,7 +210,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, u16 stype, u16 reason,
- void *cookie)
+ void *cookie, bool send_frame)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -247,7 +247,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- ieee80211_tx_skb(sdata, skb);
+
+ if (send_frame)
+ ieee80211_tx_skb(sdata, skb);
+ else
+ kfree_skb(skb);
}
void ieee80211_send_pspoll(struct ieee80211_local *local,
@@ -980,7 +984,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
ieee80211_send_deauth_disassoc(sdata, bssid,
IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
- NULL);
+ NULL, true);
}
void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -1724,7 +1728,7 @@ static void ieee80211_sta_work(struct work_struct *work)
ieee80211_send_deauth_disassoc(sdata, bssid,
IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
- NULL);
+ NULL, true);
mutex_lock(&ifmgd->mtx);
}
}
@@ -1908,6 +1912,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_work *wk;
u16 auth_alg;
+ if (req->local_state_change)
+ return 0; /* no need to update mac80211 state */
+
switch (req->auth_type) {
case NL80211_AUTHTYPE_OPEN_SYSTEM:
auth_alg = WLAN_AUTH_OPEN;
@@ -2163,9 +2170,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
sdata->name, bssid, req->reason_code);
- ieee80211_send_deauth_disassoc(sdata, bssid,
- IEEE80211_STYPE_DEAUTH, req->reason_code,
- cookie);
+ ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH,
+ req->reason_code, cookie,
+ !req->local_state_change);
ieee80211_recalc_idle(sdata->local);
@@ -2202,7 +2209,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
IEEE80211_STYPE_DISASSOC, req->reason_code,
- cookie);
+ cookie, !req->local_state_change);
sta_info_destroy_addr(sdata, bssid);
ieee80211_recalc_idle(sdata->local);