aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-08 11:44:22 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-11 15:53:36 -0400
commit60f8b39c9406752ea5e0d3bbf5df6f903d61cacf (patch)
treec8884076f32b0533579efb171fe6f1e6f2a6d906 /net
parent24e64622c3f3143c801850897ab0cea8f3c69445 (diff)
mac80211: reorder mlme code
This reorders the mlme code a bit so we don't need all the forward function declarations. It also removes the ERP_INFO_USE_PROTECTION define that is unused, but otherwise contains no real changes. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/mlme.c1030
1 files changed, 500 insertions, 530 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d889e2a89e4b..67c38235a3c5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -26,9 +26,8 @@
26#include <linux/etherdevice.h> 26#include <linux/etherdevice.h>
27#include <linux/rtnetlink.h> 27#include <linux/rtnetlink.h>
28#include <net/iw_handler.h> 28#include <net/iw_handler.h>
29#include <asm/types.h>
30
31#include <net/mac80211.h> 29#include <net/mac80211.h>
30
32#include "ieee80211_i.h" 31#include "ieee80211_i.h"
33#include "rate.h" 32#include "rate.h"
34#include "led.h" 33#include "led.h"
@@ -58,8 +57,6 @@
58#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 57#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
59 58
60 59
61#define ERP_INFO_USE_PROTECTION BIT(1)
62
63/* mgmt header + 1 byte category code */ 60/* mgmt header + 1 byte category code */
64#define IEEE80211_MIN_ACTION_SIZE (24 + 1) 61#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
65 62
@@ -74,24 +71,199 @@
74#define IEEE80211_MIN_AMPDU_BUF 0x8 71#define IEEE80211_MIN_AMPDU_BUF 0x8
75#define IEEE80211_MAX_AMPDU_BUF 0x40 72#define IEEE80211_MAX_AMPDU_BUF 0x40
76 73
77static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 74/* BSS handling */
78 u8 *ssid, size_t ssid_len);
79static struct ieee80211_sta_bss * 75static struct ieee80211_sta_bss *
80ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, 76ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
81 u8 *ssid, u8 ssid_len); 77 u8 *ssid, u8 ssid_len)
78{
79 struct ieee80211_sta_bss *bss;
80
81 spin_lock_bh(&local->sta_bss_lock);
82 bss = local->sta_bss_hash[STA_HASH(bssid)];
83 while (bss) {
84 if (!bss_mesh_cfg(bss) &&
85 !memcmp(bss->bssid, bssid, ETH_ALEN) &&
86 bss->freq == freq &&
87 bss->ssid_len == ssid_len &&
88 (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
89 atomic_inc(&bss->users);
90 break;
91 }
92 bss = bss->hnext;
93 }
94 spin_unlock_bh(&local->sta_bss_lock);
95 return bss;
96}
97
98/* Caller must hold local->sta_bss_lock */
99static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
100 struct ieee80211_sta_bss *bss)
101{
102 u8 hash_idx;
103
104 if (bss_mesh_cfg(bss))
105 hash_idx = mesh_id_hash(bss_mesh_id(bss),
106 bss_mesh_id_len(bss));
107 else
108 hash_idx = STA_HASH(bss->bssid);
109
110 bss->hnext = local->sta_bss_hash[hash_idx];
111 local->sta_bss_hash[hash_idx] = bss;
112}
113
114/* Caller must hold local->sta_bss_lock */
115static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
116 struct ieee80211_sta_bss *bss)
117{
118 struct ieee80211_sta_bss *b, *prev = NULL;
119 b = local->sta_bss_hash[STA_HASH(bss->bssid)];
120 while (b) {
121 if (b == bss) {
122 if (!prev)
123 local->sta_bss_hash[STA_HASH(bss->bssid)] =
124 bss->hnext;
125 else
126 prev->hnext = bss->hnext;
127 break;
128 }
129 prev = b;
130 b = b->hnext;
131 }
132}
133
134static struct ieee80211_sta_bss *
135ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq,
136 u8 *ssid, u8 ssid_len)
137{
138 struct ieee80211_local *local = sdata->local;
139 struct ieee80211_sta_bss *bss;
140
141 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
142 if (!bss)
143 return NULL;
144 atomic_inc(&bss->users);
145 atomic_inc(&bss->users);
146 memcpy(bss->bssid, bssid, ETH_ALEN);
147 bss->freq = freq;
148 if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
149 memcpy(bss->ssid, ssid, ssid_len);
150 bss->ssid_len = ssid_len;
151 }
152
153 spin_lock_bh(&local->sta_bss_lock);
154 /* TODO: order by RSSI? */
155 list_add_tail(&bss->list, &local->sta_bss_list);
156 __ieee80211_rx_bss_hash_add(local, bss);
157 spin_unlock_bh(&local->sta_bss_lock);
158 return bss;
159}
160
161#ifdef CONFIG_MAC80211_MESH
162static struct ieee80211_sta_bss *
163ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
164 u8 *mesh_cfg, int freq)
165{
166 struct ieee80211_sta_bss *bss;
167
168 spin_lock_bh(&local->sta_bss_lock);
169 bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
170 while (bss) {
171 if (bss_mesh_cfg(bss) &&
172 !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
173 bss->freq == freq &&
174 mesh_id_len == bss->mesh_id_len &&
175 (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
176 mesh_id_len))) {
177 atomic_inc(&bss->users);
178 break;
179 }
180 bss = bss->hnext;
181 }
182 spin_unlock_bh(&local->sta_bss_lock);
183 return bss;
184}
185
186static struct ieee80211_sta_bss *
187ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
188 u8 *mesh_cfg, int mesh_config_len, int freq)
189{
190 struct ieee80211_sta_bss *bss;
191
192 if (mesh_config_len != MESH_CFG_LEN)
193 return NULL;
194
195 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
196 if (!bss)
197 return NULL;
198
199 bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
200 if (!bss->mesh_cfg) {
201 kfree(bss);
202 return NULL;
203 }
204
205 if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
206 bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
207 if (!bss->mesh_id) {
208 kfree(bss->mesh_cfg);
209 kfree(bss);
210 return NULL;
211 }
212 memcpy(bss->mesh_id, mesh_id, mesh_id_len);
213 }
214
215 atomic_inc(&bss->users);
216 atomic_inc(&bss->users);
217 memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
218 bss->mesh_id_len = mesh_id_len;
219 bss->freq = freq;
220 spin_lock_bh(&local->sta_bss_lock);
221 /* TODO: order by RSSI? */
222 list_add_tail(&bss->list, &local->sta_bss_list);
223 __ieee80211_rx_bss_hash_add(local, bss);
224 spin_unlock_bh(&local->sta_bss_lock);
225 return bss;
226}
227#endif
228
229static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
230{
231 kfree(bss->ies);
232 kfree(bss_mesh_id(bss));
233 kfree(bss_mesh_cfg(bss));
234 kfree(bss);
235}
236
82static void ieee80211_rx_bss_put(struct ieee80211_local *local, 237static void ieee80211_rx_bss_put(struct ieee80211_local *local,
83 struct ieee80211_sta_bss *bss); 238 struct ieee80211_sta_bss *bss)
84static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, 239{
85 struct ieee80211_if_sta *ifsta); 240 local_bh_disable();
86static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata); 241 if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
87static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *sdata, 242 local_bh_enable();
88 u8 *ssid, size_t ssid_len); 243 return;
89static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, 244 }
90 struct ieee80211_if_sta *ifsta); 245
91static void sta_rx_agg_session_timer_expired(unsigned long data); 246 __ieee80211_rx_bss_hash_del(local, bss);
247 list_del(&bss->list);
248 spin_unlock_bh(&local->sta_bss_lock);
249 ieee80211_rx_bss_free(bss);
250}
92 251
252void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
253{
254 spin_lock_init(&local->sta_bss_lock);
255 INIT_LIST_HEAD(&local->sta_bss_list);
256}
93 257
94static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) 258void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
259{
260 struct ieee80211_sta_bss *bss, *tmp;
261
262 list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
263 ieee80211_rx_bss_put(local, bss);
264}
265
266static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie)
95{ 267{
96 u8 *end, *pos; 268 u8 *end, *pos;
97 269
@@ -111,13 +283,125 @@ static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie)
111 return NULL; 283 return NULL;
112} 284}
113 285
114 286/* utils */
115static int ecw2cw(int ecw) 287static int ecw2cw(int ecw)
116{ 288{
117 return (1 << ecw) - 1; 289 return (1 << ecw) - 1;
118} 290}
119 291
292/* frame sending functions */
293void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
294 int encrypt)
295{
296 skb->dev = sdata->local->mdev;
297 skb_set_mac_header(skb, 0);
298 skb_set_network_header(skb, 0);
299 skb_set_transport_header(skb, 0);
300
301 skb->iif = sdata->dev->ifindex;
302 skb->do_not_encrypt = !encrypt;
303
304 dev_queue_xmit(skb);
305}
306
307static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
308 struct ieee80211_if_sta *ifsta,
309 int transaction, u8 *extra, size_t extra_len,
310 int encrypt)
311{
312 struct ieee80211_local *local = sdata->local;
313 struct sk_buff *skb;
314 struct ieee80211_mgmt *mgmt;
120 315
316 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
317 sizeof(*mgmt) + 6 + extra_len);
318 if (!skb) {
319 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
320 "frame\n", sdata->dev->name);
321 return;
322 }
323 skb_reserve(skb, local->hw.extra_tx_headroom);
324
325 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
326 memset(mgmt, 0, 24 + 6);
327 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
328 IEEE80211_STYPE_AUTH);
329 if (encrypt)
330 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
331 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
332 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
333 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
334 mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
335 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
336 ifsta->auth_transaction = transaction + 1;
337 mgmt->u.auth.status_code = cpu_to_le16(0);
338 if (extra)
339 memcpy(skb_put(skb, extra_len), extra, extra_len);
340
341 ieee80211_sta_tx(sdata, skb, encrypt);
342}
343
344static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
345 u8 *ssid, size_t ssid_len)
346{
347 struct ieee80211_local *local = sdata->local;
348 struct ieee80211_supported_band *sband;
349 struct sk_buff *skb;
350 struct ieee80211_mgmt *mgmt;
351 u8 *pos, *supp_rates, *esupp_rates = NULL;
352 int i;
353
354 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
355 if (!skb) {
356 printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
357 "request\n", sdata->dev->name);
358 return;
359 }
360 skb_reserve(skb, local->hw.extra_tx_headroom);
361
362 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
363 memset(mgmt, 0, 24);
364 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
365 IEEE80211_STYPE_PROBE_REQ);
366 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
367 if (dst) {
368 memcpy(mgmt->da, dst, ETH_ALEN);
369 memcpy(mgmt->bssid, dst, ETH_ALEN);
370 } else {
371 memset(mgmt->da, 0xff, ETH_ALEN);
372 memset(mgmt->bssid, 0xff, ETH_ALEN);
373 }
374 pos = skb_put(skb, 2 + ssid_len);
375 *pos++ = WLAN_EID_SSID;
376 *pos++ = ssid_len;
377 memcpy(pos, ssid, ssid_len);
378
379 supp_rates = skb_put(skb, 2);
380 supp_rates[0] = WLAN_EID_SUPP_RATES;
381 supp_rates[1] = 0;
382 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
383
384 for (i = 0; i < sband->n_bitrates; i++) {
385 struct ieee80211_rate *rate = &sband->bitrates[i];
386 if (esupp_rates) {
387 pos = skb_put(skb, 1);
388 esupp_rates[1]++;
389 } else if (supp_rates[1] == 8) {
390 esupp_rates = skb_put(skb, 3);
391 esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
392 esupp_rates[1] = 1;
393 pos = &esupp_rates[2];
394 } else {
395 pos = skb_put(skb, 1);
396 supp_rates[1]++;
397 }
398 *pos = rate->bitrate / 5;
399 }
400
401 ieee80211_sta_tx(sdata, skb, 0);
402}
403
404/* MLME */
121static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, 405static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
122 struct ieee80211_sta_bss *bss, 406 struct ieee80211_sta_bss *bss,
123 int ibss) 407 int ibss)
@@ -434,58 +718,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
434 ieee80211_sta_send_apinfo(sdata, ifsta); 718 ieee80211_sta_send_apinfo(sdata, ifsta);
435} 719}
436 720
437void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
438 int encrypt)
439{
440 skb->dev = sdata->local->mdev;
441 skb_set_mac_header(skb, 0);
442 skb_set_network_header(skb, 0);
443 skb_set_transport_header(skb, 0);
444
445 skb->iif = sdata->dev->ifindex;
446 skb->do_not_encrypt = !encrypt;
447
448 dev_queue_xmit(skb);
449}
450
451
452static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
453 struct ieee80211_if_sta *ifsta,
454 int transaction, u8 *extra, size_t extra_len,
455 int encrypt)
456{
457 struct ieee80211_local *local = sdata->local;
458 struct sk_buff *skb;
459 struct ieee80211_mgmt *mgmt;
460
461 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
462 sizeof(*mgmt) + 6 + extra_len);
463 if (!skb) {
464 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
465 "frame\n", sdata->dev->name);
466 return;
467 }
468 skb_reserve(skb, local->hw.extra_tx_headroom);
469
470 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
471 memset(mgmt, 0, 24 + 6);
472 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
473 IEEE80211_STYPE_AUTH);
474 if (encrypt)
475 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
476 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
477 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
478 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
479 mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
480 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
481 ifsta->auth_transaction = transaction + 1;
482 mgmt->u.auth.status_code = cpu_to_le16(0);
483 if (extra)
484 memcpy(skb_put(skb, extra_len), extra, extra_len);
485
486 ieee80211_sta_tx(sdata, skb, encrypt);
487}
488
489static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, 721static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
490 struct ieee80211_if_sta *ifsta) 722 struct ieee80211_if_sta *ifsta)
491{ 723{
@@ -798,6 +1030,13 @@ static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata,
798 ieee80211_sta_tx(sdata, skb, 0); 1030 ieee80211_sta_tx(sdata, skb, 0);
799} 1031}
800 1032
1033static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
1034{
1035 if (!sdata || !sdata->default_key ||
1036 sdata->default_key->conf.alg != ALG_WEP)
1037 return 0;
1038 return 1;
1039}
801 1040
802static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, 1041static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata,
803 struct ieee80211_if_sta *ifsta, u16 reason) 1042 struct ieee80211_if_sta *ifsta, u16 reason)
@@ -917,7 +1156,6 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
917 return 1; 1156 return 1;
918} 1157}
919 1158
920
921static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, 1159static void ieee80211_associate(struct ieee80211_sub_if_data *sdata,
922 struct ieee80211_if_sta *ifsta) 1160 struct ieee80211_if_sta *ifsta)
923{ 1161{
@@ -1008,76 +1246,6 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata,
1008} 1246}
1009 1247
1010 1248
1011static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1012 u8 *ssid, size_t ssid_len)
1013{
1014 struct ieee80211_local *local = sdata->local;
1015 struct ieee80211_supported_band *sband;
1016 struct sk_buff *skb;
1017 struct ieee80211_mgmt *mgmt;
1018 u8 *pos, *supp_rates, *esupp_rates = NULL;
1019 int i;
1020
1021 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
1022 if (!skb) {
1023 printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
1024 "request\n", sdata->dev->name);
1025 return;
1026 }
1027 skb_reserve(skb, local->hw.extra_tx_headroom);
1028
1029 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
1030 memset(mgmt, 0, 24);
1031 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1032 IEEE80211_STYPE_PROBE_REQ);
1033 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
1034 if (dst) {
1035 memcpy(mgmt->da, dst, ETH_ALEN);
1036 memcpy(mgmt->bssid, dst, ETH_ALEN);
1037 } else {
1038 memset(mgmt->da, 0xff, ETH_ALEN);
1039 memset(mgmt->bssid, 0xff, ETH_ALEN);
1040 }
1041 pos = skb_put(skb, 2 + ssid_len);
1042 *pos++ = WLAN_EID_SSID;
1043 *pos++ = ssid_len;
1044 memcpy(pos, ssid, ssid_len);
1045
1046 supp_rates = skb_put(skb, 2);
1047 supp_rates[0] = WLAN_EID_SUPP_RATES;
1048 supp_rates[1] = 0;
1049 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1050
1051 for (i = 0; i < sband->n_bitrates; i++) {
1052 struct ieee80211_rate *rate = &sband->bitrates[i];
1053 if (esupp_rates) {
1054 pos = skb_put(skb, 1);
1055 esupp_rates[1]++;
1056 } else if (supp_rates[1] == 8) {
1057 esupp_rates = skb_put(skb, 3);
1058 esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
1059 esupp_rates[1] = 1;
1060 pos = &esupp_rates[2];
1061 } else {
1062 pos = skb_put(skb, 1);
1063 supp_rates[1]++;
1064 }
1065 *pos = rate->bitrate / 5;
1066 }
1067
1068 ieee80211_sta_tx(sdata, skb, 0);
1069}
1070
1071
1072static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
1073{
1074 if (!sdata || !sdata->default_key ||
1075 sdata->default_key->conf.alg != ALG_WEP)
1076 return 0;
1077 return 1;
1078}
1079
1080
1081static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, 1249static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
1082 struct ieee80211_if_sta *ifsta) 1250 struct ieee80211_if_sta *ifsta)
1083{ 1251{
@@ -1200,6 +1368,30 @@ void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8
1200 ieee80211_sta_tx(sdata, skb, 0); 1368 ieee80211_sta_tx(sdata, skb, 0);
1201} 1369}
1202 1370
1371/*
1372 * After accepting the AddBA Request we activated a timer,
1373 * resetting it after each frame that arrives from the originator.
1374 * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
1375 */
1376static void sta_rx_agg_session_timer_expired(unsigned long data)
1377{
1378 /* not an elegant detour, but there is no choice as the timer passes
1379 * only one argument, and various sta_info are needed here, so init
1380 * flow in sta_info_create gives the TID as data, while the timer_to_id
1381 * array gives the sta through container_of */
1382 u8 *ptid = (u8 *)data;
1383 u8 *timer_to_id = ptid - *ptid;
1384 struct sta_info *sta = container_of(timer_to_id, struct sta_info,
1385 timer_to_tid[0]);
1386
1387#ifdef CONFIG_MAC80211_HT_DEBUG
1388 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
1389#endif
1390 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr,
1391 (u16)*ptid, WLAN_BACK_TIMER,
1392 WLAN_REASON_QSTA_TIMEOUT);
1393}
1394
1203static void ieee80211_sta_process_addba_request(struct ieee80211_local *local, 1395static void ieee80211_sta_process_addba_request(struct ieee80211_local *local,
1204 struct ieee80211_mgmt *mgmt, 1396 struct ieee80211_mgmt *mgmt,
1205 size_t len) 1397 size_t len)
@@ -1646,30 +1838,6 @@ timer_expired_exit:
1646 rcu_read_unlock(); 1838 rcu_read_unlock();
1647} 1839}
1648 1840
1649/*
1650 * After accepting the AddBA Request we activated a timer,
1651 * resetting it after each frame that arrives from the originator.
1652 * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
1653 */
1654static void sta_rx_agg_session_timer_expired(unsigned long data)
1655{
1656 /* not an elegant detour, but there is no choice as the timer passes
1657 * only one argument, and various sta_info are needed here, so init
1658 * flow in sta_info_create gives the TID as data, while the timer_to_id
1659 * array gives the sta through container_of */
1660 u8 *ptid = (u8 *)data;
1661 u8 *timer_to_id = ptid - *ptid;
1662 struct sta_info *sta = container_of(timer_to_id, struct sta_info,
1663 timer_to_tid[0]);
1664
1665#ifdef CONFIG_MAC80211_HT_DEBUG
1666 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
1667#endif
1668 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr,
1669 (u16)*ptid, WLAN_BACK_TIMER,
1670 WLAN_REASON_QSTA_TIMEOUT);
1671}
1672
1673void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) 1841void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr)
1674{ 1842{
1675 struct ieee80211_local *local = sdata->local; 1843 struct ieee80211_local *local = sdata->local;
@@ -2099,203 +2267,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2099} 2267}
2100 2268
2101 2269
2102/* Caller must hold local->sta_bss_lock */
2103static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
2104 struct ieee80211_sta_bss *bss)
2105{
2106 u8 hash_idx;
2107
2108 if (bss_mesh_cfg(bss))
2109 hash_idx = mesh_id_hash(bss_mesh_id(bss),
2110 bss_mesh_id_len(bss));
2111 else
2112 hash_idx = STA_HASH(bss->bssid);
2113
2114 bss->hnext = local->sta_bss_hash[hash_idx];
2115 local->sta_bss_hash[hash_idx] = bss;
2116}
2117
2118
2119/* Caller must hold local->sta_bss_lock */
2120static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
2121 struct ieee80211_sta_bss *bss)
2122{
2123 struct ieee80211_sta_bss *b, *prev = NULL;
2124 b = local->sta_bss_hash[STA_HASH(bss->bssid)];
2125 while (b) {
2126 if (b == bss) {
2127 if (!prev)
2128 local->sta_bss_hash[STA_HASH(bss->bssid)] =
2129 bss->hnext;
2130 else
2131 prev->hnext = bss->hnext;
2132 break;
2133 }
2134 prev = b;
2135 b = b->hnext;
2136 }
2137}
2138
2139
2140static struct ieee80211_sta_bss *
2141ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq,
2142 u8 *ssid, u8 ssid_len)
2143{
2144 struct ieee80211_local *local = sdata->local;
2145 struct ieee80211_sta_bss *bss;
2146
2147 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
2148 if (!bss)
2149 return NULL;
2150 atomic_inc(&bss->users);
2151 atomic_inc(&bss->users);
2152 memcpy(bss->bssid, bssid, ETH_ALEN);
2153 bss->freq = freq;
2154 if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
2155 memcpy(bss->ssid, ssid, ssid_len);
2156 bss->ssid_len = ssid_len;
2157 }
2158
2159 spin_lock_bh(&local->sta_bss_lock);
2160 /* TODO: order by RSSI? */
2161 list_add_tail(&bss->list, &local->sta_bss_list);
2162 __ieee80211_rx_bss_hash_add(local, bss);
2163 spin_unlock_bh(&local->sta_bss_lock);
2164 return bss;
2165}
2166
2167static struct ieee80211_sta_bss *
2168ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
2169 u8 *ssid, u8 ssid_len)
2170{
2171 struct ieee80211_sta_bss *bss;
2172
2173 spin_lock_bh(&local->sta_bss_lock);
2174 bss = local->sta_bss_hash[STA_HASH(bssid)];
2175 while (bss) {
2176 if (!bss_mesh_cfg(bss) &&
2177 !memcmp(bss->bssid, bssid, ETH_ALEN) &&
2178 bss->freq == freq &&
2179 bss->ssid_len == ssid_len &&
2180 (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
2181 atomic_inc(&bss->users);
2182 break;
2183 }
2184 bss = bss->hnext;
2185 }
2186 spin_unlock_bh(&local->sta_bss_lock);
2187 return bss;
2188}
2189
2190#ifdef CONFIG_MAC80211_MESH
2191static struct ieee80211_sta_bss *
2192ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
2193 u8 *mesh_cfg, int freq)
2194{
2195 struct ieee80211_sta_bss *bss;
2196
2197 spin_lock_bh(&local->sta_bss_lock);
2198 bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
2199 while (bss) {
2200 if (bss_mesh_cfg(bss) &&
2201 !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
2202 bss->freq == freq &&
2203 mesh_id_len == bss->mesh_id_len &&
2204 (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
2205 mesh_id_len))) {
2206 atomic_inc(&bss->users);
2207 break;
2208 }
2209 bss = bss->hnext;
2210 }
2211 spin_unlock_bh(&local->sta_bss_lock);
2212 return bss;
2213}
2214
2215static struct ieee80211_sta_bss *
2216ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
2217 u8 *mesh_cfg, int mesh_config_len, int freq)
2218{
2219 struct ieee80211_sta_bss *bss;
2220
2221 if (mesh_config_len != MESH_CFG_LEN)
2222 return NULL;
2223
2224 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
2225 if (!bss)
2226 return NULL;
2227
2228 bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
2229 if (!bss->mesh_cfg) {
2230 kfree(bss);
2231 return NULL;
2232 }
2233
2234 if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
2235 bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
2236 if (!bss->mesh_id) {
2237 kfree(bss->mesh_cfg);
2238 kfree(bss);
2239 return NULL;
2240 }
2241 memcpy(bss->mesh_id, mesh_id, mesh_id_len);
2242 }
2243
2244 atomic_inc(&bss->users);
2245 atomic_inc(&bss->users);
2246 memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
2247 bss->mesh_id_len = mesh_id_len;
2248 bss->freq = freq;
2249 spin_lock_bh(&local->sta_bss_lock);
2250 /* TODO: order by RSSI? */
2251 list_add_tail(&bss->list, &local->sta_bss_list);
2252 __ieee80211_rx_bss_hash_add(local, bss);
2253 spin_unlock_bh(&local->sta_bss_lock);
2254 return bss;
2255}
2256#endif
2257
2258static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
2259{
2260 kfree(bss->ies);
2261 kfree(bss_mesh_id(bss));
2262 kfree(bss_mesh_cfg(bss));
2263 kfree(bss);
2264}
2265
2266
2267static void ieee80211_rx_bss_put(struct ieee80211_local *local,
2268 struct ieee80211_sta_bss *bss)
2269{
2270 local_bh_disable();
2271 if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
2272 local_bh_enable();
2273 return;
2274 }
2275
2276 __ieee80211_rx_bss_hash_del(local, bss);
2277 list_del(&bss->list);
2278 spin_unlock_bh(&local->sta_bss_lock);
2279 ieee80211_rx_bss_free(bss);
2280}
2281
2282
2283void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
2284{
2285 spin_lock_init(&local->sta_bss_lock);
2286 INIT_LIST_HEAD(&local->sta_bss_list);
2287}
2288
2289
2290void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
2291{
2292 struct ieee80211_sta_bss *bss, *tmp;
2293
2294 list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
2295 ieee80211_rx_bss_put(local, bss);
2296}
2297
2298
2299static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 2270static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
2300 struct ieee80211_if_sta *ifsta, 2271 struct ieee80211_if_sta *ifsta,
2301 struct ieee80211_sta_bss *bss) 2272 struct ieee80211_sta_bss *bss)
@@ -3154,95 +3125,6 @@ void ieee80211_sta_timer(unsigned long data)
3154 queue_work(local->hw.workqueue, &ifsta->work); 3125 queue_work(local->hw.workqueue, &ifsta->work);
3155} 3126}
3156 3127
3157void ieee80211_sta_work(struct work_struct *work)
3158{
3159 struct ieee80211_sub_if_data *sdata =
3160 container_of(work, struct ieee80211_sub_if_data, u.sta.work);
3161 struct ieee80211_local *local = sdata->local;
3162 struct ieee80211_if_sta *ifsta;
3163 struct sk_buff *skb;
3164
3165 if (!netif_running(sdata->dev))
3166 return;
3167
3168 if (local->sta_sw_scanning || local->sta_hw_scanning)
3169 return;
3170
3171 if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA &&
3172 sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
3173 sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
3174 return;
3175 ifsta = &sdata->u.sta;
3176
3177 while ((skb = skb_dequeue(&ifsta->skb_queue)))
3178 ieee80211_sta_rx_queued_mgmt(sdata, skb);
3179
3180#ifdef CONFIG_MAC80211_MESH
3181 if (ifsta->preq_queue_len &&
3182 time_after(jiffies,
3183 ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
3184 mesh_path_start_discovery(sdata);
3185#endif
3186
3187 if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
3188 ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
3189 ifsta->state != IEEE80211_STA_MLME_ASSOCIATE &&
3190 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
3191 if (ifsta->scan_ssid_len)
3192 ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len);
3193 else
3194 ieee80211_sta_start_scan(sdata, NULL, 0);
3195 return;
3196 }
3197
3198 if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
3199 if (ieee80211_sta_config_auth(sdata, ifsta))
3200 return;
3201 clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
3202 } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
3203 return;
3204
3205 switch (ifsta->state) {
3206 case IEEE80211_STA_MLME_DISABLED:
3207 break;
3208 case IEEE80211_STA_MLME_DIRECT_PROBE:
3209 ieee80211_direct_probe(sdata, ifsta);
3210 break;
3211 case IEEE80211_STA_MLME_AUTHENTICATE:
3212 ieee80211_authenticate(sdata, ifsta);
3213 break;
3214 case IEEE80211_STA_MLME_ASSOCIATE:
3215 ieee80211_associate(sdata, ifsta);
3216 break;
3217 case IEEE80211_STA_MLME_ASSOCIATED:
3218 ieee80211_associated(sdata, ifsta);
3219 break;
3220 case IEEE80211_STA_MLME_IBSS_SEARCH:
3221 ieee80211_sta_find_ibss(sdata, ifsta);
3222 break;
3223 case IEEE80211_STA_MLME_IBSS_JOINED:
3224 ieee80211_sta_merge_ibss(sdata, ifsta);
3225 break;
3226#ifdef CONFIG_MAC80211_MESH
3227 case IEEE80211_STA_MLME_MESH_UP:
3228 ieee80211_mesh_housekeeping(sdata, ifsta);
3229 break;
3230#endif
3231 default:
3232 WARN_ON(1);
3233 break;
3234 }
3235
3236 if (ieee80211_privacy_mismatch(sdata, ifsta)) {
3237 printk(KERN_DEBUG "%s: privacy configuration mismatch and "
3238 "mixed-cell disabled - disassociate\n", sdata->dev->name);
3239
3240 ieee80211_set_disassoc(sdata, ifsta, false, true,
3241 WLAN_REASON_UNSPECIFIED);
3242 }
3243}
3244
3245
3246static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, 3128static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata,
3247 struct ieee80211_if_sta *ifsta) 3129 struct ieee80211_if_sta *ifsta)
3248{ 3130{
@@ -3327,85 +3209,6 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
3327 return 0; 3209 return 0;
3328} 3210}
3329 3211
3330static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
3331 struct ieee80211_if_sta *ifsta)
3332{
3333 struct ieee80211_local *local = sdata->local;
3334 struct ieee80211_sta_bss *bss, *selected = NULL;
3335 int top_rssi = 0, freq;
3336
3337 spin_lock_bh(&local->sta_bss_lock);
3338 freq = local->oper_channel->center_freq;
3339 list_for_each_entry(bss, &local->sta_bss_list, list) {
3340 if (!(bss->capability & WLAN_CAPABILITY_ESS))
3341 continue;
3342
3343 if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
3344 IEEE80211_STA_AUTO_BSSID_SEL |
3345 IEEE80211_STA_AUTO_CHANNEL_SEL)) &&
3346 (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
3347 !!sdata->default_key))
3348 continue;
3349
3350 if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
3351 bss->freq != freq)
3352 continue;
3353
3354 if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
3355 memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
3356 continue;
3357
3358 if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
3359 !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
3360 continue;
3361
3362 if (!selected || top_rssi < bss->signal) {
3363 selected = bss;
3364 top_rssi = bss->signal;
3365 }
3366 }
3367 if (selected)
3368 atomic_inc(&selected->users);
3369 spin_unlock_bh(&local->sta_bss_lock);
3370
3371 if (selected) {
3372 ieee80211_set_freq(sdata, selected->freq);
3373 if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
3374 ieee80211_sta_set_ssid(sdata, selected->ssid,
3375 selected->ssid_len);
3376 ieee80211_sta_set_bssid(sdata, selected->bssid);
3377 ieee80211_sta_def_wmm_params(sdata, selected, 0);
3378
3379 /* Send out direct probe if no probe resp was received or
3380 * the one we have is outdated
3381 */
3382 if (!selected->last_probe_resp ||
3383 time_after(jiffies, selected->last_probe_resp
3384 + IEEE80211_SCAN_RESULT_EXPIRE))
3385 ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
3386 else
3387 ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
3388
3389 ieee80211_rx_bss_put(local, selected);
3390 ieee80211_sta_reset_auth(sdata, ifsta);
3391 return 0;
3392 } else {
3393 if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
3394 ifsta->assoc_scan_tries++;
3395 if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
3396 ieee80211_sta_start_scan(sdata, NULL, 0);
3397 else
3398 ieee80211_sta_start_scan(sdata, ifsta->ssid,
3399 ifsta->ssid_len);
3400 ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
3401 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
3402 } else
3403 ifsta->state = IEEE80211_STA_MLME_DISABLED;
3404 }
3405 return -1;
3406}
3407
3408
3409static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, 3212static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
3410 struct ieee80211_if_sta *ifsta) 3213 struct ieee80211_if_sta *ifsta)
3411{ 3214{
@@ -4273,6 +4076,85 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
4273} 4076}
4274 4077
4275 4078
4079static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
4080 struct ieee80211_if_sta *ifsta)
4081{
4082 struct ieee80211_local *local = sdata->local;
4083 struct ieee80211_sta_bss *bss, *selected = NULL;
4084 int top_rssi = 0, freq;
4085
4086 spin_lock_bh(&local->sta_bss_lock);
4087 freq = local->oper_channel->center_freq;
4088 list_for_each_entry(bss, &local->sta_bss_list, list) {
4089 if (!(bss->capability & WLAN_CAPABILITY_ESS))
4090 continue;
4091
4092 if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
4093 IEEE80211_STA_AUTO_BSSID_SEL |
4094 IEEE80211_STA_AUTO_CHANNEL_SEL)) &&
4095 (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
4096 !!sdata->default_key))
4097 continue;
4098
4099 if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
4100 bss->freq != freq)
4101 continue;
4102
4103 if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
4104 memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
4105 continue;
4106
4107 if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
4108 !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
4109 continue;
4110
4111 if (!selected || top_rssi < bss->signal) {
4112 selected = bss;
4113 top_rssi = bss->signal;
4114 }
4115 }
4116 if (selected)
4117 atomic_inc(&selected->users);
4118 spin_unlock_bh(&local->sta_bss_lock);
4119
4120 if (selected) {
4121 ieee80211_set_freq(sdata, selected->freq);
4122 if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
4123 ieee80211_sta_set_ssid(sdata, selected->ssid,
4124 selected->ssid_len);
4125 ieee80211_sta_set_bssid(sdata, selected->bssid);
4126 ieee80211_sta_def_wmm_params(sdata, selected, 0);
4127
4128 /* Send out direct probe if no probe resp was received or
4129 * the one we have is outdated
4130 */
4131 if (!selected->last_probe_resp ||
4132 time_after(jiffies, selected->last_probe_resp
4133 + IEEE80211_SCAN_RESULT_EXPIRE))
4134 ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
4135 else
4136 ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
4137
4138 ieee80211_rx_bss_put(local, selected);
4139 ieee80211_sta_reset_auth(sdata, ifsta);
4140 return 0;
4141 } else {
4142 if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
4143 ifsta->assoc_scan_tries++;
4144 if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
4145 ieee80211_sta_start_scan(sdata, NULL, 0);
4146 else
4147 ieee80211_sta_start_scan(sdata, ifsta->ssid,
4148 ifsta->ssid_len);
4149 ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
4150 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
4151 } else
4152 ifsta->state = IEEE80211_STA_MLME_DISABLED;
4153 }
4154 return -1;
4155}
4156
4157
4276int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) 4158int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
4277{ 4159{
4278 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 4160 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
@@ -4326,3 +4208,91 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw,
4326 } 4208 }
4327} 4209}
4328EXPORT_SYMBOL(ieee80211_notify_mac); 4210EXPORT_SYMBOL(ieee80211_notify_mac);
4211
4212void ieee80211_sta_work(struct work_struct *work)
4213{
4214 struct ieee80211_sub_if_data *sdata =
4215 container_of(work, struct ieee80211_sub_if_data, u.sta.work);
4216 struct ieee80211_local *local = sdata->local;
4217 struct ieee80211_if_sta *ifsta;
4218 struct sk_buff *skb;
4219
4220 if (!netif_running(sdata->dev))
4221 return;
4222
4223 if (local->sta_sw_scanning || local->sta_hw_scanning)
4224 return;
4225
4226 if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA &&
4227 sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
4228 sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
4229 return;
4230 ifsta = &sdata->u.sta;
4231
4232 while ((skb = skb_dequeue(&ifsta->skb_queue)))
4233 ieee80211_sta_rx_queued_mgmt(sdata, skb);
4234
4235#ifdef CONFIG_MAC80211_MESH
4236 if (ifsta->preq_queue_len &&
4237 time_after(jiffies,
4238 ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
4239 mesh_path_start_discovery(sdata);
4240#endif
4241
4242 if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
4243 ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
4244 ifsta->state != IEEE80211_STA_MLME_ASSOCIATE &&
4245 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
4246 if (ifsta->scan_ssid_len)
4247 ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len);
4248 else
4249 ieee80211_sta_start_scan(sdata, NULL, 0);
4250 return;
4251 }
4252
4253 if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
4254 if (ieee80211_sta_config_auth(sdata, ifsta))
4255 return;
4256 clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
4257 } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
4258 return;
4259
4260 switch (ifsta->state) {
4261 case IEEE80211_STA_MLME_DISABLED:
4262 break;
4263 case IEEE80211_STA_MLME_DIRECT_PROBE:
4264 ieee80211_direct_probe(sdata, ifsta);
4265 break;
4266 case IEEE80211_STA_MLME_AUTHENTICATE:
4267 ieee80211_authenticate(sdata, ifsta);
4268 break;
4269 case IEEE80211_STA_MLME_ASSOCIATE:
4270 ieee80211_associate(sdata, ifsta);
4271 break;
4272 case IEEE80211_STA_MLME_ASSOCIATED:
4273 ieee80211_associated(sdata, ifsta);
4274 break;
4275 case IEEE80211_STA_MLME_IBSS_SEARCH:
4276 ieee80211_sta_find_ibss(sdata, ifsta);
4277 break;
4278 case IEEE80211_STA_MLME_IBSS_JOINED:
4279 ieee80211_sta_merge_ibss(sdata, ifsta);
4280 break;
4281#ifdef CONFIG_MAC80211_MESH
4282 case IEEE80211_STA_MLME_MESH_UP:
4283 ieee80211_mesh_housekeeping(sdata, ifsta);
4284 break;
4285#endif
4286 default:
4287 WARN_ON(1);
4288 break;
4289 }
4290
4291 if (ieee80211_privacy_mismatch(sdata, ifsta)) {
4292 printk(KERN_DEBUG "%s: privacy configuration mismatch and "
4293 "mixed-cell disabled - disassociate\n", sdata->dev->name);
4294
4295 ieee80211_set_disassoc(sdata, ifsta, false, true,
4296 WLAN_REASON_UNSPECIFIED);
4297 }
4298}