aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext-sme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/wext-sme.c')
-rw-r--r--net/wireless/wext-sme.c125
1 files changed, 88 insertions, 37 deletions
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index fe1987acb891..6f75aaa7f795 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -15,6 +15,9 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
15{ 15{
16 int err; 16 int err;
17 17
18 ASSERT_RDEV_LOCK(rdev);
19 ASSERT_WDEV_LOCK(wdev);
20
18 if (!netif_running(wdev->netdev)) 21 if (!netif_running(wdev->netdev))
19 return 0; 22 return 0;
20 23
@@ -24,8 +27,8 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
24 27
25 err = 0; 28 err = 0;
26 if (wdev->wext.connect.ssid_len != 0) 29 if (wdev->wext.connect.ssid_len != 0)
27 err = cfg80211_connect(rdev, wdev->netdev, 30 err = __cfg80211_connect(rdev, wdev->netdev,
28 &wdev->wext.connect); 31 &wdev->wext.connect);
29 32
30 return err; 33 return err;
31} 34}
@@ -50,33 +53,43 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
50 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED)) 53 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED))
51 return -EINVAL; 54 return -EINVAL;
52 55
53 if (wdev->wext.connect.channel == chan) 56 cfg80211_lock_rdev(rdev);
54 return 0; 57 wdev_lock(wdev);
58
59 if (wdev->wext.connect.channel == chan) {
60 err = 0;
61 goto out;
62 }
55 63
56 if (wdev->sme_state != CFG80211_SME_IDLE) { 64 if (wdev->sme_state != CFG80211_SME_IDLE) {
57 bool event = true; 65 bool event = true;
58 /* if SSID set, we'll try right again, avoid event */ 66 /* if SSID set, we'll try right again, avoid event */
59 if (wdev->wext.connect.ssid_len) 67 if (wdev->wext.connect.ssid_len)
60 event = false; 68 event = false;
61 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 69 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
62 dev, WLAN_REASON_DEAUTH_LEAVING, 70 dev, WLAN_REASON_DEAUTH_LEAVING,
63 event); 71 event);
64 if (err) 72 if (err)
65 return err; 73 goto out;
66 } 74 }
67 75
76
68 wdev->wext.connect.channel = chan; 77 wdev->wext.connect.channel = chan;
69 78
70 /* SSID is not set, we just want to switch channel */ 79 /* SSID is not set, we just want to switch channel */
71 if (wdev->wext.connect.ssid_len && chan) { 80 if (wdev->wext.connect.ssid_len && chan) {
72 if (!rdev->ops->set_channel) 81 err = -EOPNOTSUPP;
73 return -EOPNOTSUPP; 82 if (rdev->ops->set_channel)
74 83 err = rdev->ops->set_channel(wdev->wiphy, chan,
75 return rdev->ops->set_channel(wdev->wiphy, chan, 84 NL80211_CHAN_NO_HT);
76 NL80211_CHAN_NO_HT); 85 goto out;
77 } 86 }
78 87
79 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 88 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
89 out:
90 wdev_unlock(wdev);
91 cfg80211_unlock_rdev(rdev);
92 return err;
80} 93}
81/* temporary symbol - mark GPL - in the future the handler won't be */ 94/* temporary symbol - mark GPL - in the future the handler won't be */
82EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); 95EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq);
@@ -92,10 +105,12 @@ int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
92 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 105 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
93 return -EINVAL; 106 return -EINVAL;
94 107
108 wdev_lock(wdev);
95 if (wdev->current_bss) 109 if (wdev->current_bss)
96 chan = wdev->current_bss->pub.channel; 110 chan = wdev->current_bss->pub.channel;
97 else if (wdev->wext.connect.channel) 111 else if (wdev->wext.connect.channel)
98 chan = wdev->wext.connect.channel; 112 chan = wdev->wext.connect.channel;
113 wdev_unlock(wdev);
99 114
100 if (chan) { 115 if (chan) {
101 freq->m = chan->center_freq; 116 freq->m = chan->center_freq;
@@ -128,21 +143,26 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
128 if (len > 0 && ssid[len - 1] == '\0') 143 if (len > 0 && ssid[len - 1] == '\0')
129 len--; 144 len--;
130 145
146 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
147 wdev_lock(wdev);
148
149 err = 0;
150
131 if (wdev->wext.connect.ssid && len && 151 if (wdev->wext.connect.ssid && len &&
132 len == wdev->wext.connect.ssid_len && 152 len == wdev->wext.connect.ssid_len &&
133 memcmp(wdev->wext.connect.ssid, ssid, len)) 153 memcmp(wdev->wext.connect.ssid, ssid, len))
134 return 0; 154 goto out;
135 155
136 if (wdev->sme_state != CFG80211_SME_IDLE) { 156 if (wdev->sme_state != CFG80211_SME_IDLE) {
137 bool event = true; 157 bool event = true;
138 /* if SSID set now, we'll try to connect, avoid event */ 158 /* if SSID set now, we'll try to connect, avoid event */
139 if (len) 159 if (len)
140 event = false; 160 event = false;
141 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 161 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
142 dev, WLAN_REASON_DEAUTH_LEAVING, 162 dev, WLAN_REASON_DEAUTH_LEAVING,
143 event); 163 event);
144 if (err) 164 if (err)
145 return err; 165 goto out;
146 } 166 }
147 167
148 wdev->wext.connect.ssid = wdev->wext.ssid; 168 wdev->wext.connect.ssid = wdev->wext.ssid;
@@ -151,7 +171,11 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
151 171
152 wdev->wext.connect.crypto.control_port = false; 172 wdev->wext.connect.crypto.control_port = false;
153 173
154 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 174 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
175 out:
176 wdev_unlock(wdev);
177 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
178 return err;
155} 179}
156/* temporary symbol - mark GPL - in the future the handler won't be */ 180/* temporary symbol - mark GPL - in the future the handler won't be */
157EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); 181EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid);
@@ -168,6 +192,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
168 192
169 data->flags = 0; 193 data->flags = 0;
170 194
195 wdev_lock(wdev);
171 if (wdev->ssid_len) { 196 if (wdev->ssid_len) {
172 data->flags = 1; 197 data->flags = 1;
173 data->length = wdev->ssid_len; 198 data->length = wdev->ssid_len;
@@ -178,6 +203,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
178 memcpy(ssid, wdev->wext.connect.ssid, data->length); 203 memcpy(ssid, wdev->wext.connect.ssid, data->length);
179 } else 204 } else
180 data->flags = 0; 205 data->flags = 0;
206 wdev_unlock(wdev);
181 207
182 return 0; 208 return 0;
183} 209}
@@ -203,21 +229,25 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
203 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 229 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
204 bssid = NULL; 230 bssid = NULL;
205 231
232 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
233 wdev_lock(wdev);
234
235 err = 0;
206 /* both automatic */ 236 /* both automatic */
207 if (!bssid && !wdev->wext.connect.bssid) 237 if (!bssid && !wdev->wext.connect.bssid)
208 return 0; 238 goto out;
209 239
210 /* fixed already - and no change */ 240 /* fixed already - and no change */
211 if (wdev->wext.connect.bssid && bssid && 241 if (wdev->wext.connect.bssid && bssid &&
212 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) 242 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
213 return 0; 243 goto out;
214 244
215 if (wdev->sme_state != CFG80211_SME_IDLE) { 245 if (wdev->sme_state != CFG80211_SME_IDLE) {
216 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 246 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
217 dev, WLAN_REASON_DEAUTH_LEAVING, 247 dev, WLAN_REASON_DEAUTH_LEAVING,
218 false); 248 false);
219 if (err) 249 if (err)
220 return err; 250 goto out;
221 } 251 }
222 252
223 if (bssid) { 253 if (bssid) {
@@ -226,7 +256,11 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
226 } else 256 } else
227 wdev->wext.connect.bssid = NULL; 257 wdev->wext.connect.bssid = NULL;
228 258
229 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 259 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
260 out:
261 wdev_unlock(wdev);
262 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
263 return err;
230} 264}
231/* temporary symbol - mark GPL - in the future the handler won't be */ 265/* temporary symbol - mark GPL - in the future the handler won't be */
232EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); 266EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap);
@@ -243,12 +277,14 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev,
243 277
244 ap_addr->sa_family = ARPHRD_ETHER; 278 ap_addr->sa_family = ARPHRD_ETHER;
245 279
280 wdev_lock(wdev);
246 if (wdev->current_bss) 281 if (wdev->current_bss)
247 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); 282 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
248 else if (wdev->wext.connect.bssid) 283 else if (wdev->wext.connect.bssid)
249 memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN); 284 memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
250 else 285 else
251 memset(ap_addr->sa_data, 0, ETH_ALEN); 286 memset(ap_addr->sa_data, 0, ETH_ALEN);
287 wdev_unlock(wdev);
252 288
253 return 0; 289 return 0;
254} 290}
@@ -270,15 +306,20 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
270 if (!ie_len) 306 if (!ie_len)
271 ie = NULL; 307 ie = NULL;
272 308
309 wdev_lock(wdev);
310
273 /* no change */ 311 /* no change */
312 err = 0;
274 if (wdev->wext.ie_len == ie_len && 313 if (wdev->wext.ie_len == ie_len &&
275 memcmp(wdev->wext.ie, ie, ie_len) == 0) 314 memcmp(wdev->wext.ie, ie, ie_len) == 0)
276 return 0; 315 goto out;
277 316
278 if (ie_len) { 317 if (ie_len) {
279 ie = kmemdup(extra, ie_len, GFP_KERNEL); 318 ie = kmemdup(extra, ie_len, GFP_KERNEL);
280 if (!ie) 319 if (!ie) {
281 return -ENOMEM; 320 err = -ENOMEM;
321 goto out;
322 }
282 } else 323 } else
283 ie = NULL; 324 ie = NULL;
284 325
@@ -287,14 +328,17 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
287 wdev->wext.ie_len = ie_len; 328 wdev->wext.ie_len = ie_len;
288 329
289 if (wdev->sme_state != CFG80211_SME_IDLE) { 330 if (wdev->sme_state != CFG80211_SME_IDLE) {
290 err = cfg80211_disconnect(rdev, dev, 331 err = __cfg80211_disconnect(rdev, dev,
291 WLAN_REASON_DEAUTH_LEAVING, false); 332 WLAN_REASON_DEAUTH_LEAVING, false);
292 if (err) 333 if (err)
293 return err; 334 goto out;
294 } 335 }
295 336
296 /* userspace better not think we'll reconnect */ 337 /* userspace better not think we'll reconnect */
297 return 0; 338 err = 0;
339 out:
340 wdev_unlock(wdev);
341 return err;
298} 342}
299EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie); 343EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie);
300 344
@@ -305,6 +349,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
305 struct wireless_dev *wdev = dev->ieee80211_ptr; 349 struct wireless_dev *wdev = dev->ieee80211_ptr;
306 struct iw_mlme *mlme = (struct iw_mlme *)extra; 350 struct iw_mlme *mlme = (struct iw_mlme *)extra;
307 struct cfg80211_registered_device *rdev; 351 struct cfg80211_registered_device *rdev;
352 int err;
308 353
309 if (!wdev) 354 if (!wdev)
310 return -EOPNOTSUPP; 355 return -EOPNOTSUPP;
@@ -317,13 +362,19 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
317 if (mlme->addr.sa_family != ARPHRD_ETHER) 362 if (mlme->addr.sa_family != ARPHRD_ETHER)
318 return -EINVAL; 363 return -EINVAL;
319 364
365 wdev_lock(wdev);
320 switch (mlme->cmd) { 366 switch (mlme->cmd) {
321 case IW_MLME_DEAUTH: 367 case IW_MLME_DEAUTH:
322 case IW_MLME_DISASSOC: 368 case IW_MLME_DISASSOC:
323 return cfg80211_disconnect(rdev, dev, mlme->reason_code, 369 err = __cfg80211_disconnect(rdev, dev, mlme->reason_code,
324 true); 370 true);
371 break;
325 default: 372 default:
326 return -EOPNOTSUPP; 373 err = -EOPNOTSUPP;
374 break;
327 } 375 }
376 wdev_unlock(wdev);
377
378 return err;
328} 379}
329EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); 380EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);