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