2 * cfg80211 MLME SAP interface
4 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
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>
18 void cfg80211_send_rx_auth(struct net_device
*dev
, const u8
*buf
, size_t len
)
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
;
26 u16 status
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
31 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
32 if (wdev
->authtry_bsses
[i
] &&
33 memcmp(wdev
->authtry_bsses
[i
]->pub
.bssid
, bssid
,
35 if (status
== WLAN_STATUS_SUCCESS
) {
36 wdev
->auth_bsses
[i
] = wdev
->authtry_bsses
[i
];
38 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
39 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
41 wdev
->authtry_bsses
[i
] = NULL
;
48 nl80211_send_rx_auth(rdev
, dev
, buf
, len
, GFP_KERNEL
);
49 cfg80211_sme_rx_auth(dev
, buf
, len
);
54 EXPORT_SYMBOL(cfg80211_send_rx_auth
);
56 void cfg80211_send_rx_assoc(struct net_device
*dev
, const u8
*buf
, size_t len
)
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
;
69 status_code
= le16_to_cpu(mgmt
->u
.assoc_resp
.status_code
);
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.
77 if (status_code
!= WLAN_STATUS_SUCCESS
&& wdev
->conn
&&
78 cfg80211_sme_failed_reassoc(wdev
))
81 nl80211_send_rx_assoc(rdev
, dev
, buf
, len
, GFP_KERNEL
);
83 if (status_code
== WLAN_STATUS_SUCCESS
) {
84 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
85 if (!wdev
->auth_bsses
[i
])
87 if (memcmp(wdev
->auth_bsses
[i
]->pub
.bssid
, mgmt
->bssid
,
89 bss
= wdev
->auth_bsses
[i
];
90 wdev
->auth_bsses
[i
] = NULL
;
91 /* additional reference to drop hold */
92 cfg80211_ref_bss(bss
);
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.
109 } else if (wdev
->conn
) {
110 cfg80211_sme_failed_assoc(wdev
);
112 * do not call connect_result() now because the
113 * sme will schedule work that does it later.
118 if (!wdev
->conn
&& wdev
->sme_state
== CFG80211_SME_IDLE
) {
120 * This is for the userspace SME, the CONNECTING
121 * state will be changed to CONNECTED by
122 * __cfg80211_connect_result() below.
124 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
127 /* this consumes one bss reference (unless bss is NULL) */
128 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, ie
, len
- ieoffs
,
130 status_code
== WLAN_STATUS_SUCCESS
,
131 bss
? &bss
->pub
: NULL
);
132 /* drop hold now, and also reference acquired above */
134 cfg80211_unhold_bss(bss
);
135 cfg80211_put_bss(&bss
->pub
);
141 EXPORT_SYMBOL(cfg80211_send_rx_assoc
);
143 void __cfg80211_send_deauth(struct net_device
*dev
,
144 const u8
*buf
, size_t len
)
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
;
152 bool found
= false, was_current
= false;
154 ASSERT_WDEV_LOCK(wdev
);
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
;
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
;
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
;
185 nl80211_send_deauth(rdev
, dev
, buf
, len
, GFP_KERNEL
);
187 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
&& was_current
) {
191 reason_code
= le16_to_cpu(mgmt
->u
.deauth
.reason_code
);
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
,
201 EXPORT_SYMBOL(__cfg80211_send_deauth
);
203 void cfg80211_send_deauth(struct net_device
*dev
, const u8
*buf
, size_t len
)
205 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
208 __cfg80211_send_deauth(dev
, buf
, len
);
211 EXPORT_SYMBOL(cfg80211_send_deauth
);
213 void __cfg80211_send_disassoc(struct net_device
*dev
,
214 const u8
*buf
, size_t len
)
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
;
226 ASSERT_WDEV_LOCK(wdev
);
228 nl80211_send_disassoc(rdev
, dev
, buf
, len
, GFP_KERNEL
);
230 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
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
])
238 wdev
->auth_bsses
[i
] = wdev
->current_bss
;
239 wdev
->current_bss
= NULL
;
241 cfg80211_sme_disassoc(dev
, i
);
249 reason_code
= le16_to_cpu(mgmt
->u
.disassoc
.reason_code
);
251 from_ap
= memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0;
252 __cfg80211_disconnected(dev
, NULL
, 0, reason_code
, from_ap
);
254 EXPORT_SYMBOL(__cfg80211_send_disassoc
);
256 void cfg80211_send_disassoc(struct net_device
*dev
, const u8
*buf
, size_t len
)
258 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
261 __cfg80211_send_disassoc(dev
, buf
, len
);
264 EXPORT_SYMBOL(cfg80211_send_disassoc
);
266 static void __cfg80211_auth_remove(struct wireless_dev
*wdev
, const u8
*addr
)
271 ASSERT_WDEV_LOCK(wdev
);
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
;
288 void __cfg80211_auth_canceled(struct net_device
*dev
, const u8
*addr
)
290 __cfg80211_auth_remove(dev
->ieee80211_ptr
, addr
);
292 EXPORT_SYMBOL(__cfg80211_auth_canceled
);
294 void cfg80211_send_auth_timeout(struct net_device
*dev
, const u8
*addr
)
296 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
297 struct wiphy
*wiphy
= wdev
->wiphy
;
298 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
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
,
308 __cfg80211_auth_remove(wdev
, addr
);
312 EXPORT_SYMBOL(cfg80211_send_auth_timeout
);
314 void cfg80211_send_assoc_timeout(struct net_device
*dev
, const u8
*addr
)
316 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
317 struct wiphy
*wiphy
= wdev
->wiphy
;
318 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
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
,
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
;
346 EXPORT_SYMBOL(cfg80211_send_assoc_timeout
);
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
)
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
);
359 sprintf(buf
, "MLME-MICHAELMICFAILURE.indication("
360 "keyid=%d %scast addr=%pM)", key_id
,
361 key_type
== NL80211_KEYTYPE_GROUP
? "broad" : "uni",
363 memset(&wrqu
, 0, sizeof(wrqu
));
364 wrqu
.data
.length
= strlen(buf
);
365 wireless_send_event(dev
, IWEVCUSTOM
, &wrqu
, buf
);
370 nl80211_michael_mic_failure(rdev
, dev
, addr
, key_type
, key_id
, tsc
, gfp
);
372 EXPORT_SYMBOL(cfg80211_michael_mic_failure
);
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
,
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
)
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;
390 ASSERT_WDEV_LOCK(wdev
);
392 if (auth_type
== NL80211_AUTHTYPE_SHARED_KEY
)
393 if (!key
|| !key_len
|| key_idx
< 0 || key_idx
> 4)
396 if (wdev
->current_bss
&&
397 memcmp(bssid
, wdev
->current_bss
->pub
.bssid
, ETH_ALEN
) == 0)
400 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
401 if (wdev
->authtry_bsses
[i
] &&
402 memcmp(bssid
, wdev
->authtry_bsses
[i
]->pub
.bssid
,
405 if (wdev
->auth_bsses
[i
] &&
406 memcmp(bssid
, wdev
->auth_bsses
[i
]->pub
.bssid
,
411 memset(&req
, 0, sizeof(req
));
413 req
.local_state_change
= local_state_change
;
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
);
420 req
.key_len
= key_len
;
421 req
.key_idx
= key_idx
;
425 bss
= bss_from_pub(req
.bss
);
427 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
428 if (!wdev
->auth_bsses
[i
] && !wdev
->authtry_bsses
[i
]) {
434 /* we need one free slot for disassoc and one for this auth */
440 if (local_state_change
)
441 wdev
->auth_bsses
[slot
] = bss
;
443 wdev
->authtry_bsses
[slot
] = bss
;
444 cfg80211_hold_bss(bss
);
446 err
= rdev
->ops
->auth(&rdev
->wiphy
, dev
, &req
);
448 if (local_state_change
)
449 wdev
->auth_bsses
[slot
] = NULL
;
451 wdev
->authtry_bsses
[slot
] = NULL
;
452 cfg80211_unhold_bss(bss
);
457 cfg80211_put_bss(req
.bss
);
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
)
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
);
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
)
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;
494 ASSERT_WDEV_LOCK(wdev
);
496 memset(&req
, 0, sizeof(req
));
498 if (wdev
->current_bss
&& prev_bssid
&&
499 memcmp(wdev
->current_bss
->pub
.bssid
, prev_bssid
, ETH_ALEN
) == 0) {
501 * Trying to reassociate: Allow this to proceed and let the old
502 * association to be dropped when the new one is completed.
504 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
) {
505 was_connected
= true;
506 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
508 } else if (wdev
->current_bss
)
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
);
520 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
524 bss
= bss_from_pub(req
.bss
);
526 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
527 if (bss
== wdev
->auth_bsses
[i
]) {
538 err
= rdev
->ops
->assoc(&rdev
->wiphy
, dev
, &req
);
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
);
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
)
555 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
559 err
= __cfg80211_mlme_assoc(rdev
, dev
, chan
, bssid
, prev_bssid
,
560 ssid
, ssid_len
, ie
, ie_len
, use_mfp
, crypt
);
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
)
571 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
572 struct cfg80211_deauth_request req
;
575 ASSERT_WDEV_LOCK(wdev
);
577 memset(&req
, 0, sizeof(req
));
578 req
.reason_code
= reason
;
579 req
.local_state_change
= local_state_change
;
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
;
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
;
601 return rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
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
)
609 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
613 err
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, ie
, ie_len
, reason
,
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
)
625 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
626 struct cfg80211_disassoc_request req
;
628 ASSERT_WDEV_LOCK(wdev
);
630 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
633 if (WARN_ON(!wdev
->current_bss
))
636 memset(&req
, 0, sizeof(req
));
637 req
.reason_code
= reason
;
638 req
.local_state_change
= local_state_change
;
641 if (memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0)
642 req
.bss
= &wdev
->current_bss
->pub
;
646 return rdev
->ops
->disassoc(&rdev
->wiphy
, dev
, &req
, wdev
);
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
)
654 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
658 err
= __cfg80211_mlme_disassoc(rdev
, dev
, bssid
, ie
, ie_len
, reason
,
665 void cfg80211_mlme_down(struct cfg80211_registered_device
*rdev
,
666 struct net_device
*dev
)
668 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
669 struct cfg80211_deauth_request req
;
672 ASSERT_WDEV_LOCK(wdev
);
674 if (!rdev
->ops
->deauth
)
677 memset(&req
, 0, sizeof(req
));
678 req
.reason_code
= WLAN_REASON_DEAUTH_LEAVING
;
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
;
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
;
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
;
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
)
719 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
720 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
722 nl80211_send_remain_on_channel(rdev
, dev
, cookie
, chan
, channel_type
,
725 EXPORT_SYMBOL(cfg80211_ready_on_channel
);
727 void cfg80211_remain_on_channel_expired(struct net_device
*dev
,
729 struct ieee80211_channel
*chan
,
730 enum nl80211_channel_type channel_type
,
733 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
734 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
736 nl80211_send_remain_on_channel_cancel(rdev
, dev
, cookie
, chan
,
739 EXPORT_SYMBOL(cfg80211_remain_on_channel_expired
);
741 void cfg80211_new_sta(struct net_device
*dev
, const u8
*mac_addr
,
742 struct station_info
*sinfo
, gfp_t gfp
)
744 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
745 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
747 nl80211_send_sta_event(rdev
, dev
, mac_addr
, sinfo
, gfp
);
749 EXPORT_SYMBOL(cfg80211_new_sta
);
751 struct cfg80211_mgmt_registration
{
752 struct list_head list
;
763 int cfg80211_mlme_register_mgmt(struct wireless_dev
*wdev
, u32 snd_pid
,
764 u16 frame_type
, const u8
*match_data
,
767 struct wiphy
*wiphy
= wdev
->wiphy
;
768 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
769 struct cfg80211_mgmt_registration
*reg
, *nreg
;
773 if (!wdev
->wiphy
->mgmt_stypes
)
776 if ((frame_type
& IEEE80211_FCTL_FTYPE
) != IEEE80211_FTYPE_MGMT
)
779 if (frame_type
& ~(IEEE80211_FCTL_FTYPE
| IEEE80211_FCTL_STYPE
))
782 mgmt_type
= (frame_type
& IEEE80211_FCTL_STYPE
) >> 4;
783 if (!(wdev
->wiphy
->mgmt_stypes
[wdev
->iftype
].rx
& BIT(mgmt_type
)))
786 nreg
= kzalloc(sizeof(*reg
) + match_len
, GFP_KERNEL
);
790 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
792 list_for_each_entry(reg
, &wdev
->mgmt_registrations
, list
) {
793 int mlen
= min(match_len
, reg
->match_len
);
795 if (frame_type
!= le16_to_cpu(reg
->frame_type
))
798 if (memcmp(reg
->match
, match_data
, mlen
) == 0) {
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
);
815 if (rdev
->ops
->mgmt_frame_register
)
816 rdev
->ops
->mgmt_frame_register(wiphy
, wdev
->netdev
,
820 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
825 void cfg80211_mlme_unregister_socket(struct wireless_dev
*wdev
, u32 nlpid
)
827 struct wiphy
*wiphy
= wdev
->wiphy
;
828 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
829 struct cfg80211_mgmt_registration
*reg
, *tmp
;
831 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
833 list_for_each_entry_safe(reg
, tmp
, &wdev
->mgmt_registrations
, list
) {
834 if (reg
->nlpid
!= nlpid
)
837 if (rdev
->ops
->mgmt_frame_register
) {
838 u16 frame_type
= le16_to_cpu(reg
->frame_type
);
840 rdev
->ops
->mgmt_frame_register(wiphy
, wdev
->netdev
,
844 list_del(®
->list
);
848 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
851 void cfg80211_mlme_purge_registrations(struct wireless_dev
*wdev
)
853 struct cfg80211_mgmt_registration
*reg
, *tmp
;
855 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
857 list_for_each_entry_safe(reg
, tmp
, &wdev
->mgmt_registrations
, list
) {
858 list_del(®
->list
);
862 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
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
)
872 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
873 const struct ieee80211_mgmt
*mgmt
;
876 if (!wdev
->wiphy
->mgmt_stypes
)
879 if (!rdev
->ops
->mgmt_tx
)
885 mgmt
= (const struct ieee80211_mgmt
*) buf
;
887 if (!ieee80211_is_mgmt(mgmt
->frame_control
))
890 stype
= le16_to_cpu(mgmt
->frame_control
) & IEEE80211_FCTL_STYPE
;
891 if (!(wdev
->wiphy
->mgmt_stypes
[wdev
->iftype
].tx
& BIT(stype
>> 4)))
894 if (ieee80211_is_action(mgmt
->frame_control
) &&
895 mgmt
->u
.action
.category
!= WLAN_CATEGORY_PUBLIC
) {
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
) {
909 if (memcmp(wdev
->current_bss
->pub
.bssid
,
910 mgmt
->bssid
, ETH_ALEN
)) {
916 * check for IBSS DA must be done by driver as
917 * cfg80211 doesn't track the stations
919 if (wdev
->iftype
== NL80211_IFTYPE_ADHOC
)
922 /* for station, check that DA is the AP */
923 if (memcmp(wdev
->current_bss
->pub
.bssid
,
924 mgmt
->da
, ETH_ALEN
)) {
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
))
945 if (memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0)
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
);
953 bool cfg80211_rx_mgmt(struct net_device
*dev
, int freq
, const u8
*buf
,
954 size_t len
, gfp_t gfp
)
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
;
966 __le16 ftype
= mgmt
->frame_control
&
967 cpu_to_le16(IEEE80211_FCTL_FTYPE
| IEEE80211_FCTL_STYPE
);
970 stype
= (le16_to_cpu(mgmt
->frame_control
) & IEEE80211_FCTL_STYPE
) >> 4;
972 if (!(stypes
->rx
& BIT(stype
)))
975 data
= buf
+ ieee80211_hdrlen(mgmt
->frame_control
);
976 data_len
= len
- ieee80211_hdrlen(mgmt
->frame_control
);
978 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
980 list_for_each_entry(reg
, &wdev
->mgmt_registrations
, list
) {
981 if (reg
->frame_type
!= ftype
)
984 if (reg
->match_len
> data_len
)
987 if (memcmp(reg
->match
, data
, reg
->match_len
))
992 /* Indicate the received Action frame to user space */
993 if (nl80211_send_mgmt(rdev
, dev
, reg
->nlpid
, freq
,
1001 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
1005 EXPORT_SYMBOL(cfg80211_rx_mgmt
);
1007 void cfg80211_mgmt_tx_status(struct net_device
*dev
, u64 cookie
,
1008 const u8
*buf
, size_t len
, bool ack
, gfp_t gfp
)
1010 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1011 struct wiphy
*wiphy
= wdev
->wiphy
;
1012 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1014 /* Indicate TX status of the Action frame to user space */
1015 nl80211_send_mgmt_tx_status(rdev
, dev
, cookie
, buf
, len
, ack
, gfp
);
1017 EXPORT_SYMBOL(cfg80211_mgmt_tx_status
);
1019 void cfg80211_cqm_rssi_notify(struct net_device
*dev
,
1020 enum nl80211_cqm_rssi_threshold_event rssi_event
,
1023 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1024 struct wiphy
*wiphy
= wdev
->wiphy
;
1025 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1027 /* Indicate roaming trigger event to user space */
1028 nl80211_send_cqm_rssi_notify(rdev
, dev
, rssi_event
, gfp
);
1030 EXPORT_SYMBOL(cfg80211_cqm_rssi_notify
);