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