cfg80211: add tracing to rdev-ops
[deliverable/linux.git] / net / wireless / mlme.c
CommitLineData
6039f6d2
JM
1/*
2 * cfg80211 MLME SAP interface
3 *
4 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
c6fb08aa 9#include <linux/etherdevice.h>
6039f6d2
JM
10#include <linux/netdevice.h>
11#include <linux/nl80211.h>
5a0e3ad6 12#include <linux/slab.h>
a9a11622 13#include <linux/wireless.h>
6039f6d2 14#include <net/cfg80211.h>
a9a11622 15#include <net/iw_handler.h>
6039f6d2
JM
16#include "core.h"
17#include "nl80211.h"
e35e4d28
HG
18#include "rdev-ops.h"
19
6039f6d2 20
cb0b4beb 21void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
6039f6d2 22{
19957bb3
JB
23 struct wireless_dev *wdev = dev->ieee80211_ptr;
24 struct wiphy *wiphy = wdev->wiphy;
6039f6d2 25 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
19957bb3 26
667503dd 27 wdev_lock(wdev);
cb0b4beb 28
95de817b
JB
29 nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
30 cfg80211_sme_rx_auth(dev, buf, len);
667503dd
JB
31
32 wdev_unlock(wdev);
6039f6d2
JM
33}
34EXPORT_SYMBOL(cfg80211_send_rx_auth);
35
95de817b
JB
36void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
37 const u8 *buf, size_t len)
6039f6d2 38{
6829c878
JB
39 u16 status_code;
40 struct wireless_dev *wdev = dev->ieee80211_ptr;
41 struct wiphy *wiphy = wdev->wiphy;
6039f6d2 42 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
6829c878
JB
43 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
44 u8 *ie = mgmt->u.assoc_resp.variable;
95de817b 45 int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
6829c878 46
667503dd 47 wdev_lock(wdev);
cb0b4beb 48
6829c878
JB
49 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
50
f401a6f7
JB
51 /*
52 * This is a bit of a hack, we don't notify userspace of
53 * a (re-)association reply if we tried to send a reassoc
54 * and got a reject -- we only try again with an assoc
55 * frame instead of reassoc.
56 */
57 if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
95de817b
JB
58 cfg80211_sme_failed_reassoc(wdev)) {
59 cfg80211_put_bss(bss);
f401a6f7 60 goto out;
95de817b 61 }
f401a6f7 62
cb0b4beb 63 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
6829c878 64
95de817b 65 if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) {
7d930bc3 66 cfg80211_sme_failed_assoc(wdev);
7d930bc3
JB
67 /*
68 * do not call connect_result() now because the
69 * sme will schedule work that does it later.
70 */
95de817b 71 cfg80211_put_bss(bss);
7d930bc3 72 goto out;
df7fc0f9
JB
73 }
74
ea416a79
JB
75 if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
76 /*
77 * This is for the userspace SME, the CONNECTING
78 * state will be changed to CONNECTED by
79 * __cfg80211_connect_result() below.
80 */
81 wdev->sme_state = CFG80211_SME_CONNECTING;
82 }
83
95de817b 84 /* this consumes the bss reference */
df7fc0f9
JB
85 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
86 status_code,
95de817b 87 status_code == WLAN_STATUS_SUCCESS, bss);
f401a6f7 88 out:
667503dd 89 wdev_unlock(wdev);
6039f6d2
JM
90}
91EXPORT_SYMBOL(cfg80211_send_rx_assoc);
92
ce470613 93void __cfg80211_send_deauth(struct net_device *dev,
667503dd 94 const u8 *buf, size_t len)
6039f6d2 95{
6829c878
JB
96 struct wireless_dev *wdev = dev->ieee80211_ptr;
97 struct wiphy *wiphy = wdev->wiphy;
6039f6d2 98 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
6829c878 99 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
19957bb3 100 const u8 *bssid = mgmt->bssid;
95de817b 101 bool was_current = false;
6829c878 102
667503dd 103 ASSERT_WDEV_LOCK(wdev);
cb0b4beb 104
19957bb3 105 if (wdev->current_bss &&
ac422d3c 106 ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
19957bb3
JB
107 cfg80211_unhold_bss(wdev->current_bss);
108 cfg80211_put_bss(&wdev->current_bss->pub);
109 wdev->current_bss = NULL;
3f3b6a8d 110 was_current = true;
19957bb3 111 }
19957bb3 112
5fba4af3
JB
113 nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
114
3f3b6a8d 115 if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) {
6829c878
JB
116 u16 reason_code;
117 bool from_ap;
118
119 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
120
ac422d3c 121 from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
667503dd 122 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
6829c878 123 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
667503dd
JB
124 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
125 WLAN_STATUS_UNSPECIFIED_FAILURE,
df7fc0f9 126 false, NULL);
667503dd
JB
127 }
128}
ce470613 129EXPORT_SYMBOL(__cfg80211_send_deauth);
667503dd 130
ce470613 131void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
667503dd
JB
132{
133 struct wireless_dev *wdev = dev->ieee80211_ptr;
134
ce470613
HS
135 wdev_lock(wdev);
136 __cfg80211_send_deauth(dev, buf, len);
137 wdev_unlock(wdev);
6039f6d2 138}
53b46b84 139EXPORT_SYMBOL(cfg80211_send_deauth);
6039f6d2 140
ce470613 141void __cfg80211_send_disassoc(struct net_device *dev,
667503dd 142 const u8 *buf, size_t len)
6039f6d2 143{
6829c878
JB
144 struct wireless_dev *wdev = dev->ieee80211_ptr;
145 struct wiphy *wiphy = wdev->wiphy;
6039f6d2 146 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
6829c878 147 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
19957bb3 148 const u8 *bssid = mgmt->bssid;
19957bb3
JB
149 u16 reason_code;
150 bool from_ap;
6829c878 151
596a07c1 152 ASSERT_WDEV_LOCK(wdev);
cb0b4beb
JB
153
154 nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
a3b8b056 155
596a07c1
JB
156 if (wdev->sme_state != CFG80211_SME_CONNECTED)
157 return;
6829c878 158
19957bb3 159 if (wdev->current_bss &&
ac422d3c 160 ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
95de817b
JB
161 cfg80211_sme_disassoc(dev, wdev->current_bss);
162 cfg80211_unhold_bss(wdev->current_bss);
163 cfg80211_put_bss(&wdev->current_bss->pub);
164 wdev->current_bss = NULL;
19957bb3
JB
165 } else
166 WARN_ON(1);
6829c878 167
6829c878 168
19957bb3
JB
169 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
170
ac422d3c 171 from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
667503dd 172 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
667503dd 173}
ce470613 174EXPORT_SYMBOL(__cfg80211_send_disassoc);
667503dd 175
ce470613 176void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
667503dd
JB
177{
178 struct wireless_dev *wdev = dev->ieee80211_ptr;
179
ce470613
HS
180 wdev_lock(wdev);
181 __cfg80211_send_disassoc(dev, buf, len);
182 wdev_unlock(wdev);
1965c853 183}
6829c878 184EXPORT_SYMBOL(cfg80211_send_disassoc);
1965c853 185
cf4e594e
JM
186void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
187 size_t len)
188{
189 struct wireless_dev *wdev = dev->ieee80211_ptr;
190 struct wiphy *wiphy = wdev->wiphy;
191 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
192
193 nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC);
194}
195EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
196
197void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
198 size_t len)
199{
200 struct wireless_dev *wdev = dev->ieee80211_ptr;
201 struct wiphy *wiphy = wdev->wiphy;
202 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
203
204 nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC);
205}
206EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
207
a58ce43f
JB
208void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
209{
210 struct wireless_dev *wdev = dev->ieee80211_ptr;
211 struct wiphy *wiphy = wdev->wiphy;
212 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
213
214 wdev_lock(wdev);
215
216 nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
217 if (wdev->sme_state == CFG80211_SME_CONNECTING)
218 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
219 WLAN_STATUS_UNSPECIFIED_FAILURE,
220 false, NULL);
221
667503dd 222 wdev_unlock(wdev);
1965c853
JM
223}
224EXPORT_SYMBOL(cfg80211_send_auth_timeout);
225
cb0b4beb 226void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
1965c853 227{
6829c878
JB
228 struct wireless_dev *wdev = dev->ieee80211_ptr;
229 struct wiphy *wiphy = wdev->wiphy;
1965c853 230 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
19957bb3 231
667503dd 232 wdev_lock(wdev);
cb0b4beb
JB
233
234 nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
6829c878 235 if (wdev->sme_state == CFG80211_SME_CONNECTING)
667503dd
JB
236 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
237 WLAN_STATUS_UNSPECIFIED_FAILURE,
df7fc0f9 238 false, NULL);
19957bb3 239
667503dd 240 wdev_unlock(wdev);
1965c853
JM
241}
242EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
243
a3b8b056
JM
244void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
245 enum nl80211_key_type key_type, int key_id,
e6d6e342 246 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
247{
248 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
249 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
3d23e349 250#ifdef CONFIG_CFG80211_WEXT
f58d4ed9 251 union iwreq_data wrqu;
e6d6e342 252 char *buf = kmalloc(128, gfp);
f58d4ed9
JB
253
254 if (buf) {
255 sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
256 "keyid=%d %scast addr=%pM)", key_id,
257 key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
258 addr);
259 memset(&wrqu, 0, sizeof(wrqu));
260 wrqu.data.length = strlen(buf);
261 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
262 kfree(buf);
263 }
264#endif
265
e6d6e342 266 nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
a3b8b056
JM
267}
268EXPORT_SYMBOL(cfg80211_michael_mic_failure);
19957bb3
JB
269
270/* some MLME handling for userspace SME */
667503dd
JB
271int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
272 struct net_device *dev,
273 struct ieee80211_channel *chan,
274 enum nl80211_auth_type auth_type,
275 const u8 *bssid,
276 const u8 *ssid, int ssid_len,
fffd0934 277 const u8 *ie, int ie_len,
e39e5b5e
JM
278 const u8 *key, int key_len, int key_idx,
279 const u8 *sae_data, int sae_data_len)
19957bb3
JB
280{
281 struct wireless_dev *wdev = dev->ieee80211_ptr;
282 struct cfg80211_auth_request req;
95de817b 283 int err;
19957bb3 284
667503dd
JB
285 ASSERT_WDEV_LOCK(wdev);
286
fffd0934
JB
287 if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
288 if (!key || !key_len || key_idx < 0 || key_idx > 4)
289 return -EINVAL;
290
0a9b5e17 291 if (wdev->current_bss &&
ac422d3c 292 ether_addr_equal(bssid, wdev->current_bss->pub.bssid))
0a9b5e17
JB
293 return -EALREADY;
294
19957bb3
JB
295 memset(&req, 0, sizeof(req));
296
297 req.ie = ie;
298 req.ie_len = ie_len;
e39e5b5e
JM
299 req.sae_data = sae_data;
300 req.sae_data_len = sae_data_len;
19957bb3
JB
301 req.auth_type = auth_type;
302 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
303 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
fffd0934
JB
304 req.key = key;
305 req.key_len = key_len;
306 req.key_idx = key_idx;
19957bb3
JB
307 if (!req.bss)
308 return -ENOENT;
309
e4e32459
MK
310 err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
311 CHAN_MODE_SHARED);
312 if (err)
313 goto out;
314
e35e4d28 315 err = rdev_auth(rdev, dev, &req);
19957bb3 316
e4e32459 317out:
95de817b 318 cfg80211_put_bss(req.bss);
19957bb3
JB
319 return err;
320}
321
667503dd
JB
322int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
323 struct net_device *dev, struct ieee80211_channel *chan,
324 enum nl80211_auth_type auth_type, const u8 *bssid,
325 const u8 *ssid, int ssid_len,
fffd0934 326 const u8 *ie, int ie_len,
e39e5b5e
JM
327 const u8 *key, int key_len, int key_idx,
328 const u8 *sae_data, int sae_data_len)
667503dd
JB
329{
330 int err;
331
e4e32459 332 mutex_lock(&rdev->devlist_mtx);
667503dd
JB
333 wdev_lock(dev->ieee80211_ptr);
334 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
fffd0934 335 ssid, ssid_len, ie, ie_len,
e39e5b5e
JM
336 key, key_len, key_idx,
337 sae_data, sae_data_len);
667503dd 338 wdev_unlock(dev->ieee80211_ptr);
e4e32459 339 mutex_unlock(&rdev->devlist_mtx);
667503dd
JB
340
341 return err;
342}
343
7e7c8926
BG
344/* Do a logical ht_capa &= ht_capa_mask. */
345void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
346 const struct ieee80211_ht_cap *ht_capa_mask)
347{
348 int i;
349 u8 *p1, *p2;
350 if (!ht_capa_mask) {
351 memset(ht_capa, 0, sizeof(*ht_capa));
352 return;
353 }
354
355 p1 = (u8*)(ht_capa);
356 p2 = (u8*)(ht_capa_mask);
357 for (i = 0; i<sizeof(*ht_capa); i++)
358 p1[i] &= p2[i];
359}
360
667503dd
JB
361int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
362 struct net_device *dev,
363 struct ieee80211_channel *chan,
364 const u8 *bssid, const u8 *prev_bssid,
365 const u8 *ssid, int ssid_len,
366 const u8 *ie, int ie_len, bool use_mfp,
7e7c8926
BG
367 struct cfg80211_crypto_settings *crypt,
368 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
369 struct ieee80211_ht_cap *ht_capa_mask)
19957bb3
JB
370{
371 struct wireless_dev *wdev = dev->ieee80211_ptr;
372 struct cfg80211_assoc_request req;
95de817b 373 int err;
24b6b15f 374 bool was_connected = false;
19957bb3 375
667503dd
JB
376 ASSERT_WDEV_LOCK(wdev);
377
19957bb3
JB
378 memset(&req, 0, sizeof(req));
379
24b6b15f 380 if (wdev->current_bss && prev_bssid &&
ac422d3c 381 ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) {
24b6b15f
JM
382 /*
383 * Trying to reassociate: Allow this to proceed and let the old
384 * association to be dropped when the new one is completed.
385 */
386 if (wdev->sme_state == CFG80211_SME_CONNECTED) {
387 was_connected = true;
388 wdev->sme_state = CFG80211_SME_CONNECTING;
389 }
390 } else if (wdev->current_bss)
19957bb3
JB
391 return -EALREADY;
392
393 req.ie = ie;
394 req.ie_len = ie_len;
395 memcpy(&req.crypto, crypt, sizeof(req.crypto));
396 req.use_mfp = use_mfp;
3e5d7649 397 req.prev_bssid = prev_bssid;
7e7c8926
BG
398 req.flags = assoc_flags;
399 if (ht_capa)
400 memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
401 if (ht_capa_mask)
402 memcpy(&req.ht_capa_mask, ht_capa_mask,
403 sizeof(req.ht_capa_mask));
404 cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
405 rdev->wiphy.ht_capa_mod_mask);
406
19957bb3
JB
407 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
408 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
24b6b15f
JM
409 if (!req.bss) {
410 if (was_connected)
411 wdev->sme_state = CFG80211_SME_CONNECTED;
19957bb3 412 return -ENOENT;
24b6b15f 413 }
19957bb3 414
e4e32459
MK
415 err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
416 CHAN_MODE_SHARED);
417 if (err)
418 goto out;
419
e35e4d28 420 err = rdev_assoc(rdev, dev, &req);
19957bb3 421
e4e32459 422out:
95de817b
JB
423 if (err) {
424 if (was_connected)
425 wdev->sme_state = CFG80211_SME_CONNECTED;
426 cfg80211_put_bss(req.bss);
19957bb3
JB
427 }
428
19957bb3
JB
429 return err;
430}
431
667503dd
JB
432int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
433 struct net_device *dev,
434 struct ieee80211_channel *chan,
435 const u8 *bssid, const u8 *prev_bssid,
436 const u8 *ssid, int ssid_len,
437 const u8 *ie, int ie_len, bool use_mfp,
7e7c8926
BG
438 struct cfg80211_crypto_settings *crypt,
439 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
440 struct ieee80211_ht_cap *ht_capa_mask)
667503dd
JB
441{
442 struct wireless_dev *wdev = dev->ieee80211_ptr;
443 int err;
444
e4e32459 445 mutex_lock(&rdev->devlist_mtx);
667503dd
JB
446 wdev_lock(wdev);
447 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
7e7c8926
BG
448 ssid, ssid_len, ie, ie_len, use_mfp, crypt,
449 assoc_flags, ht_capa, ht_capa_mask);
667503dd 450 wdev_unlock(wdev);
e4e32459 451 mutex_unlock(&rdev->devlist_mtx);
667503dd
JB
452
453 return err;
454}
455
456int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
457 struct net_device *dev, const u8 *bssid,
d5cdfacb
JM
458 const u8 *ie, int ie_len, u16 reason,
459 bool local_state_change)
19957bb3
JB
460{
461 struct wireless_dev *wdev = dev->ieee80211_ptr;
95de817b
JB
462 struct cfg80211_deauth_request req = {
463 .bssid = bssid,
464 .reason_code = reason,
465 .ie = ie,
466 .ie_len = ie_len,
467 };
19957bb3 468
667503dd
JB
469 ASSERT_WDEV_LOCK(wdev);
470
95de817b
JB
471 if (local_state_change) {
472 if (wdev->current_bss &&
ac422d3c 473 ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
95de817b
JB
474 cfg80211_unhold_bss(wdev->current_bss);
475 cfg80211_put_bss(&wdev->current_bss->pub);
476 wdev->current_bss = NULL;
19957bb3 477 }
19957bb3 478
95de817b
JB
479 return 0;
480 }
19957bb3 481
e35e4d28 482 return rdev_deauth(rdev, dev, &req);
19957bb3
JB
483}
484
667503dd
JB
485int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
486 struct net_device *dev, const u8 *bssid,
d5cdfacb
JM
487 const u8 *ie, int ie_len, u16 reason,
488 bool local_state_change)
667503dd
JB
489{
490 struct wireless_dev *wdev = dev->ieee80211_ptr;
491 int err;
492
493 wdev_lock(wdev);
d5cdfacb
JM
494 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
495 local_state_change);
667503dd
JB
496 wdev_unlock(wdev);
497
498 return err;
499}
500
501static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
502 struct net_device *dev, const u8 *bssid,
d5cdfacb
JM
503 const u8 *ie, int ie_len, u16 reason,
504 bool local_state_change)
19957bb3
JB
505{
506 struct wireless_dev *wdev = dev->ieee80211_ptr;
507 struct cfg80211_disassoc_request req;
508
667503dd
JB
509 ASSERT_WDEV_LOCK(wdev);
510
f9d6b402
JB
511 if (wdev->sme_state != CFG80211_SME_CONNECTED)
512 return -ENOTCONN;
513
514 if (WARN_ON(!wdev->current_bss))
515 return -ENOTCONN;
516
19957bb3
JB
517 memset(&req, 0, sizeof(req));
518 req.reason_code = reason;
d5cdfacb 519 req.local_state_change = local_state_change;
19957bb3
JB
520 req.ie = ie;
521 req.ie_len = ie_len;
ac422d3c 522 if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
19957bb3
JB
523 req.bss = &wdev->current_bss->pub;
524 else
525 return -ENOTCONN;
526
e35e4d28 527 return rdev_disassoc(rdev, dev, &req);
667503dd
JB
528}
529
530int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
531 struct net_device *dev, const u8 *bssid,
d5cdfacb
JM
532 const u8 *ie, int ie_len, u16 reason,
533 bool local_state_change)
667503dd
JB
534{
535 struct wireless_dev *wdev = dev->ieee80211_ptr;
536 int err;
537
538 wdev_lock(wdev);
d5cdfacb
JM
539 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
540 local_state_change);
667503dd
JB
541 wdev_unlock(wdev);
542
543 return err;
19957bb3
JB
544}
545
546void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
547 struct net_device *dev)
548{
549 struct wireless_dev *wdev = dev->ieee80211_ptr;
550 struct cfg80211_deauth_request req;
95de817b 551 u8 bssid[ETH_ALEN];
19957bb3 552
667503dd
JB
553 ASSERT_WDEV_LOCK(wdev);
554
19957bb3
JB
555 if (!rdev->ops->deauth)
556 return;
557
558 memset(&req, 0, sizeof(req));
559 req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
560 req.ie = NULL;
561 req.ie_len = 0;
562
95de817b
JB
563 if (!wdev->current_bss)
564 return;
19957bb3 565
95de817b
JB
566 memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
567 req.bssid = bssid;
e35e4d28 568 rdev_deauth(rdev, dev, &req);
95de817b
JB
569
570 if (wdev->current_bss) {
571 cfg80211_unhold_bss(wdev->current_bss);
572 cfg80211_put_bss(&wdev->current_bss->pub);
573 wdev->current_bss = NULL;
19957bb3
JB
574 }
575}
9588bbd5 576
71bbc994 577void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
9588bbd5
JM
578 struct ieee80211_channel *chan,
579 enum nl80211_channel_type channel_type,
580 unsigned int duration, gfp_t gfp)
581{
71bbc994 582 struct wiphy *wiphy = wdev->wiphy;
9588bbd5
JM
583 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
584
71bbc994 585 nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
9588bbd5
JM
586 duration, gfp);
587}
588EXPORT_SYMBOL(cfg80211_ready_on_channel);
589
71bbc994 590void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
9588bbd5
JM
591 struct ieee80211_channel *chan,
592 enum nl80211_channel_type channel_type,
593 gfp_t gfp)
594{
71bbc994 595 struct wiphy *wiphy = wdev->wiphy;
9588bbd5
JM
596 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
597
71bbc994 598 nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
9588bbd5
JM
599 channel_type, gfp);
600}
601EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
98b62183
JB
602
603void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
604 struct station_info *sinfo, gfp_t gfp)
605{
606 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
607 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
608
609 nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
610}
611EXPORT_SYMBOL(cfg80211_new_sta);
026331c4 612
ec15e68b
JM
613void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
614{
615 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
616 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
617
618 nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp);
619}
620EXPORT_SYMBOL(cfg80211_del_sta);
621
ed44a951
PP
622void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
623 enum nl80211_connect_failed_reason reason,
624 gfp_t gfp)
625{
626 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
627 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
628
629 nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp);
630}
631EXPORT_SYMBOL(cfg80211_conn_failed);
632
2e161f78 633struct cfg80211_mgmt_registration {
026331c4
JM
634 struct list_head list;
635
15e47304 636 u32 nlportid;
026331c4
JM
637
638 int match_len;
639
2e161f78
JB
640 __le16 frame_type;
641
026331c4
JM
642 u8 match[];
643};
644
15e47304 645int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
2e161f78
JB
646 u16 frame_type, const u8 *match_data,
647 int match_len)
026331c4 648{
271733cf
JB
649 struct wiphy *wiphy = wdev->wiphy;
650 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
2e161f78 651 struct cfg80211_mgmt_registration *reg, *nreg;
026331c4 652 int err = 0;
2e161f78
JB
653 u16 mgmt_type;
654
655 if (!wdev->wiphy->mgmt_stypes)
656 return -EOPNOTSUPP;
657
658 if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
659 return -EINVAL;
660
661 if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
662 return -EINVAL;
663
664 mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
665 if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
666 return -EINVAL;
026331c4
JM
667
668 nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
669 if (!nreg)
670 return -ENOMEM;
671
2e161f78 672 spin_lock_bh(&wdev->mgmt_registrations_lock);
026331c4 673
2e161f78 674 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
026331c4
JM
675 int mlen = min(match_len, reg->match_len);
676
2e161f78
JB
677 if (frame_type != le16_to_cpu(reg->frame_type))
678 continue;
679
026331c4
JM
680 if (memcmp(reg->match, match_data, mlen) == 0) {
681 err = -EALREADY;
682 break;
683 }
684 }
685
686 if (err) {
687 kfree(nreg);
688 goto out;
689 }
690
691 memcpy(nreg->match, match_data, match_len);
692 nreg->match_len = match_len;
15e47304 693 nreg->nlportid = snd_portid;
2e161f78
JB
694 nreg->frame_type = cpu_to_le16(frame_type);
695 list_add(&nreg->list, &wdev->mgmt_registrations);
026331c4 696
271733cf 697 if (rdev->ops->mgmt_frame_register)
e35e4d28 698 rdev_mgmt_frame_register(rdev, wdev, frame_type, true);
271733cf 699
026331c4 700 out:
2e161f78 701 spin_unlock_bh(&wdev->mgmt_registrations_lock);
271733cf 702
026331c4
JM
703 return err;
704}
705
15e47304 706void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
026331c4 707{
271733cf
JB
708 struct wiphy *wiphy = wdev->wiphy;
709 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
2e161f78 710 struct cfg80211_mgmt_registration *reg, *tmp;
026331c4 711
2e161f78 712 spin_lock_bh(&wdev->mgmt_registrations_lock);
026331c4 713
2e161f78 714 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
15e47304 715 if (reg->nlportid != nlportid)
271733cf
JB
716 continue;
717
718 if (rdev->ops->mgmt_frame_register) {
719 u16 frame_type = le16_to_cpu(reg->frame_type);
720
e35e4d28
HG
721 rdev_mgmt_frame_register(rdev, wdev,
722 frame_type, false);
026331c4 723 }
271733cf
JB
724
725 list_del(&reg->list);
726 kfree(reg);
026331c4
JM
727 }
728
2e161f78 729 spin_unlock_bh(&wdev->mgmt_registrations_lock);
28946da7 730
15e47304
EB
731 if (nlportid == wdev->ap_unexpected_nlportid)
732 wdev->ap_unexpected_nlportid = 0;
026331c4
JM
733}
734
2e161f78 735void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
026331c4 736{
2e161f78 737 struct cfg80211_mgmt_registration *reg, *tmp;
026331c4 738
2e161f78 739 spin_lock_bh(&wdev->mgmt_registrations_lock);
026331c4 740
2e161f78 741 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
026331c4
JM
742 list_del(&reg->list);
743 kfree(reg);
744 }
745
2e161f78 746 spin_unlock_bh(&wdev->mgmt_registrations_lock);
026331c4
JM
747}
748
2e161f78 749int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
71bbc994 750 struct wireless_dev *wdev,
f7ca38df 751 struct ieee80211_channel *chan, bool offchan,
2e161f78 752 enum nl80211_channel_type channel_type,
f7ca38df 753 bool channel_type_valid, unsigned int wait,
e9f935e3 754 const u8 *buf, size_t len, bool no_cck,
e247bd90 755 bool dont_wait_for_ack, u64 *cookie)
026331c4 756{
026331c4 757 const struct ieee80211_mgmt *mgmt;
2e161f78
JB
758 u16 stype;
759
760 if (!wdev->wiphy->mgmt_stypes)
761 return -EOPNOTSUPP;
026331c4 762
2e161f78 763 if (!rdev->ops->mgmt_tx)
026331c4 764 return -EOPNOTSUPP;
2e161f78 765
026331c4
JM
766 if (len < 24 + 1)
767 return -EINVAL;
768
769 mgmt = (const struct ieee80211_mgmt *) buf;
2e161f78
JB
770
771 if (!ieee80211_is_mgmt(mgmt->frame_control))
026331c4 772 return -EINVAL;
2e161f78
JB
773
774 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
775 if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
776 return -EINVAL;
777
778 if (ieee80211_is_action(mgmt->frame_control) &&
779 mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
663fcafd
JB
780 int err = 0;
781
fe100acd
JB
782 wdev_lock(wdev);
783
663fcafd
JB
784 switch (wdev->iftype) {
785 case NL80211_IFTYPE_ADHOC:
786 case NL80211_IFTYPE_STATION:
787 case NL80211_IFTYPE_P2P_CLIENT:
788 if (!wdev->current_bss) {
789 err = -ENOTCONN;
790 break;
791 }
792
ac422d3c
JP
793 if (!ether_addr_equal(wdev->current_bss->pub.bssid,
794 mgmt->bssid)) {
663fcafd
JB
795 err = -ENOTCONN;
796 break;
797 }
798
799 /*
800 * check for IBSS DA must be done by driver as
801 * cfg80211 doesn't track the stations
802 */
803 if (wdev->iftype == NL80211_IFTYPE_ADHOC)
804 break;
fe100acd 805
663fcafd 806 /* for station, check that DA is the AP */
ac422d3c
JP
807 if (!ether_addr_equal(wdev->current_bss->pub.bssid,
808 mgmt->da)) {
663fcafd
JB
809 err = -ENOTCONN;
810 break;
811 }
812 break;
813 case NL80211_IFTYPE_AP:
814 case NL80211_IFTYPE_P2P_GO:
815 case NL80211_IFTYPE_AP_VLAN:
98104fde 816 if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)))
663fcafd
JB
817 err = -EINVAL;
818 break;
0778a6a3 819 case NL80211_IFTYPE_MESH_POINT:
ac422d3c 820 if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) {
0778a6a3
JC
821 err = -EINVAL;
822 break;
823 }
824 /*
825 * check for mesh DA must be done by driver as
826 * cfg80211 doesn't track the stations
827 */
828 break;
98104fde
JB
829 case NL80211_IFTYPE_P2P_DEVICE:
830 /*
831 * fall through, P2P device only supports
832 * public action frames
833 */
663fcafd
JB
834 default:
835 err = -EOPNOTSUPP;
836 break;
837 }
fe100acd 838 wdev_unlock(wdev);
663fcafd
JB
839
840 if (err)
841 return err;
026331c4
JM
842 }
843
98104fde 844 if (!ether_addr_equal(mgmt->sa, wdev_address(wdev)))
026331c4
JM
845 return -EINVAL;
846
847 /* Transmit the Action frame as requested by user space */
e35e4d28
HG
848 return rdev_mgmt_tx(rdev, wdev, chan, offchan,
849 channel_type, channel_type_valid,
850 wait, buf, len, no_cck, dont_wait_for_ack,
851 cookie);
026331c4
JM
852}
853
71bbc994 854bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
804483e9 855 const u8 *buf, size_t len, gfp_t gfp)
026331c4 856{
026331c4
JM
857 struct wiphy *wiphy = wdev->wiphy;
858 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
2e161f78
JB
859 struct cfg80211_mgmt_registration *reg;
860 const struct ieee80211_txrx_stypes *stypes =
861 &wiphy->mgmt_stypes[wdev->iftype];
862 struct ieee80211_mgmt *mgmt = (void *)buf;
863 const u8 *data;
864 int data_len;
026331c4 865 bool result = false;
2e161f78
JB
866 __le16 ftype = mgmt->frame_control &
867 cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
868 u16 stype;
026331c4 869
2e161f78 870 stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
026331c4 871
2e161f78
JB
872 if (!(stypes->rx & BIT(stype)))
873 return false;
026331c4 874
2e161f78
JB
875 data = buf + ieee80211_hdrlen(mgmt->frame_control);
876 data_len = len - ieee80211_hdrlen(mgmt->frame_control);
877
878 spin_lock_bh(&wdev->mgmt_registrations_lock);
879
880 list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
881 if (reg->frame_type != ftype)
882 continue;
026331c4 883
2e161f78 884 if (reg->match_len > data_len)
026331c4
JM
885 continue;
886
2e161f78 887 if (memcmp(reg->match, data, reg->match_len))
026331c4
JM
888 continue;
889
890 /* found match! */
891
892 /* Indicate the received Action frame to user space */
15e47304 893 if (nl80211_send_mgmt(rdev, wdev, reg->nlportid,
804483e9 894 freq, sig_mbm,
2e161f78 895 buf, len, gfp))
026331c4
JM
896 continue;
897
898 result = true;
899 break;
900 }
901
2e161f78 902 spin_unlock_bh(&wdev->mgmt_registrations_lock);
026331c4
JM
903
904 return result;
905}
2e161f78 906EXPORT_SYMBOL(cfg80211_rx_mgmt);
026331c4 907
71bbc994 908void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
2e161f78 909 const u8 *buf, size_t len, bool ack, gfp_t gfp)
026331c4 910{
026331c4
JM
911 struct wiphy *wiphy = wdev->wiphy;
912 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
913
914 /* Indicate TX status of the Action frame to user space */
71bbc994 915 nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
026331c4 916}
2e161f78 917EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
d6dc1a38
JO
918
919void cfg80211_cqm_rssi_notify(struct net_device *dev,
920 enum nl80211_cqm_rssi_threshold_event rssi_event,
921 gfp_t gfp)
922{
923 struct wireless_dev *wdev = dev->ieee80211_ptr;
924 struct wiphy *wiphy = wdev->wiphy;
925 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
926
927 /* Indicate roaming trigger event to user space */
928 nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
929}
930EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
c063dbf5
JB
931
932void cfg80211_cqm_pktloss_notify(struct net_device *dev,
933 const u8 *peer, u32 num_packets, gfp_t gfp)
934{
935 struct wireless_dev *wdev = dev->ieee80211_ptr;
936 struct wiphy *wiphy = wdev->wiphy;
937 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
938
939 /* Indicate roaming trigger event to user space */
940 nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
941}
942EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
e5497d76 943
84f10708
TP
944void cfg80211_cqm_txe_notify(struct net_device *dev,
945 const u8 *peer, u32 num_packets,
946 u32 rate, u32 intvl, gfp_t gfp)
947{
948 struct wireless_dev *wdev = dev->ieee80211_ptr;
949 struct wiphy *wiphy = wdev->wiphy;
950 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
951
952 nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets,
953 rate, intvl, gfp);
954}
955EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
956
e5497d76
JB
957void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
958 const u8 *replay_ctr, gfp_t gfp)
959{
960 struct wireless_dev *wdev = dev->ieee80211_ptr;
961 struct wiphy *wiphy = wdev->wiphy;
962 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
963
964 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
965}
966EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
c9df56b4
JM
967
968void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
969 const u8 *bssid, bool preauth, gfp_t gfp)
970{
971 struct wireless_dev *wdev = dev->ieee80211_ptr;
972 struct wiphy *wiphy = wdev->wiphy;
973 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
974
975 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
976}
977EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
28946da7 978
5314526b
TP
979void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
980 enum nl80211_channel_type type)
981{
982 struct wireless_dev *wdev = dev->ieee80211_ptr;
983 struct wiphy *wiphy = wdev->wiphy;
984 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
985 struct ieee80211_channel *chan;
986
987 wdev_lock(wdev);
988
989 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
990 wdev->iftype != NL80211_IFTYPE_P2P_GO))
991 goto out;
992
993 chan = rdev_freq_to_chan(rdev, freq, type);
994 if (WARN_ON(!chan))
995 goto out;
996
f4489ebe 997 wdev->channel = chan;
5314526b
TP
998 nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
999out:
1000 wdev_unlock(wdev);
1001 return;
1002}
1003EXPORT_SYMBOL(cfg80211_ch_switch_notify);
1004
28946da7
JB
1005bool cfg80211_rx_spurious_frame(struct net_device *dev,
1006 const u8 *addr, gfp_t gfp)
1007{
1008 struct wireless_dev *wdev = dev->ieee80211_ptr;
1009
1010 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
1011 wdev->iftype != NL80211_IFTYPE_P2P_GO))
1012 return false;
1013
1014 return nl80211_unexpected_frame(dev, addr, gfp);
1015}
1016EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8
JB
1017
1018bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
1019 const u8 *addr, gfp_t gfp)
1020{
1021 struct wireless_dev *wdev = dev->ieee80211_ptr;
1022
1023 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
1024 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
1025 wdev->iftype != NL80211_IFTYPE_AP_VLAN))
1026 return false;
1027
1028 return nl80211_unexpected_4addr_frame(dev, addr, gfp);
1029}
1030EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
This page took 0.309404 seconds and 5 git commands to generate.