aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-04-04 02:37:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:37:56 -0400
commitd5cdfacb35ed886271d1ccfffbded98d3447da17 (patch)
tree8233a713949c4c8da8c98e75868efc74d5613c3d /net/mac80211/mlme.c
parent7590a550b88b8c3cb025f0a8ed58e279ad62e4c1 (diff)
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,
210 210
211static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 211static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
212 const u8 *bssid, u16 stype, u16 reason, 212 const u8 *bssid, u16 stype, u16 reason,
213 void *cookie) 213 void *cookie, bool send_frame)
214{ 214{
215 struct ieee80211_local *local = sdata->local; 215 struct ieee80211_local *local = sdata->local;
216 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 216 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -247,7 +247,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
247 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); 247 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
248 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) 248 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
249 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 249 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
250 ieee80211_tx_skb(sdata, skb); 250
251 if (send_frame)
252 ieee80211_tx_skb(sdata, skb);
253 else
254 kfree_skb(skb);
251} 255}
252 256
253void ieee80211_send_pspoll(struct ieee80211_local *local, 257void ieee80211_send_pspoll(struct ieee80211_local *local,
@@ -980,7 +984,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
980 ieee80211_send_deauth_disassoc(sdata, bssid, 984 ieee80211_send_deauth_disassoc(sdata, bssid,
981 IEEE80211_STYPE_DEAUTH, 985 IEEE80211_STYPE_DEAUTH,
982 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 986 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
983 NULL); 987 NULL, true);
984} 988}
985 989
986void ieee80211_beacon_connection_loss_work(struct work_struct *work) 990void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -1724,7 +1728,7 @@ static void ieee80211_sta_work(struct work_struct *work)
1724 ieee80211_send_deauth_disassoc(sdata, bssid, 1728 ieee80211_send_deauth_disassoc(sdata, bssid,
1725 IEEE80211_STYPE_DEAUTH, 1729 IEEE80211_STYPE_DEAUTH,
1726 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1730 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1727 NULL); 1731 NULL, true);
1728 mutex_lock(&ifmgd->mtx); 1732 mutex_lock(&ifmgd->mtx);
1729 } 1733 }
1730 } 1734 }
@@ -1908,6 +1912,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
1908 struct ieee80211_work *wk; 1912 struct ieee80211_work *wk;
1909 u16 auth_alg; 1913 u16 auth_alg;
1910 1914
1915 if (req->local_state_change)
1916 return 0; /* no need to update mac80211 state */
1917
1911 switch (req->auth_type) { 1918 switch (req->auth_type) {
1912 case NL80211_AUTHTYPE_OPEN_SYSTEM: 1919 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1913 auth_alg = WLAN_AUTH_OPEN; 1920 auth_alg = WLAN_AUTH_OPEN;
@@ -2163,9 +2170,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2163 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", 2170 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
2164 sdata->name, bssid, req->reason_code); 2171 sdata->name, bssid, req->reason_code);
2165 2172
2166 ieee80211_send_deauth_disassoc(sdata, bssid, 2173 ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH,
2167 IEEE80211_STYPE_DEAUTH, req->reason_code, 2174 req->reason_code, cookie,
2168 cookie); 2175 !req->local_state_change);
2169 2176
2170 ieee80211_recalc_idle(sdata->local); 2177 ieee80211_recalc_idle(sdata->local);
2171 2178
@@ -2202,7 +2209,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2202 2209
2203 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, 2210 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
2204 IEEE80211_STYPE_DISASSOC, req->reason_code, 2211 IEEE80211_STYPE_DISASSOC, req->reason_code,
2205 cookie); 2212 cookie, !req->local_state_change);
2206 sta_info_destroy_addr(sdata, bssid); 2213 sta_info_destroy_addr(sdata, bssid);
2207 2214
2208 ieee80211_recalc_idle(sdata->local); 2215 ieee80211_recalc_idle(sdata->local);