diff options
Diffstat (limited to 'net/wireless/wext-sme.c')
-rw-r--r-- | net/wireless/wext-sme.c | 125 |
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 */ |
82 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); | 95 | EXPORT_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 */ |
157 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); | 181 | EXPORT_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 */ |
232 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); | 266 | EXPORT_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 | } |
299 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie); | 343 | EXPORT_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 | } |
329 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); | 380 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); |