aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-12-23 07:15:34 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-28 16:54:54 -0500
commitf679f65d417c3ea3f91b4bbfb68e3951c9eb8f04 (patch)
treed4fb47f1197d175fa1851a1d4f75d78246ef4106
parent63f170e0c80a131cdd549fab7afb5036009944fc (diff)
mac80211: generalise management work a bit
As a first step of generalising management work, this renames a few things and puts more information directly into the struct so that auth/assoc need not access the BSS pointer as often -- in fact it can be removed from auth completely. Also since the previous patch made sure a new work item is used for association, we can make the different data a union. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/ieee80211_i.h53
-rw-r--r--net/mac80211/mlme.c226
2 files changed, 172 insertions, 107 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e21e0301548b..0339e909e0c4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -227,31 +227,48 @@ struct mesh_preq_queue {
227 u8 flags; 227 u8 flags;
228}; 228};
229 229
230enum ieee80211_mgd_state { 230enum ieee80211_work_type {
231 IEEE80211_MGD_STATE_INVALID, 231 IEEE80211_WORK_AUTH_PROBE,
232 IEEE80211_MGD_STATE_PROBE, 232 IEEE80211_WORK_AUTH,
233 IEEE80211_MGD_STATE_AUTH, 233 IEEE80211_WORK_ASSOC,
234 IEEE80211_MGD_STATE_ASSOC,
235}; 234};
236 235
237struct ieee80211_mgd_work { 236struct ieee80211_work {
238 struct list_head list; 237 struct list_head list;
239 struct ieee80211_bss *bss;
240 int ie_len;
241 u8 prev_bssid[ETH_ALEN];
242 u8 ssid[IEEE80211_MAX_SSID_LEN];
243 u8 ssid_len;
244 unsigned long timeout;
245 enum ieee80211_mgd_state state;
246 u16 auth_alg, auth_transaction;
247 238
248 int tries; 239 struct ieee80211_channel *chan;
240 /* XXX: chan type? -- right now not really needed */
241 unsigned long timeout;
242 enum ieee80211_work_type type;
249 243
250 u8 key[WLAN_KEY_LEN_WEP104]; 244 union {
251 u8 key_len, key_idx; 245 struct {
246 int tries;
247 u16 algorithm, transaction;
248 u8 ssid[IEEE80211_MAX_SSID_LEN];
249 u8 ssid_len;
250 u8 bssid[ETH_ALEN];
251 u8 key[WLAN_KEY_LEN_WEP104];
252 u8 key_len, key_idx;
253 bool privacy;
254 } auth;
255 struct {
256 struct ieee80211_bss *bss;
257 const u8 *supp_rates;
258 const u8 *ht_information_ie;
259 int tries;
260 u16 capability;
261 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
262 u8 ssid[IEEE80211_MAX_SSID_LEN];
263 u8 ssid_len;
264 u8 supp_rates_len;
265 bool wmm_used;
266 } assoc;
267 };
252 268
269 int ie_len;
253 /* must be last */ 270 /* must be last */
254 u8 ie[0]; /* for auth or assoc frame, not probe */ 271 u8 ie[0];
255}; 272};
256 273
257/* flags used in struct ieee80211_if_managed.flags */ 274/* flags used in struct ieee80211_if_managed.flags */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f060bc616203..c65225f29bb6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -125,15 +125,15 @@ static int ecw2cw(int ecw)
125 return (1 << ecw) - 1; 125 return (1 << ecw) - 1;
126} 126}
127 127
128static int ieee80211_compatible_rates(struct ieee80211_bss *bss, 128static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
129 struct ieee80211_supported_band *sband, 129 struct ieee80211_supported_band *sband,
130 u32 *rates) 130 u32 *rates)
131{ 131{
132 int i, j, count; 132 int i, j, count;
133 *rates = 0; 133 *rates = 0;
134 count = 0; 134 count = 0;
135 for (i = 0; i < bss->supp_rates_len; i++) { 135 for (i = 0; i < supp_rates_len; i++) {
136 int rate = (bss->supp_rates[i] & 0x7F) * 5; 136 int rate = (supp_rates[i] & 0x7F) * 5;
137 137
138 for (j = 0; j < sband->n_bitrates; j++) 138 for (j = 0; j < sband->n_bitrates; j++)
139 if (sband->bitrates[j].bitrate == rate) { 139 if (sband->bitrates[j].bitrate == rate) {
@@ -232,7 +232,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
232/* frame sending functions */ 232/* frame sending functions */
233 233
234static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, 234static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
235 struct ieee80211_mgd_work *wk) 235 struct ieee80211_work *wk)
236{ 236{
237 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 237 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
238 struct ieee80211_local *local = sdata->local; 238 struct ieee80211_local *local = sdata->local;
@@ -248,7 +248,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
248 248
249 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 249 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
250 sizeof(*mgmt) + 200 + wk->ie_len + 250 sizeof(*mgmt) + 200 + wk->ie_len +
251 wk->ssid_len); 251 wk->assoc.ssid_len);
252 if (!skb) { 252 if (!skb) {
253 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " 253 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
254 "frame\n", sdata->name); 254 "frame\n", sdata->name);
@@ -267,35 +267,37 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
267 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; 267 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
268 } 268 }
269 269
270 if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY) 270 if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY)
271 capab |= WLAN_CAPABILITY_PRIVACY; 271 capab |= WLAN_CAPABILITY_PRIVACY;
272 if (wk->bss->wmm_used) 272 if (wk->assoc.wmm_used)
273 wmm = 1; 273 wmm = 1;
274 274
275 /* get all rates supported by the device and the AP as 275 /* get all rates supported by the device and the AP as
276 * some APs don't like getting a superset of their rates 276 * some APs don't like getting a superset of their rates
277 * in the association request (e.g. D-Link DAP 1353 in 277 * in the association request (e.g. D-Link DAP 1353 in
278 * b-only mode) */ 278 * b-only mode) */
279 rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates); 279 rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates,
280 wk->assoc.supp_rates_len,
281 sband, &rates);
280 282
281 if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && 283 if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
282 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) 284 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
283 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; 285 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
284 286
285 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 287 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
286 memset(mgmt, 0, 24); 288 memset(mgmt, 0, 24);
287 memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); 289 memcpy(mgmt->da, wk->assoc.bssid, ETH_ALEN);
288 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 290 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
289 memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); 291 memcpy(mgmt->bssid, wk->assoc.bssid, ETH_ALEN);
290 292
291 if (!is_zero_ether_addr(wk->prev_bssid)) { 293 if (!is_zero_ether_addr(wk->assoc.prev_bssid)) {
292 skb_put(skb, 10); 294 skb_put(skb, 10);
293 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 295 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
294 IEEE80211_STYPE_REASSOC_REQ); 296 IEEE80211_STYPE_REASSOC_REQ);
295 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); 297 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
296 mgmt->u.reassoc_req.listen_interval = 298 mgmt->u.reassoc_req.listen_interval =
297 cpu_to_le16(local->hw.conf.listen_interval); 299 cpu_to_le16(local->hw.conf.listen_interval);
298 memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid, 300 memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid,
299 ETH_ALEN); 301 ETH_ALEN);
300 } else { 302 } else {
301 skb_put(skb, 4); 303 skb_put(skb, 4);
@@ -307,10 +309,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
307 } 309 }
308 310
309 /* SSID */ 311 /* SSID */
310 ies = pos = skb_put(skb, 2 + wk->ssid_len); 312 ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len);
311 *pos++ = WLAN_EID_SSID; 313 *pos++ = WLAN_EID_SSID;
312 *pos++ = wk->ssid_len; 314 *pos++ = wk->assoc.ssid_len;
313 memcpy(pos, wk->ssid, wk->ssid_len); 315 memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len);
314 316
315 /* add all rates which were marked to be used above */ 317 /* add all rates which were marked to be used above */
316 supp_rates_len = rates_len; 318 supp_rates_len = rates_len;
@@ -392,7 +394,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
392 */ 394 */
393 if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && 395 if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
394 sband->ht_cap.ht_supported && 396 sband->ht_cap.ht_supported &&
395 (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) && 397 (ht_ie = wk->assoc.ht_information_ie) &&
396 ht_ie[1] >= sizeof(struct ieee80211_ht_info) && 398 ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
397 (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) { 399 (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
398 struct ieee80211_ht_info *ht_info = 400 struct ieee80211_ht_info *ht_info =
@@ -1003,23 +1005,43 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1003 netif_carrier_on(sdata->dev); 1005 netif_carrier_on(sdata->dev);
1004} 1006}
1005 1007
1008static void ieee80211_remove_auth_bss(struct ieee80211_local *local,
1009 struct ieee80211_work *wk)
1010{
1011 struct cfg80211_bss *cbss;
1012 u16 capa_val = WLAN_CAPABILITY_ESS;
1013
1014 if (wk->auth.privacy)
1015 capa_val |= WLAN_CAPABILITY_PRIVACY;
1016
1017 cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->auth.bssid,
1018 wk->auth.ssid, wk->auth.ssid_len,
1019 WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
1020 capa_val);
1021 if (!cbss)
1022 return;
1023
1024 cfg80211_unlink_bss(local->hw.wiphy, cbss);
1025 cfg80211_put_bss(cbss);
1026}
1027
1006static enum rx_mgmt_action __must_check 1028static enum rx_mgmt_action __must_check
1007ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, 1029ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
1008 struct ieee80211_mgd_work *wk) 1030 struct ieee80211_work *wk)
1009{ 1031{
1010 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1032 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1011 struct ieee80211_local *local = sdata->local; 1033 struct ieee80211_local *local = sdata->local;
1012 1034
1013 wk->tries++; 1035 wk->auth.tries++;
1014 if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { 1036 if (wk->auth.tries > IEEE80211_AUTH_MAX_TRIES) {
1015 printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", 1037 printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
1016 sdata->name, wk->bss->cbss.bssid); 1038 sdata->name, wk->auth.bssid);
1017 1039
1018 /* 1040 /*
1019 * Most likely AP is not in the range so remove the 1041 * Most likely AP is not in the range so remove the
1020 * bss struct for that AP. 1042 * bss struct for that AP.
1021 */ 1043 */
1022 cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); 1044 ieee80211_remove_auth_bss(local, wk);
1023 1045
1024 /* 1046 /*
1025 * We might have a pending scan which had no chance to run yet 1047 * We might have a pending scan which had no chance to run yet
@@ -1031,14 +1053,14 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
1031 } 1053 }
1032 1054
1033 printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", 1055 printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
1034 sdata->name, wk->bss->cbss.bssid, 1056 sdata->name, wk->auth.bssid, wk->auth.tries);
1035 wk->tries);
1036 1057
1037 /* 1058 /*
1038 * Direct probe is sent to broadcast address as some APs 1059 * Direct probe is sent to broadcast address as some APs
1039 * will not answer to direct packet in unassociated state. 1060 * will not answer to direct packet in unassociated state.
1040 */ 1061 */
1041 ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); 1062 ieee80211_send_probe_req(sdata, NULL, wk->auth.ssid, wk->auth.ssid_len,
1063 NULL, 0);
1042 1064
1043 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 1065 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
1044 run_again(ifmgd, wk->timeout); 1066 run_again(ifmgd, wk->timeout);
@@ -1049,22 +1071,21 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
1049 1071
1050static enum rx_mgmt_action __must_check 1072static enum rx_mgmt_action __must_check
1051ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, 1073ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
1052 struct ieee80211_mgd_work *wk) 1074 struct ieee80211_work *wk)
1053{ 1075{
1054 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1076 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1055 struct ieee80211_local *local = sdata->local; 1077 struct ieee80211_local *local = sdata->local;
1056 1078
1057 wk->tries++; 1079 wk->auth.tries++;
1058 if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { 1080 if (wk->auth.tries > IEEE80211_AUTH_MAX_TRIES) {
1059 printk(KERN_DEBUG "%s: authentication with AP %pM" 1081 printk(KERN_DEBUG "%s: authentication with AP %pM"
1060 " timed out\n", 1082 " timed out\n", sdata->name, wk->auth.bssid);
1061 sdata->name, wk->bss->cbss.bssid);
1062 1083
1063 /* 1084 /*
1064 * Most likely AP is not in the range so remove the 1085 * Most likely AP is not in the range so remove the
1065 * bss struct for that AP. 1086 * bss struct for that AP.
1066 */ 1087 */
1067 cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); 1088 ieee80211_remove_auth_bss(local, wk);
1068 1089
1069 /* 1090 /*
1070 * We might have a pending scan which had no chance to run yet 1091 * We might have a pending scan which had no chance to run yet
@@ -1076,11 +1097,11 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
1076 } 1097 }
1077 1098
1078 printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", 1099 printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
1079 sdata->name, wk->bss->cbss.bssid, wk->tries); 1100 sdata->name, wk->auth.bssid, wk->auth.tries);
1080 1101
1081 ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, 1102 ieee80211_send_auth(sdata, 1, wk->auth.algorithm, wk->ie, wk->ie_len,
1082 wk->bss->cbss.bssid, NULL, 0, 0); 1103 wk->auth.bssid, NULL, 0, 0);
1083 wk->auth_transaction = 2; 1104 wk->auth.transaction = 2;
1084 1105
1085 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 1106 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
1086 run_again(ifmgd, wk->timeout); 1107 run_again(ifmgd, wk->timeout);
@@ -1176,22 +1197,22 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
1176 1197
1177static enum rx_mgmt_action __must_check 1198static enum rx_mgmt_action __must_check
1178ieee80211_associate(struct ieee80211_sub_if_data *sdata, 1199ieee80211_associate(struct ieee80211_sub_if_data *sdata,
1179 struct ieee80211_mgd_work *wk) 1200 struct ieee80211_work *wk)
1180{ 1201{
1181 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1202 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1182 struct ieee80211_local *local = sdata->local; 1203 struct ieee80211_local *local = sdata->local;
1183 1204
1184 wk->tries++; 1205 wk->assoc.tries++;
1185 if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { 1206 if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
1186 printk(KERN_DEBUG "%s: association with AP %pM" 1207 printk(KERN_DEBUG "%s: association with AP %pM"
1187 " timed out\n", 1208 " timed out\n",
1188 sdata->name, wk->bss->cbss.bssid); 1209 sdata->name, wk->assoc.bssid);
1189 1210
1190 /* 1211 /*
1191 * Most likely AP is not in the range so remove the 1212 * Most likely AP is not in the range so remove the
1192 * bss struct for that AP. 1213 * bss struct for that AP.
1193 */ 1214 */
1194 cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); 1215 cfg80211_unlink_bss(local->hw.wiphy, &wk->assoc.bss->cbss);
1195 1216
1196 /* 1217 /*
1197 * We might have a pending scan which had no chance to run yet 1218 * We might have a pending scan which had no chance to run yet
@@ -1203,7 +1224,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
1203 } 1224 }
1204 1225
1205 printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", 1226 printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
1206 sdata->name, wk->bss->cbss.bssid, wk->tries); 1227 sdata->name, wk->assoc.bssid, wk->assoc.tries);
1207 ieee80211_send_assoc(sdata, wk); 1228 ieee80211_send_assoc(sdata, wk);
1208 1229
1209 wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; 1230 wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
@@ -1318,7 +1339,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
1318EXPORT_SYMBOL(ieee80211_beacon_loss); 1339EXPORT_SYMBOL(ieee80211_beacon_loss);
1319 1340
1320static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, 1341static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
1321 struct ieee80211_mgd_work *wk) 1342 struct ieee80211_work *wk)
1322{ 1343{
1323 list_del(&wk->list); 1344 list_del(&wk->list);
1324 kfree(wk); 1345 kfree(wk);
@@ -1327,7 +1348,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
1327 1348
1328 1349
1329static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, 1350static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1330 struct ieee80211_mgd_work *wk, 1351 struct ieee80211_work *wk,
1331 struct ieee80211_mgmt *mgmt, 1352 struct ieee80211_mgmt *mgmt,
1332 size_t len) 1353 size_t len)
1333{ 1354{
@@ -1338,38 +1359,38 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1338 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); 1359 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1339 if (!elems.challenge) 1360 if (!elems.challenge)
1340 return; 1361 return;
1341 ieee80211_send_auth(sdata, 3, wk->auth_alg, 1362 ieee80211_send_auth(sdata, 3, wk->auth.algorithm,
1342 elems.challenge - 2, elems.challenge_len + 2, 1363 elems.challenge - 2, elems.challenge_len + 2,
1343 wk->bss->cbss.bssid, 1364 wk->auth.bssid, wk->auth.key, wk->auth.key_len,
1344 wk->key, wk->key_len, wk->key_idx); 1365 wk->auth.key_idx);
1345 wk->auth_transaction = 4; 1366 wk->auth.transaction = 4;
1346} 1367}
1347 1368
1348static enum rx_mgmt_action __must_check 1369static enum rx_mgmt_action __must_check
1349ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, 1370ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1350 struct ieee80211_mgd_work *wk, 1371 struct ieee80211_work *wk,
1351 struct ieee80211_mgmt *mgmt, size_t len) 1372 struct ieee80211_mgmt *mgmt, size_t len)
1352{ 1373{
1353 u16 auth_alg, auth_transaction, status_code; 1374 u16 auth_alg, auth_transaction, status_code;
1354 1375
1355 if (wk->state != IEEE80211_MGD_STATE_AUTH) 1376 if (wk->type != IEEE80211_WORK_AUTH)
1356 return RX_MGMT_NONE; 1377 return RX_MGMT_NONE;
1357 1378
1358 if (len < 24 + 6) 1379 if (len < 24 + 6)
1359 return RX_MGMT_NONE; 1380 return RX_MGMT_NONE;
1360 1381
1361 if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) 1382 if (memcmp(wk->auth.bssid, mgmt->sa, ETH_ALEN) != 0)
1362 return RX_MGMT_NONE; 1383 return RX_MGMT_NONE;
1363 1384
1364 if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) 1385 if (memcmp(wk->auth.bssid, mgmt->bssid, ETH_ALEN) != 0)
1365 return RX_MGMT_NONE; 1386 return RX_MGMT_NONE;
1366 1387
1367 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); 1388 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
1368 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); 1389 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
1369 status_code = le16_to_cpu(mgmt->u.auth.status_code); 1390 status_code = le16_to_cpu(mgmt->u.auth.status_code);
1370 1391
1371 if (auth_alg != wk->auth_alg || 1392 if (auth_alg != wk->auth.algorithm ||
1372 auth_transaction != wk->auth_transaction) 1393 auth_transaction != wk->auth.transaction)
1373 return RX_MGMT_NONE; 1394 return RX_MGMT_NONE;
1374 1395
1375 if (status_code != WLAN_STATUS_SUCCESS) { 1396 if (status_code != WLAN_STATUS_SUCCESS) {
@@ -1378,14 +1399,14 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1378 return RX_MGMT_CFG80211_AUTH; 1399 return RX_MGMT_CFG80211_AUTH;
1379 } 1400 }
1380 1401
1381 switch (wk->auth_alg) { 1402 switch (wk->auth.algorithm) {
1382 case WLAN_AUTH_OPEN: 1403 case WLAN_AUTH_OPEN:
1383 case WLAN_AUTH_LEAP: 1404 case WLAN_AUTH_LEAP:
1384 case WLAN_AUTH_FT: 1405 case WLAN_AUTH_FT:
1385 ieee80211_auth_completed(sdata, wk); 1406 ieee80211_auth_completed(sdata, wk);
1386 return RX_MGMT_CFG80211_AUTH; 1407 return RX_MGMT_CFG80211_AUTH;
1387 case WLAN_AUTH_SHARED_KEY: 1408 case WLAN_AUTH_SHARED_KEY:
1388 if (wk->auth_transaction == 4) { 1409 if (wk->auth.transaction == 4) {
1389 ieee80211_auth_completed(sdata, wk); 1410 ieee80211_auth_completed(sdata, wk);
1390 return RX_MGMT_CFG80211_AUTH; 1411 return RX_MGMT_CFG80211_AUTH;
1391 } else 1412 } else
@@ -1455,7 +1476,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1455 1476
1456static enum rx_mgmt_action __must_check 1477static enum rx_mgmt_action __must_check
1457ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, 1478ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1458 struct ieee80211_mgd_work *wk, 1479 struct ieee80211_work *wk,
1459 struct ieee80211_mgmt *mgmt, size_t len, 1480 struct ieee80211_mgmt *mgmt, size_t len,
1460 bool reassoc) 1481 bool reassoc)
1461{ 1482{
@@ -1463,7 +1484,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1463 struct ieee80211_local *local = sdata->local; 1484 struct ieee80211_local *local = sdata->local;
1464 struct ieee80211_supported_band *sband; 1485 struct ieee80211_supported_band *sband;
1465 struct sta_info *sta; 1486 struct sta_info *sta;
1466 struct ieee80211_bss *bss = wk->bss; 1487 struct ieee80211_bss *bss = wk->assoc.bss;
1467 u32 rates, basic_rates; 1488 u32 rates, basic_rates;
1468 u16 capab_info, status_code, aid; 1489 u16 capab_info, status_code, aid;
1469 struct ieee802_11_elems elems; 1490 struct ieee802_11_elems elems;
@@ -1693,7 +1714,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1693 1714
1694 1715
1695static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, 1716static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1696 struct ieee80211_mgd_work *wk, 1717 struct ieee80211_work *wk,
1697 struct ieee80211_mgmt *mgmt, size_t len, 1718 struct ieee80211_mgmt *mgmt, size_t len,
1698 struct ieee80211_rx_status *rx_status) 1719 struct ieee80211_rx_status *rx_status)
1699{ 1720{
@@ -1718,11 +1739,11 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1718 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); 1739 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1719 1740
1720 /* direct probe may be part of the association flow */ 1741 /* direct probe may be part of the association flow */
1721 if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { 1742 if (wk && wk->type == IEEE80211_WORK_AUTH_PROBE) {
1722 printk(KERN_DEBUG "%s: direct probe responded\n", 1743 printk(KERN_DEBUG "%s: direct probe responded\n",
1723 sdata->name); 1744 sdata->name);
1724 wk->tries = 0; 1745 wk->auth.tries = 0;
1725 wk->state = IEEE80211_MGD_STATE_AUTH; 1746 wk->type = IEEE80211_WORK_AUTH;
1726 WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); 1747 WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
1727 } 1748 }
1728 1749
@@ -1959,7 +1980,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1959 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1980 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1960 struct ieee80211_rx_status *rx_status; 1981 struct ieee80211_rx_status *rx_status;
1961 struct ieee80211_mgmt *mgmt; 1982 struct ieee80211_mgmt *mgmt;
1962 struct ieee80211_mgd_work *wk; 1983 struct ieee80211_work *wk;
1963 enum rx_mgmt_action rma = RX_MGMT_NONE; 1984 enum rx_mgmt_action rma = RX_MGMT_NONE;
1964 u16 fc; 1985 u16 fc;
1965 1986
@@ -2013,7 +2034,20 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
2013 } 2034 }
2014 2035
2015 list_for_each_entry(wk, &ifmgd->work_list, list) { 2036 list_for_each_entry(wk, &ifmgd->work_list, list) {
2016 if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) 2037 const u8 *bssid = NULL;
2038
2039 switch (wk->type) {
2040 case IEEE80211_WORK_AUTH_PROBE:
2041 case IEEE80211_WORK_AUTH:
2042 bssid = wk->auth.bssid;
2043 break;
2044 case IEEE80211_WORK_ASSOC:
2045 bssid = wk->assoc.bssid;
2046 break;
2047 default:
2048 continue;
2049 }
2050 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
2017 continue; 2051 continue;
2018 2052
2019 switch (fc & IEEE80211_FCTL_STYPE) { 2053 switch (fc & IEEE80211_FCTL_STYPE) {
@@ -2108,7 +2142,7 @@ static void ieee80211_sta_work(struct work_struct *work)
2108 struct ieee80211_local *local = sdata->local; 2142 struct ieee80211_local *local = sdata->local;
2109 struct ieee80211_if_managed *ifmgd; 2143 struct ieee80211_if_managed *ifmgd;
2110 struct sk_buff *skb; 2144 struct sk_buff *skb;
2111 struct ieee80211_mgd_work *wk, *tmp; 2145 struct ieee80211_work *wk, *tmp;
2112 LIST_HEAD(free_work); 2146 LIST_HEAD(free_work);
2113 enum rx_mgmt_action rma; 2147 enum rx_mgmt_action rma;
2114 2148
@@ -2194,19 +2228,19 @@ static void ieee80211_sta_work(struct work_struct *work)
2194 continue; 2228 continue;
2195 } 2229 }
2196 2230
2197 switch (wk->state) { 2231 switch (wk->type) {
2198 default: 2232 default:
2199 WARN_ON(1); 2233 WARN_ON(1);
2200 /* nothing */ 2234 /* nothing */
2201 rma = RX_MGMT_NONE; 2235 rma = RX_MGMT_NONE;
2202 break; 2236 break;
2203 case IEEE80211_MGD_STATE_PROBE: 2237 case IEEE80211_WORK_AUTH_PROBE:
2204 rma = ieee80211_direct_probe(sdata, wk); 2238 rma = ieee80211_direct_probe(sdata, wk);
2205 break; 2239 break;
2206 case IEEE80211_MGD_STATE_AUTH: 2240 case IEEE80211_WORK_AUTH:
2207 rma = ieee80211_authenticate(sdata, wk); 2241 rma = ieee80211_authenticate(sdata, wk);
2208 break; 2242 break;
2209 case IEEE80211_MGD_STATE_ASSOC: 2243 case IEEE80211_WORK_ASSOC:
2210 rma = ieee80211_associate(sdata, wk); 2244 rma = ieee80211_associate(sdata, wk);
2211 break; 2245 break;
2212 } 2246 }
@@ -2243,12 +2277,11 @@ static void ieee80211_sta_work(struct work_struct *work)
2243 /* see above how we're using wk->timeout */ 2277 /* see above how we're using wk->timeout */
2244 switch (wk->timeout) { 2278 switch (wk->timeout) {
2245 case RX_MGMT_CFG80211_AUTH_TO: 2279 case RX_MGMT_CFG80211_AUTH_TO:
2246 cfg80211_send_auth_timeout(sdata->dev, 2280 cfg80211_send_auth_timeout(sdata->dev, wk->auth.bssid);
2247 wk->bss->cbss.bssid);
2248 break; 2281 break;
2249 case RX_MGMT_CFG80211_ASSOC_TO: 2282 case RX_MGMT_CFG80211_ASSOC_TO:
2250 cfg80211_send_assoc_timeout(sdata->dev, 2283 cfg80211_send_assoc_timeout(sdata->dev,
2251 wk->bss->cbss.bssid); 2284 wk->assoc.bssid);
2252 break; 2285 break;
2253 default: 2286 default:
2254 WARN(1, "unexpected: %lu", wk->timeout); 2287 WARN(1, "unexpected: %lu", wk->timeout);
@@ -2415,7 +2448,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2415{ 2448{
2416 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2449 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2417 const u8 *ssid; 2450 const u8 *ssid;
2418 struct ieee80211_mgd_work *wk; 2451 struct ieee80211_work *wk;
2419 u16 auth_alg; 2452 u16 auth_alg;
2420 2453
2421 switch (req->auth_type) { 2454 switch (req->auth_type) {
@@ -2439,7 +2472,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2439 if (!wk) 2472 if (!wk)
2440 return -ENOMEM; 2473 return -ENOMEM;
2441 2474
2442 wk->bss = (void *)req->bss; 2475 memcpy(wk->auth.bssid, req->bss->bssid, ETH_ALEN);;
2443 2476
2444 if (req->ie && req->ie_len) { 2477 if (req->ie && req->ie_len) {
2445 memcpy(wk->ie, req->ie, req->ie_len); 2478 memcpy(wk->ie, req->ie, req->ie_len);
@@ -2447,22 +2480,27 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2447 } 2480 }
2448 2481
2449 if (req->key && req->key_len) { 2482 if (req->key && req->key_len) {
2450 wk->key_len = req->key_len; 2483 wk->auth.key_len = req->key_len;
2451 wk->key_idx = req->key_idx; 2484 wk->auth.key_idx = req->key_idx;
2452 memcpy(wk->key, req->key, req->key_len); 2485 memcpy(wk->auth.key, req->key, req->key_len);
2453 } 2486 }
2454 2487
2455 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); 2488 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
2456 memcpy(wk->ssid, ssid + 2, ssid[1]); 2489 memcpy(wk->auth.ssid, ssid + 2, ssid[1]);
2457 wk->ssid_len = ssid[1]; 2490 wk->auth.ssid_len = ssid[1];
2491
2492 wk->auth.algorithm = auth_alg;
2493 wk->auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY;
2458 2494
2459 wk->state = IEEE80211_MGD_STATE_PROBE; 2495 wk->type = IEEE80211_WORK_AUTH_PROBE;
2460 wk->auth_alg = auth_alg;
2461 wk->timeout = jiffies; /* run right away */ 2496 wk->timeout = jiffies; /* run right away */
2497 wk->chan = req->bss->channel;
2462 2498
2463 /* 2499 /*
2464 * XXX: if still associated need to tell AP that we're going 2500 * XXX: if still associated need to tell AP that we're going
2465 * to sleep and then change channel etc. 2501 * to sleep and then change channel etc.
2502 * For now switch channel here, later will be handled
2503 * by submitting this as an off-channel work item.
2466 */ 2504 */
2467 sdata->local->oper_channel = req->bss->channel; 2505 sdata->local->oper_channel = req->bss->channel;
2468 ieee80211_hw_config(sdata->local, 0); 2506 ieee80211_hw_config(sdata->local, 0);
@@ -2479,7 +2517,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2479 struct cfg80211_assoc_request *req) 2517 struct cfg80211_assoc_request *req)
2480{ 2518{
2481 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2519 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2482 struct ieee80211_mgd_work *wk; 2520 struct ieee80211_work *wk;
2483 const u8 *ssid; 2521 const u8 *ssid;
2484 int i, err; 2522 int i, err;
2485 2523
@@ -2506,17 +2544,27 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2506 } else 2544 } else
2507 wk->ie_len = 0; 2545 wk->ie_len = 0;
2508 2546
2509 wk->bss = (void *)req->bss; 2547 wk->assoc.bss = (void *)req->bss;
2548
2549 memcpy(wk->assoc.bssid, req->bss->bssid, ETH_ALEN);
2550
2551 wk->assoc.capability = req->bss->capability;
2552 wk->assoc.wmm_used = wk->assoc.bss->wmm_used;
2553 wk->assoc.supp_rates = wk->assoc.bss->supp_rates;
2554 wk->assoc.supp_rates_len = wk->assoc.bss->supp_rates_len;
2555 wk->assoc.ht_information_ie =
2556 ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION);
2510 2557
2511 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); 2558 ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
2512 memcpy(wk->ssid, ssid + 2, ssid[1]); 2559 memcpy(wk->assoc.ssid, ssid + 2, ssid[1]);
2513 wk->ssid_len = ssid[1]; 2560 wk->assoc.ssid_len = ssid[1];
2514 2561
2515 if (req->prev_bssid) 2562 if (req->prev_bssid)
2516 memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN); 2563 memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
2517 2564
2518 wk->state = IEEE80211_MGD_STATE_ASSOC; 2565 wk->type = IEEE80211_WORK_ASSOC;
2519 wk->timeout = jiffies; /* run right away */ 2566 wk->timeout = jiffies; /* run right away */
2567 wk->chan = req->bss->channel;
2520 2568
2521 if (req->use_mfp) { 2569 if (req->use_mfp) {
2522 ifmgd->mfp = IEEE80211_MFP_REQUIRED; 2570 ifmgd->mfp = IEEE80211_MFP_REQUIRED;
@@ -2549,7 +2597,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2549 void *cookie) 2597 void *cookie)
2550{ 2598{
2551 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2599 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2552 struct ieee80211_mgd_work *wk; 2600 struct ieee80211_work *wk;
2553 const u8 *bssid = req->bss->bssid; 2601 const u8 *bssid = req->bss->bssid;
2554 bool not_auth_yet = false; 2602 bool not_auth_yet = false;
2555 2603
@@ -2559,9 +2607,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2559 bssid = req->bss->bssid; 2607 bssid = req->bss->bssid;
2560 ieee80211_set_disassoc(sdata); 2608 ieee80211_set_disassoc(sdata);
2561 } else list_for_each_entry(wk, &ifmgd->work_list, list) { 2609 } else list_for_each_entry(wk, &ifmgd->work_list, list) {
2562 if (wk->state != IEEE80211_MGD_STATE_PROBE) 2610 if (wk->type != IEEE80211_WORK_AUTH_PROBE)
2563 continue; 2611 continue;
2564 if (req->bss != &wk->bss->cbss) 2612 if (memcmp(req->bss->bssid, wk->auth.bssid, ETH_ALEN))
2565 continue; 2613 continue;
2566 not_auth_yet = true; 2614 not_auth_yet = true;
2567 list_del(&wk->list); 2615 list_del(&wk->list);