aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/softmac/ieee80211softmac_assoc.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2006-09-27 08:26:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-10-16 20:09:47 -0400
commit7c28ad2d83ecc637237fe684659a6afbce0bb2a8 (patch)
tree4bdbe26516d2d8aa195f97eae9cd120d47521ab6 /net/ieee80211/softmac/ieee80211softmac_assoc.c
parent3693ec670b3bb4d11295856bea3592dd8f37f9a5 (diff)
[PATCH] softmac: Fix WX and association related races
This fixes some race conditions in the WirelessExtension handling and association handling code. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/ieee80211/softmac/ieee80211softmac_assoc.c')
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c56
1 files changed, 27 insertions, 29 deletions
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 589f6d2c548a..cf51c87a971d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -48,7 +48,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
48 dprintk(KERN_INFO PFX "sent association request!\n"); 48 dprintk(KERN_INFO PFX "sent association request!\n");
49 49
50 spin_lock_irqsave(&mac->lock, flags); 50 spin_lock_irqsave(&mac->lock, flags);
51 mac->associated = 0; /* just to make sure */ 51 mac->associnfo.associated = 0; /* just to make sure */
52 52
53 /* Set a timer for timeout */ 53 /* Set a timer for timeout */
54 /* FIXME: make timeout configurable */ 54 /* FIXME: make timeout configurable */
@@ -62,24 +62,22 @@ ieee80211softmac_assoc_timeout(void *d)
62{ 62{
63 struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; 63 struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
64 struct ieee80211softmac_network *n; 64 struct ieee80211softmac_network *n;
65 unsigned long flags;
66 65
67 spin_lock_irqsave(&mac->lock, flags); 66 mutex_lock(&mac->associnfo.mutex);
68 /* we might race against ieee80211softmac_handle_assoc_response, 67 /* we might race against ieee80211softmac_handle_assoc_response,
69 * so make sure only one of us does something */ 68 * so make sure only one of us does something */
70 if (!mac->associnfo.associating) { 69 if (!mac->associnfo.associating)
71 spin_unlock_irqrestore(&mac->lock, flags); 70 goto out;
72 return;
73 }
74 mac->associnfo.associating = 0; 71 mac->associnfo.associating = 0;
75 mac->associnfo.bssvalid = 0; 72 mac->associnfo.bssvalid = 0;
76 mac->associated = 0; 73 mac->associnfo.associated = 0;
77 74
78 n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid); 75 n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
79 spin_unlock_irqrestore(&mac->lock, flags);
80 76
81 dprintk(KERN_INFO PFX "assoc request timed out!\n"); 77 dprintk(KERN_INFO PFX "assoc request timed out!\n");
82 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n); 78 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
79out:
80 mutex_unlock(&mac->associnfo.mutex);
83} 81}
84 82
85void 83void
@@ -93,7 +91,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
93 91
94 netif_carrier_off(mac->dev); 92 netif_carrier_off(mac->dev);
95 93
96 mac->associated = 0; 94 mac->associnfo.associated = 0;
97 mac->associnfo.bssvalid = 0; 95 mac->associnfo.bssvalid = 0;
98 mac->associnfo.associating = 0; 96 mac->associnfo.associating = 0;
99 ieee80211softmac_init_bss(mac); 97 ieee80211softmac_init_bss(mac);
@@ -107,7 +105,7 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas
107{ 105{
108 struct ieee80211softmac_network *found; 106 struct ieee80211softmac_network *found;
109 107
110 if (mac->associnfo.bssvalid && mac->associated) { 108 if (mac->associnfo.bssvalid && mac->associnfo.associated) {
111 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 109 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
112 if (found) 110 if (found)
113 ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); 111 ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
@@ -196,17 +194,18 @@ ieee80211softmac_assoc_work(void *d)
196 int bssvalid; 194 int bssvalid;
197 unsigned long flags; 195 unsigned long flags;
198 196
197 mutex_lock(&mac->associnfo.mutex);
198
199 if (!mac->associnfo.associating)
200 goto out;
201
199 /* ieee80211_disassoc might clear this */ 202 /* ieee80211_disassoc might clear this */
200 bssvalid = mac->associnfo.bssvalid; 203 bssvalid = mac->associnfo.bssvalid;
201 204
202 /* meh */ 205 /* meh */
203 if (mac->associated) 206 if (mac->associnfo.associated)
204 ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); 207 ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
205 208
206 spin_lock_irqsave(&mac->lock, flags);
207 mac->associnfo.associating = 1;
208 spin_unlock_irqrestore(&mac->lock, flags);
209
210 /* try to find the requested network in our list, if we found one already */ 209 /* try to find the requested network in our list, if we found one already */
211 if (bssvalid || mac->associnfo.bssfixed) 210 if (bssvalid || mac->associnfo.bssfixed)
212 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 211 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
@@ -260,10 +259,8 @@ ieee80211softmac_assoc_work(void *d)
260 259
261 if (!found) { 260 if (!found) {
262 if (mac->associnfo.scan_retry > 0) { 261 if (mac->associnfo.scan_retry > 0) {
263 spin_lock_irqsave(&mac->lock, flags);
264 mac->associnfo.scan_retry--; 262 mac->associnfo.scan_retry--;
265 spin_unlock_irqrestore(&mac->lock, flags); 263
266
267 /* We know of no such network. Let's scan. 264 /* We know of no such network. Let's scan.
268 * NB: this also happens if we had no memory to copy the network info... 265 * NB: this also happens if we had no memory to copy the network info...
269 * Maybe we can hope to have more memory after scanning finishes ;) 266 * Maybe we can hope to have more memory after scanning finishes ;)
@@ -272,19 +269,17 @@ ieee80211softmac_assoc_work(void *d)
272 ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); 269 ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
273 if (ieee80211softmac_start_scan(mac)) 270 if (ieee80211softmac_start_scan(mac))
274 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); 271 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
275 return; 272 goto out;
276 } else { 273 } else {
277 spin_lock_irqsave(&mac->lock, flags);
278 mac->associnfo.associating = 0; 274 mac->associnfo.associating = 0;
279 mac->associated = 0; 275 mac->associnfo.associated = 0;
280 spin_unlock_irqrestore(&mac->lock, flags);
281 276
282 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); 277 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
283 /* reset the retry counter for the next user request since we 278 /* reset the retry counter for the next user request since we
284 * break out and don't reschedule ourselves after this point. */ 279 * break out and don't reschedule ourselves after this point. */
285 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; 280 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
286 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); 281 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
287 return; 282 goto out;
288 } 283 }
289 } 284 }
290 285
@@ -297,7 +292,7 @@ ieee80211softmac_assoc_work(void *d)
297 /* copy the ESSID for displaying it */ 292 /* copy the ESSID for displaying it */
298 mac->associnfo.associate_essid.len = found->essid.len; 293 mac->associnfo.associate_essid.len = found->essid.len;
299 memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); 294 memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
300 295
301 /* we found a network! authenticate (if necessary) and associate to it. */ 296 /* we found a network! authenticate (if necessary) and associate to it. */
302 if (found->authenticating) { 297 if (found->authenticating) {
303 dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n"); 298 dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
@@ -305,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
305 mac->associnfo.assoc_wait = 1; 300 mac->associnfo.assoc_wait = 1;
306 ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); 301 ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
307 } 302 }
308 return; 303 goto out;
309 } 304 }
310 if (!found->authenticated && !found->authenticating) { 305 if (!found->authenticated && !found->authenticating) {
311 /* This relies on the fact that _auth_req only queues the work, 306 /* This relies on the fact that _auth_req only queues the work,
@@ -321,11 +316,14 @@ ieee80211softmac_assoc_work(void *d)
321 mac->associnfo.assoc_wait = 0; 316 mac->associnfo.assoc_wait = 0;
322 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); 317 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
323 } 318 }
324 return; 319 goto out;
325 } 320 }
326 /* finally! now we can start associating */ 321 /* finally! now we can start associating */
327 mac->associnfo.assoc_wait = 0; 322 mac->associnfo.assoc_wait = 0;
328 ieee80211softmac_assoc(mac, found); 323 ieee80211softmac_assoc(mac, found);
324
325out:
326 mutex_unlock(&mac->associnfo.mutex);
329} 327}
330 328
331/* call this to do whatever is necessary when we're associated */ 329/* call this to do whatever is necessary when we're associated */
@@ -341,7 +339,7 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
341 mac->bssinfo.supported_rates = net->supported_rates; 339 mac->bssinfo.supported_rates = net->supported_rates;
342 ieee80211softmac_recalc_txrates(mac); 340 ieee80211softmac_recalc_txrates(mac);
343 341
344 mac->associated = 1; 342 mac->associnfo.associated = 1;
345 343
346 mac->associnfo.short_preamble_available = 344 mac->associnfo.short_preamble_available =
347 (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; 345 (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
@@ -421,7 +419,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
421 dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); 419 dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
422 mac->associnfo.associating = 0; 420 mac->associnfo.associating = 0;
423 mac->associnfo.bssvalid = 0; 421 mac->associnfo.bssvalid = 0;
424 mac->associated = 0; 422 mac->associnfo.associated = 0;
425 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); 423 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
426 } 424 }
427 425