aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/ibss.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/ibss.c')
-rw-r--r--net/wireless/ibss.c133
1 files changed, 106 insertions, 27 deletions
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index a5330c5a5477..99ef9364b7e8 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -10,7 +10,7 @@
10#include "nl80211.h" 10#include "nl80211.h"
11 11
12 12
13void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) 13void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
14{ 14{
15 struct wireless_dev *wdev = dev->ieee80211_ptr; 15 struct wireless_dev *wdev = dev->ieee80211_ptr;
16 struct cfg80211_bss *bss; 16 struct cfg80211_bss *bss;
@@ -39,22 +39,45 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
39 cfg80211_hold_bss(bss_from_pub(bss)); 39 cfg80211_hold_bss(bss_from_pub(bss));
40 wdev->current_bss = bss_from_pub(bss); 40 wdev->current_bss = bss_from_pub(bss);
41 41
42 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp); 42 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
43 GFP_KERNEL);
43#ifdef CONFIG_WIRELESS_EXT 44#ifdef CONFIG_WIRELESS_EXT
44 memset(&wrqu, 0, sizeof(wrqu)); 45 memset(&wrqu, 0, sizeof(wrqu));
45 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 46 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
46 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 47 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
47#endif 48#endif
48} 49}
50
51void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
52{
53 struct wireless_dev *wdev = dev->ieee80211_ptr;
54 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
55 struct cfg80211_event *ev;
56 unsigned long flags;
57
58 ev = kzalloc(sizeof(*ev), gfp);
59 if (!ev)
60 return;
61
62 ev->type = EVENT_IBSS_JOINED;
63 memcpy(ev->cr.bssid, bssid, ETH_ALEN);
64
65 spin_lock_irqsave(&wdev->event_lock, flags);
66 list_add_tail(&ev->list, &wdev->event_list);
67 spin_unlock_irqrestore(&wdev->event_lock, flags);
68 schedule_work(&rdev->event_work);
69}
49EXPORT_SYMBOL(cfg80211_ibss_joined); 70EXPORT_SYMBOL(cfg80211_ibss_joined);
50 71
51int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 72int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
52 struct net_device *dev, 73 struct net_device *dev,
53 struct cfg80211_ibss_params *params) 74 struct cfg80211_ibss_params *params)
54{ 75{
55 struct wireless_dev *wdev = dev->ieee80211_ptr; 76 struct wireless_dev *wdev = dev->ieee80211_ptr;
56 int err; 77 int err;
57 78
79 ASSERT_WDEV_LOCK(wdev);
80
58 if (wdev->ssid_len) 81 if (wdev->ssid_len)
59 return -EALREADY; 82 return -EALREADY;
60 83
@@ -72,10 +95,26 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
72 return 0; 95 return 0;
73} 96}
74 97
75void cfg80211_clear_ibss(struct net_device *dev, bool nowext) 98int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
99 struct net_device *dev,
100 struct cfg80211_ibss_params *params)
101{
102 struct wireless_dev *wdev = dev->ieee80211_ptr;
103 int err;
104
105 wdev_lock(wdev);
106 err = __cfg80211_join_ibss(rdev, dev, params);
107 wdev_unlock(wdev);
108
109 return err;
110}
111
112static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
76{ 113{
77 struct wireless_dev *wdev = dev->ieee80211_ptr; 114 struct wireless_dev *wdev = dev->ieee80211_ptr;
78 115
116 ASSERT_WDEV_LOCK(wdev);
117
79 if (wdev->current_bss) { 118 if (wdev->current_bss) {
80 cfg80211_unhold_bss(wdev->current_bss); 119 cfg80211_unhold_bss(wdev->current_bss);
81 cfg80211_put_bss(&wdev->current_bss->pub); 120 cfg80211_put_bss(&wdev->current_bss->pub);
@@ -89,12 +128,23 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
89#endif 128#endif
90} 129}
91 130
92int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 131void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
93 struct net_device *dev, bool nowext) 132{
133 struct wireless_dev *wdev = dev->ieee80211_ptr;
134
135 wdev_lock(wdev);
136 __cfg80211_clear_ibss(dev, nowext);
137 wdev_unlock(wdev);
138}
139
140static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
141 struct net_device *dev, bool nowext)
94{ 142{
95 struct wireless_dev *wdev = dev->ieee80211_ptr; 143 struct wireless_dev *wdev = dev->ieee80211_ptr;
96 int err; 144 int err;
97 145
146 ASSERT_WDEV_LOCK(wdev);
147
98 if (!wdev->ssid_len) 148 if (!wdev->ssid_len)
99 return -ENOLINK; 149 return -ENOLINK;
100 150
@@ -103,11 +153,24 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
103 if (err) 153 if (err)
104 return err; 154 return err;
105 155
106 cfg80211_clear_ibss(dev, nowext); 156 __cfg80211_clear_ibss(dev, nowext);
107 157
108 return 0; 158 return 0;
109} 159}
110 160
161int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
162 struct net_device *dev, bool nowext)
163{
164 struct wireless_dev *wdev = dev->ieee80211_ptr;
165 int err;
166
167 wdev_lock(wdev);
168 err = __cfg80211_leave_ibss(rdev, dev, nowext);
169 wdev_unlock(wdev);
170
171 return err;
172}
173
111#ifdef CONFIG_WIRELESS_EXT 174#ifdef CONFIG_WIRELESS_EXT
112static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 175static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
113 struct wireless_dev *wdev) 176 struct wireless_dev *wdev)
@@ -184,12 +247,15 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
184 if (wdev->wext.ibss.channel == chan) 247 if (wdev->wext.ibss.channel == chan)
185 return 0; 248 return 0;
186 249
187 if (wdev->ssid_len) { 250 wdev_lock(wdev);
188 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 251 err = 0;
189 dev, true); 252 if (wdev->ssid_len)
190 if (err) 253 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
191 return err; 254 dev, true);
192 } 255 wdev_unlock(wdev);
256
257 if (err)
258 return err;
193 259
194 if (chan) { 260 if (chan) {
195 wdev->wext.ibss.channel = chan; 261 wdev->wext.ibss.channel = chan;
@@ -215,10 +281,12 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
215 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 281 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
216 return -EINVAL; 282 return -EINVAL;
217 283
284 wdev_lock(wdev);
218 if (wdev->current_bss) 285 if (wdev->current_bss)
219 chan = wdev->current_bss->pub.channel; 286 chan = wdev->current_bss->pub.channel;
220 else if (wdev->wext.ibss.channel) 287 else if (wdev->wext.ibss.channel)
221 chan = wdev->wext.ibss.channel; 288 chan = wdev->wext.ibss.channel;
289 wdev_unlock(wdev);
222 290
223 if (chan) { 291 if (chan) {
224 freq->m = chan->center_freq; 292 freq->m = chan->center_freq;
@@ -247,12 +315,15 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
247 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 315 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
248 return -EOPNOTSUPP; 316 return -EOPNOTSUPP;
249 317
250 if (wdev->ssid_len) { 318 wdev_lock(wdev);
251 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 319 err = 0;
252 dev, true); 320 if (wdev->ssid_len)
253 if (err) 321 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
254 return err; 322 dev, true);
255 } 323 wdev_unlock(wdev);
324
325 if (err)
326 return err;
256 327
257 /* iwconfig uses nul termination in SSID.. */ 328 /* iwconfig uses nul termination in SSID.. */
258 if (len > 0 && ssid[len - 1] == '\0') 329 if (len > 0 && ssid[len - 1] == '\0')
@@ -279,6 +350,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
279 350
280 data->flags = 0; 351 data->flags = 0;
281 352
353 wdev_lock(wdev);
282 if (wdev->ssid_len) { 354 if (wdev->ssid_len) {
283 data->flags = 1; 355 data->flags = 1;
284 data->length = wdev->ssid_len; 356 data->length = wdev->ssid_len;
@@ -288,6 +360,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
288 data->length = wdev->wext.ibss.ssid_len; 360 data->length = wdev->wext.ibss.ssid_len;
289 memcpy(ssid, wdev->wext.ibss.ssid, data->length); 361 memcpy(ssid, wdev->wext.ibss.ssid, data->length);
290 } 362 }
363 wdev_unlock(wdev);
291 364
292 return 0; 365 return 0;
293} 366}
@@ -325,12 +398,15 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
325 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0) 398 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0)
326 return 0; 399 return 0;
327 400
328 if (wdev->ssid_len) { 401 wdev_lock(wdev);
329 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 402 err = 0;
330 dev, true); 403 if (wdev->ssid_len)
331 if (err) 404 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
332 return err; 405 dev, true);
333 } 406 wdev_unlock(wdev);
407
408 if (err)
409 return err;
334 410
335 if (bssid) { 411 if (bssid) {
336 memcpy(wdev->wext.bssid, bssid, ETH_ALEN); 412 memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
@@ -355,10 +431,13 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev,
355 431
356 ap_addr->sa_family = ARPHRD_ETHER; 432 ap_addr->sa_family = ARPHRD_ETHER;
357 433
434 wdev_lock(wdev);
358 if (wdev->current_bss) 435 if (wdev->current_bss)
359 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); 436 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
360 else 437 else
361 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); 438 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
439 wdev_unlock(wdev);
440
362 return 0; 441 return 0;
363} 442}
364/* temporary symbol - mark GPL - in the future the handler won't be */ 443/* temporary symbol - mark GPL - in the future the handler won't be */