ibss.c (8a517c514d5893602cf85c1b4c47afbbc04d2198) | ibss.c (f7969969f416e593bcc7dc24abf3f9fd6c27136d) |
---|---|
1/* 2 * Some IBSS support code for cfg80211. 3 * 4 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 5 */ 6 7#include <linux/etherdevice.h> 8#include <linux/if_arp.h> 9#include <net/cfg80211.h> | 1/* 2 * Some IBSS support code for cfg80211. 3 * 4 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 5 */ 6 7#include <linux/etherdevice.h> 8#include <linux/if_arp.h> 9#include <net/cfg80211.h> |
10#include "wext-compat.h" |
|
10#include "nl80211.h" 11 12 | 11#include "nl80211.h" 12 13 |
13void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) | 14void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) |
14{ 15 struct wireless_dev *wdev = dev->ieee80211_ptr; 16 struct cfg80211_bss *bss; 17#ifdef CONFIG_WIRELESS_EXT 18 union iwreq_data wrqu; 19#endif 20 21 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 22 return; 23 | 15{ 16 struct wireless_dev *wdev = dev->ieee80211_ptr; 17 struct cfg80211_bss *bss; 18#ifdef CONFIG_WIRELESS_EXT 19 union iwreq_data wrqu; 20#endif 21 22 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 23 return; 24 |
24 if (WARN_ON(!wdev->ssid_len)) | 25 if (!wdev->ssid_len) |
25 return; 26 | 26 return; 27 |
27 if (memcmp(bssid, wdev->bssid, ETH_ALEN) == 0) 28 return; 29 | |
30 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 31 wdev->ssid, wdev->ssid_len, 32 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); 33 34 if (WARN_ON(!bss)) 35 return; 36 37 if (wdev->current_bss) { 38 cfg80211_unhold_bss(wdev->current_bss); | 28 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 29 wdev->ssid, wdev->ssid_len, 30 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); 31 32 if (WARN_ON(!bss)) 33 return; 34 35 if (wdev->current_bss) { 36 cfg80211_unhold_bss(wdev->current_bss); |
39 cfg80211_put_bss(wdev->current_bss); | 37 cfg80211_put_bss(&wdev->current_bss->pub); |
40 } 41 | 38 } 39 |
42 cfg80211_hold_bss(bss); 43 wdev->current_bss = bss; 44 memcpy(wdev->bssid, bssid, ETH_ALEN); | 40 cfg80211_hold_bss(bss_from_pub(bss)); 41 wdev->current_bss = bss_from_pub(bss); |
45 | 42 |
46 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp); | 43 cfg80211_upload_connect_keys(wdev); 44 45 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, 46 GFP_KERNEL); |
47#ifdef CONFIG_WIRELESS_EXT 48 memset(&wrqu, 0, sizeof(wrqu)); 49 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 50 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 51#endif 52} | 47#ifdef CONFIG_WIRELESS_EXT 48 memset(&wrqu, 0, sizeof(wrqu)); 49 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 50 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 51#endif 52} |
53 54void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) 55{ 56 struct wireless_dev *wdev = dev->ieee80211_ptr; 57 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 58 struct cfg80211_event *ev; 59 unsigned long flags; 60 61 CFG80211_DEV_WARN_ON(!wdev->ssid_len); 62 63 ev = kzalloc(sizeof(*ev), gfp); 64 if (!ev) 65 return; 66 67 ev->type = EVENT_IBSS_JOINED; 68 memcpy(ev->cr.bssid, bssid, ETH_ALEN); 69 70 spin_lock_irqsave(&wdev->event_lock, flags); 71 list_add_tail(&ev->list, &wdev->event_list); 72 spin_unlock_irqrestore(&wdev->event_lock, flags); 73 schedule_work(&rdev->event_work); 74} |
|
53EXPORT_SYMBOL(cfg80211_ibss_joined); 54 | 75EXPORT_SYMBOL(cfg80211_ibss_joined); 76 |
55int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 56 struct net_device *dev, 57 struct cfg80211_ibss_params *params) | 77int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 78 struct net_device *dev, 79 struct cfg80211_ibss_params *params, 80 struct cfg80211_cached_keys *connkeys) |
58{ 59 struct wireless_dev *wdev = dev->ieee80211_ptr; | 81{ 82 struct wireless_dev *wdev = dev->ieee80211_ptr; |
83 struct ieee80211_channel *chan; |
|
60 int err; 61 | 84 int err; 85 |
86 ASSERT_WDEV_LOCK(wdev); 87 88 chan = rdev_fixed_channel(rdev, wdev); 89 if (chan && chan != params->channel) 90 return -EBUSY; 91 |
|
62 if (wdev->ssid_len) 63 return -EALREADY; 64 | 92 if (wdev->ssid_len) 93 return -EALREADY; 94 |
95 if (WARN_ON(wdev->connect_keys)) 96 kfree(wdev->connect_keys); 97 wdev->connect_keys = connkeys; 98 |
|
65#ifdef CONFIG_WIRELESS_EXT 66 wdev->wext.ibss.channel = params->channel; 67#endif 68 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); | 99#ifdef CONFIG_WIRELESS_EXT 100 wdev->wext.ibss.channel = params->channel; 101#endif 102 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); |
69 70 if (err) | 103 if (err) { 104 wdev->connect_keys = NULL; |
71 return err; | 105 return err; |
106 } |
|
72 73 memcpy(wdev->ssid, params->ssid, params->ssid_len); 74 wdev->ssid_len = params->ssid_len; 75 76 return 0; 77} 78 | 107 108 memcpy(wdev->ssid, params->ssid, params->ssid_len); 109 wdev->ssid_len = params->ssid_len; 110 111 return 0; 112} 113 |
79void cfg80211_clear_ibss(struct net_device *dev, bool nowext) | 114int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 115 struct net_device *dev, 116 struct cfg80211_ibss_params *params, 117 struct cfg80211_cached_keys *connkeys) |
80{ 81 struct wireless_dev *wdev = dev->ieee80211_ptr; | 118{ 119 struct wireless_dev *wdev = dev->ieee80211_ptr; |
120 int err; |
|
82 | 121 |
122 mutex_lock(&rdev->devlist_mtx); 123 wdev_lock(wdev); 124 err = __cfg80211_join_ibss(rdev, dev, params, connkeys); 125 wdev_unlock(wdev); 126 mutex_unlock(&rdev->devlist_mtx); 127 128 return err; 129} 130 131static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) 132{ 133 struct wireless_dev *wdev = dev->ieee80211_ptr; 134 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 135 int i; 136 137 ASSERT_WDEV_LOCK(wdev); 138 139 kfree(wdev->connect_keys); 140 wdev->connect_keys = NULL; 141 142 /* 143 * Delete all the keys ... pairwise keys can't really 144 * exist any more anyway, but default keys might. 145 */ 146 if (rdev->ops->del_key) 147 for (i = 0; i < 6; i++) 148 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 149 |
|
83 if (wdev->current_bss) { 84 cfg80211_unhold_bss(wdev->current_bss); | 150 if (wdev->current_bss) { 151 cfg80211_unhold_bss(wdev->current_bss); |
85 cfg80211_put_bss(wdev->current_bss); | 152 cfg80211_put_bss(&wdev->current_bss->pub); |
86 } 87 88 wdev->current_bss = NULL; 89 wdev->ssid_len = 0; | 153 } 154 155 wdev->current_bss = NULL; 156 wdev->ssid_len = 0; |
90 memset(wdev->bssid, 0, ETH_ALEN); | |
91#ifdef CONFIG_WIRELESS_EXT 92 if (!nowext) 93 wdev->wext.ibss.ssid_len = 0; 94#endif 95} 96 | 157#ifdef CONFIG_WIRELESS_EXT 158 if (!nowext) 159 wdev->wext.ibss.ssid_len = 0; 160#endif 161} 162 |
97int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 98 struct net_device *dev, bool nowext) | 163void cfg80211_clear_ibss(struct net_device *dev, bool nowext) |
99{ | 164{ |
165 struct wireless_dev *wdev = dev->ieee80211_ptr; 166 167 wdev_lock(wdev); 168 __cfg80211_clear_ibss(dev, nowext); 169 wdev_unlock(wdev); 170} 171 172static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 173 struct net_device *dev, bool nowext) 174{ 175 struct wireless_dev *wdev = dev->ieee80211_ptr; |
|
100 int err; 101 | 176 int err; 177 |
178 ASSERT_WDEV_LOCK(wdev); 179 180 if (!wdev->ssid_len) 181 return -ENOLINK; 182 |
|
102 err = rdev->ops->leave_ibss(&rdev->wiphy, dev); 103 104 if (err) 105 return err; 106 | 183 err = rdev->ops->leave_ibss(&rdev->wiphy, dev); 184 185 if (err) 186 return err; 187 |
107 cfg80211_clear_ibss(dev, nowext); | 188 __cfg80211_clear_ibss(dev, nowext); |
108 109 return 0; 110} 111 | 189 190 return 0; 191} 192 |
193int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 194 struct net_device *dev, bool nowext) 195{ 196 struct wireless_dev *wdev = dev->ieee80211_ptr; 197 int err; 198 199 wdev_lock(wdev); 200 err = __cfg80211_leave_ibss(rdev, dev, nowext); 201 wdev_unlock(wdev); 202 203 return err; 204} 205 |
|
112#ifdef CONFIG_WIRELESS_EXT | 206#ifdef CONFIG_WIRELESS_EXT |
113static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 114 struct wireless_dev *wdev) | 207int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 208 struct wireless_dev *wdev) |
115{ | 209{ |
210 struct cfg80211_cached_keys *ck = NULL; |
|
116 enum ieee80211_band band; | 211 enum ieee80211_band band; |
117 int i; | 212 int i, err; |
118 | 213 |
214 ASSERT_WDEV_LOCK(wdev); 215 |
|
119 if (!wdev->wext.ibss.beacon_interval) 120 wdev->wext.ibss.beacon_interval = 100; 121 122 /* try to find an IBSS channel if none requested ... */ 123 if (!wdev->wext.ibss.channel) { 124 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 125 struct ieee80211_supported_band *sband; 126 struct ieee80211_channel *chan; --- 22 unchanged lines hidden (view full) --- 149 150 /* don't join -- SSID is not there */ 151 if (!wdev->wext.ibss.ssid_len) 152 return 0; 153 154 if (!netif_running(wdev->netdev)) 155 return 0; 156 | 216 if (!wdev->wext.ibss.beacon_interval) 217 wdev->wext.ibss.beacon_interval = 100; 218 219 /* try to find an IBSS channel if none requested ... */ 220 if (!wdev->wext.ibss.channel) { 221 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 222 struct ieee80211_supported_band *sband; 223 struct ieee80211_channel *chan; --- 22 unchanged lines hidden (view full) --- 246 247 /* don't join -- SSID is not there */ 248 if (!wdev->wext.ibss.ssid_len) 249 return 0; 250 251 if (!netif_running(wdev->netdev)) 252 return 0; 253 |
157 return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), 158 wdev->netdev, &wdev->wext.ibss); | 254 if (wdev->wext.keys) 255 wdev->wext.keys->def = wdev->wext.default_key; 256 257 wdev->wext.ibss.privacy = wdev->wext.default_key != -1; 258 259 if (wdev->wext.keys) { 260 ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL); 261 if (!ck) 262 return -ENOMEM; 263 for (i = 0; i < 6; i++) 264 ck->params[i].key = ck->data[i]; 265 } 266 err = __cfg80211_join_ibss(rdev, wdev->netdev, 267 &wdev->wext.ibss, ck); 268 if (err) 269 kfree(ck); 270 271 return err; |
159} 160 161int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 162 struct iw_request_info *info, | 272} 273 274int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 275 struct iw_request_info *info, |
163 struct iw_freq *freq, char *extra) | 276 struct iw_freq *wextfreq, char *extra) |
164{ 165 struct wireless_dev *wdev = dev->ieee80211_ptr; | 277{ 278 struct wireless_dev *wdev = dev->ieee80211_ptr; |
166 struct ieee80211_channel *chan; 167 int err; | 279 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 280 struct ieee80211_channel *chan = NULL; 281 int err, freq; |
168 169 /* call only for ibss! */ 170 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 171 return -EINVAL; 172 | 282 283 /* call only for ibss! */ 284 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 285 return -EINVAL; 286 |
173 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) | 287 if (!rdev->ops->join_ibss) |
174 return -EOPNOTSUPP; 175 | 288 return -EOPNOTSUPP; 289 |
176 chan = cfg80211_wext_freq(wdev->wiphy, freq); 177 if (chan && IS_ERR(chan)) 178 return PTR_ERR(chan); | 290 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); 291 if (freq < 0) 292 return freq; |
179 | 293 |
180 if (chan && 181 (chan->flags & IEEE80211_CHAN_NO_IBSS || 182 chan->flags & IEEE80211_CHAN_DISABLED)) 183 return -EINVAL; | 294 if (freq) { 295 chan = ieee80211_get_channel(wdev->wiphy, freq); 296 if (!chan) 297 return -EINVAL; 298 if (chan->flags & IEEE80211_CHAN_NO_IBSS || 299 chan->flags & IEEE80211_CHAN_DISABLED) 300 return -EINVAL; 301 } |
184 185 if (wdev->wext.ibss.channel == chan) 186 return 0; 187 | 302 303 if (wdev->wext.ibss.channel == chan) 304 return 0; 305 |
188 if (wdev->ssid_len) { 189 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 190 dev, true); 191 if (err) 192 return err; 193 } | 306 wdev_lock(wdev); 307 err = 0; 308 if (wdev->ssid_len) 309 err = __cfg80211_leave_ibss(rdev, dev, true); 310 wdev_unlock(wdev); |
194 | 311 |
312 if (err) 313 return err; 314 |
|
195 if (chan) { 196 wdev->wext.ibss.channel = chan; 197 wdev->wext.ibss.channel_fixed = true; 198 } else { 199 /* cfg80211_ibss_wext_join will pick one if needed */ 200 wdev->wext.ibss.channel_fixed = false; 201 } 202 | 315 if (chan) { 316 wdev->wext.ibss.channel = chan; 317 wdev->wext.ibss.channel_fixed = true; 318 } else { 319 /* cfg80211_ibss_wext_join will pick one if needed */ 320 wdev->wext.ibss.channel_fixed = false; 321 } 322 |
203 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 323 mutex_lock(&rdev->devlist_mtx); 324 wdev_lock(wdev); 325 err = cfg80211_ibss_wext_join(rdev, wdev); 326 wdev_unlock(wdev); 327 mutex_unlock(&rdev->devlist_mtx); 328 329 return err; |
204} | 330} |
205/* temporary symbol - mark GPL - in the future the handler won't be */ 206EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); | |
207 208int cfg80211_ibss_wext_giwfreq(struct net_device *dev, 209 struct iw_request_info *info, 210 struct iw_freq *freq, char *extra) 211{ 212 struct wireless_dev *wdev = dev->ieee80211_ptr; 213 struct ieee80211_channel *chan = NULL; 214 215 /* call only for ibss! */ 216 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 217 return -EINVAL; 218 | 331 332int cfg80211_ibss_wext_giwfreq(struct net_device *dev, 333 struct iw_request_info *info, 334 struct iw_freq *freq, char *extra) 335{ 336 struct wireless_dev *wdev = dev->ieee80211_ptr; 337 struct ieee80211_channel *chan = NULL; 338 339 /* call only for ibss! */ 340 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 341 return -EINVAL; 342 |
343 wdev_lock(wdev); |
|
219 if (wdev->current_bss) | 344 if (wdev->current_bss) |
220 chan = wdev->current_bss->channel; | 345 chan = wdev->current_bss->pub.channel; |
221 else if (wdev->wext.ibss.channel) 222 chan = wdev->wext.ibss.channel; | 346 else if (wdev->wext.ibss.channel) 347 chan = wdev->wext.ibss.channel; |
348 wdev_unlock(wdev); |
|
223 224 if (chan) { 225 freq->m = chan->center_freq; 226 freq->e = 6; 227 return 0; 228 } 229 230 /* no channel if not joining */ 231 return -EINVAL; 232} | 349 350 if (chan) { 351 freq->m = chan->center_freq; 352 freq->e = 6; 353 return 0; 354 } 355 356 /* no channel if not joining */ 357 return -EINVAL; 358} |
233/* temporary symbol - mark GPL - in the future the handler won't be */ 234EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwfreq); | |
235 236int cfg80211_ibss_wext_siwessid(struct net_device *dev, 237 struct iw_request_info *info, 238 struct iw_point *data, char *ssid) 239{ 240 struct wireless_dev *wdev = dev->ieee80211_ptr; | 359 360int cfg80211_ibss_wext_siwessid(struct net_device *dev, 361 struct iw_request_info *info, 362 struct iw_point *data, char *ssid) 363{ 364 struct wireless_dev *wdev = dev->ieee80211_ptr; |
365 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
|
241 size_t len = data->length; 242 int err; 243 244 /* call only for ibss! */ 245 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 246 return -EINVAL; 247 | 366 size_t len = data->length; 367 int err; 368 369 /* call only for ibss! */ 370 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 371 return -EINVAL; 372 |
248 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) | 373 if (!rdev->ops->join_ibss) |
249 return -EOPNOTSUPP; 250 | 374 return -EOPNOTSUPP; 375 |
251 if (wdev->ssid_len) { 252 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 253 dev, true); 254 if (err) 255 return err; 256 } | 376 wdev_lock(wdev); 377 err = 0; 378 if (wdev->ssid_len) 379 err = __cfg80211_leave_ibss(rdev, dev, true); 380 wdev_unlock(wdev); |
257 | 381 |
382 if (err) 383 return err; 384 |
|
258 /* iwconfig uses nul termination in SSID.. */ 259 if (len > 0 && ssid[len - 1] == '\0') 260 len--; 261 262 wdev->wext.ibss.ssid = wdev->ssid; 263 memcpy(wdev->wext.ibss.ssid, ssid, len); 264 wdev->wext.ibss.ssid_len = len; 265 | 385 /* iwconfig uses nul termination in SSID.. */ 386 if (len > 0 && ssid[len - 1] == '\0') 387 len--; 388 389 wdev->wext.ibss.ssid = wdev->ssid; 390 memcpy(wdev->wext.ibss.ssid, ssid, len); 391 wdev->wext.ibss.ssid_len = len; 392 |
266 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 393 mutex_lock(&rdev->devlist_mtx); 394 wdev_lock(wdev); 395 err = cfg80211_ibss_wext_join(rdev, wdev); 396 wdev_unlock(wdev); 397 mutex_unlock(&rdev->devlist_mtx); 398 399 return err; |
267} | 400} |
268/* temporary symbol - mark GPL - in the future the handler won't be */ 269EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); | |
270 271int cfg80211_ibss_wext_giwessid(struct net_device *dev, 272 struct iw_request_info *info, 273 struct iw_point *data, char *ssid) 274{ 275 struct wireless_dev *wdev = dev->ieee80211_ptr; 276 277 /* call only for ibss! */ 278 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 279 return -EINVAL; 280 281 data->flags = 0; 282 | 401 402int cfg80211_ibss_wext_giwessid(struct net_device *dev, 403 struct iw_request_info *info, 404 struct iw_point *data, char *ssid) 405{ 406 struct wireless_dev *wdev = dev->ieee80211_ptr; 407 408 /* call only for ibss! */ 409 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 410 return -EINVAL; 411 412 data->flags = 0; 413 |
414 wdev_lock(wdev); |
|
283 if (wdev->ssid_len) { 284 data->flags = 1; 285 data->length = wdev->ssid_len; 286 memcpy(ssid, wdev->ssid, data->length); 287 } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) { 288 data->flags = 1; 289 data->length = wdev->wext.ibss.ssid_len; 290 memcpy(ssid, wdev->wext.ibss.ssid, data->length); 291 } | 415 if (wdev->ssid_len) { 416 data->flags = 1; 417 data->length = wdev->ssid_len; 418 memcpy(ssid, wdev->ssid, data->length); 419 } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) { 420 data->flags = 1; 421 data->length = wdev->wext.ibss.ssid_len; 422 memcpy(ssid, wdev->wext.ibss.ssid, data->length); 423 } |
424 wdev_unlock(wdev); |
|
292 293 return 0; 294} | 425 426 return 0; 427} |
295/* temporary symbol - mark GPL - in the future the handler won't be */ 296EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwessid); | |
297 298int cfg80211_ibss_wext_siwap(struct net_device *dev, 299 struct iw_request_info *info, 300 struct sockaddr *ap_addr, char *extra) 301{ 302 struct wireless_dev *wdev = dev->ieee80211_ptr; | 428 429int cfg80211_ibss_wext_siwap(struct net_device *dev, 430 struct iw_request_info *info, 431 struct sockaddr *ap_addr, char *extra) 432{ 433 struct wireless_dev *wdev = dev->ieee80211_ptr; |
434 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
|
303 u8 *bssid = ap_addr->sa_data; 304 int err; 305 306 /* call only for ibss! */ 307 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 308 return -EINVAL; 309 | 435 u8 *bssid = ap_addr->sa_data; 436 int err; 437 438 /* call only for ibss! */ 439 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 440 return -EINVAL; 441 |
310 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) | 442 if (!rdev->ops->join_ibss) |
311 return -EOPNOTSUPP; 312 313 if (ap_addr->sa_family != ARPHRD_ETHER) 314 return -EINVAL; 315 316 /* automatic mode */ 317 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 318 bssid = NULL; 319 320 /* both automatic */ 321 if (!bssid && !wdev->wext.ibss.bssid) 322 return 0; 323 324 /* fixed already - and no change */ 325 if (wdev->wext.ibss.bssid && bssid && 326 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0) 327 return 0; 328 | 443 return -EOPNOTSUPP; 444 445 if (ap_addr->sa_family != ARPHRD_ETHER) 446 return -EINVAL; 447 448 /* automatic mode */ 449 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 450 bssid = NULL; 451 452 /* both automatic */ 453 if (!bssid && !wdev->wext.ibss.bssid) 454 return 0; 455 456 /* fixed already - and no change */ 457 if (wdev->wext.ibss.bssid && bssid && 458 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0) 459 return 0; 460 |
329 if (wdev->ssid_len) { 330 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 331 dev, true); 332 if (err) 333 return err; 334 } | 461 wdev_lock(wdev); 462 err = 0; 463 if (wdev->ssid_len) 464 err = __cfg80211_leave_ibss(rdev, dev, true); 465 wdev_unlock(wdev); |
335 | 466 |
467 if (err) 468 return err; 469 |
|
336 if (bssid) { 337 memcpy(wdev->wext.bssid, bssid, ETH_ALEN); 338 wdev->wext.ibss.bssid = wdev->wext.bssid; 339 } else 340 wdev->wext.ibss.bssid = NULL; 341 | 470 if (bssid) { 471 memcpy(wdev->wext.bssid, bssid, ETH_ALEN); 472 wdev->wext.ibss.bssid = wdev->wext.bssid; 473 } else 474 wdev->wext.ibss.bssid = NULL; 475 |
342 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 476 mutex_lock(&rdev->devlist_mtx); 477 wdev_lock(wdev); 478 err = cfg80211_ibss_wext_join(rdev, wdev); 479 wdev_unlock(wdev); 480 mutex_unlock(&rdev->devlist_mtx); 481 482 return err; |
343} | 483} |
344/* temporary symbol - mark GPL - in the future the handler won't be */ 345EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); | |
346 347int cfg80211_ibss_wext_giwap(struct net_device *dev, 348 struct iw_request_info *info, 349 struct sockaddr *ap_addr, char *extra) 350{ 351 struct wireless_dev *wdev = dev->ieee80211_ptr; 352 353 /* call only for ibss! */ 354 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 355 return -EINVAL; 356 357 ap_addr->sa_family = ARPHRD_ETHER; 358 | 484 485int cfg80211_ibss_wext_giwap(struct net_device *dev, 486 struct iw_request_info *info, 487 struct sockaddr *ap_addr, char *extra) 488{ 489 struct wireless_dev *wdev = dev->ieee80211_ptr; 490 491 /* call only for ibss! */ 492 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 493 return -EINVAL; 494 495 ap_addr->sa_family = ARPHRD_ETHER; 496 |
359 if (wdev->wext.ibss.bssid) { | 497 wdev_lock(wdev); 498 if (wdev->current_bss) 499 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); 500 else if (wdev->wext.ibss.bssid) |
360 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); | 501 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); |
361 return 0; 362 } | 502 else 503 memset(ap_addr->sa_data, 0, ETH_ALEN); |
363 | 504 |
364 memcpy(ap_addr->sa_data, wdev->bssid, ETH_ALEN); | 505 wdev_unlock(wdev); 506 |
365 return 0; 366} | 507 return 0; 508} |
367/* temporary symbol - mark GPL - in the future the handler won't be */ 368EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwap); | |
369#endif | 509#endif |