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