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
,
175 memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) == 0) {
176 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
177 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
178 wdev
->authtry_bsses
[i
] = NULL
;
187 nl80211_send_deauth(rdev
, dev
, buf
, len
, GFP_KERNEL
);
189 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
&& was_current
) {
193 reason_code
= le16_to_cpu(mgmt
->u
.deauth
.reason_code
);
195 from_ap
= memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0;
196 __cfg80211_disconnected(dev
, NULL
, 0, reason_code
, from_ap
);
197 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
) {
198 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
199 WLAN_STATUS_UNSPECIFIED_FAILURE
,
203 EXPORT_SYMBOL(__cfg80211_send_deauth
);
205 void cfg80211_send_deauth(struct net_device
*dev
, const u8
*buf
, size_t len
)
207 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
210 __cfg80211_send_deauth(dev
, buf
, len
);
213 EXPORT_SYMBOL(cfg80211_send_deauth
);
215 void __cfg80211_send_disassoc(struct net_device
*dev
,
216 const u8
*buf
, size_t len
)
218 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
219 struct wiphy
*wiphy
= wdev
->wiphy
;
220 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
221 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
222 const u8
*bssid
= mgmt
->bssid
;
228 ASSERT_WDEV_LOCK(wdev
);
230 nl80211_send_disassoc(rdev
, dev
, buf
, len
, GFP_KERNEL
);
232 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
235 if (wdev
->current_bss
&&
236 memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
237 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
238 if (wdev
->authtry_bsses
[i
] || wdev
->auth_bsses
[i
])
240 wdev
->auth_bsses
[i
] = wdev
->current_bss
;
241 wdev
->current_bss
= NULL
;
243 cfg80211_sme_disassoc(dev
, i
);
251 reason_code
= le16_to_cpu(mgmt
->u
.disassoc
.reason_code
);
253 from_ap
= memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0;
254 __cfg80211_disconnected(dev
, NULL
, 0, reason_code
, from_ap
);
256 EXPORT_SYMBOL(__cfg80211_send_disassoc
);
258 void cfg80211_send_disassoc(struct net_device
*dev
, const u8
*buf
, size_t len
)
260 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
263 __cfg80211_send_disassoc(dev
, buf
, len
);
266 EXPORT_SYMBOL(cfg80211_send_disassoc
);
268 void cfg80211_send_unprot_deauth(struct net_device
*dev
, const u8
*buf
,
271 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
272 struct wiphy
*wiphy
= wdev
->wiphy
;
273 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
275 nl80211_send_unprot_deauth(rdev
, dev
, buf
, len
, GFP_ATOMIC
);
277 EXPORT_SYMBOL(cfg80211_send_unprot_deauth
);
279 void cfg80211_send_unprot_disassoc(struct net_device
*dev
, const u8
*buf
,
282 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
283 struct wiphy
*wiphy
= wdev
->wiphy
;
284 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
286 nl80211_send_unprot_disassoc(rdev
, dev
, buf
, len
, GFP_ATOMIC
);
288 EXPORT_SYMBOL(cfg80211_send_unprot_disassoc
);
290 static void __cfg80211_auth_remove(struct wireless_dev
*wdev
, const u8
*addr
)
295 ASSERT_WDEV_LOCK(wdev
);
297 for (i
= 0; addr
&& i
< MAX_AUTH_BSSES
; i
++) {
298 if (wdev
->authtry_bsses
[i
] &&
299 memcmp(wdev
->authtry_bsses
[i
]->pub
.bssid
,
300 addr
, ETH_ALEN
) == 0) {
301 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
302 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
303 wdev
->authtry_bsses
[i
] = NULL
;
312 void __cfg80211_auth_canceled(struct net_device
*dev
, const u8
*addr
)
314 __cfg80211_auth_remove(dev
->ieee80211_ptr
, addr
);
316 EXPORT_SYMBOL(__cfg80211_auth_canceled
);
318 void cfg80211_send_auth_timeout(struct net_device
*dev
, const u8
*addr
)
320 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
321 struct wiphy
*wiphy
= wdev
->wiphy
;
322 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
326 nl80211_send_auth_timeout(rdev
, dev
, addr
, GFP_KERNEL
);
327 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
328 __cfg80211_connect_result(dev
, addr
, NULL
, 0, NULL
, 0,
329 WLAN_STATUS_UNSPECIFIED_FAILURE
,
332 __cfg80211_auth_remove(wdev
, addr
);
336 EXPORT_SYMBOL(cfg80211_send_auth_timeout
);
338 void cfg80211_send_assoc_timeout(struct net_device
*dev
, const u8
*addr
)
340 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
341 struct wiphy
*wiphy
= wdev
->wiphy
;
342 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
348 nl80211_send_assoc_timeout(rdev
, dev
, addr
, GFP_KERNEL
);
349 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
350 __cfg80211_connect_result(dev
, addr
, NULL
, 0, NULL
, 0,
351 WLAN_STATUS_UNSPECIFIED_FAILURE
,
354 for (i
= 0; addr
&& i
< MAX_AUTH_BSSES
; i
++) {
355 if (wdev
->auth_bsses
[i
] &&
356 memcmp(wdev
->auth_bsses
[i
]->pub
.bssid
,
357 addr
, ETH_ALEN
) == 0) {
358 cfg80211_unhold_bss(wdev
->auth_bsses
[i
]);
359 cfg80211_put_bss(&wdev
->auth_bsses
[i
]->pub
);
360 wdev
->auth_bsses
[i
] = NULL
;
370 EXPORT_SYMBOL(cfg80211_send_assoc_timeout
);
372 void cfg80211_michael_mic_failure(struct net_device
*dev
, const u8
*addr
,
373 enum nl80211_key_type key_type
, int key_id
,
374 const u8
*tsc
, gfp_t gfp
)
376 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
377 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
378 #ifdef CONFIG_CFG80211_WEXT
379 union iwreq_data wrqu
;
380 char *buf
= kmalloc(128, gfp
);
383 sprintf(buf
, "MLME-MICHAELMICFAILURE.indication("
384 "keyid=%d %scast addr=%pM)", key_id
,
385 key_type
== NL80211_KEYTYPE_GROUP
? "broad" : "uni",
387 memset(&wrqu
, 0, sizeof(wrqu
));
388 wrqu
.data
.length
= strlen(buf
);
389 wireless_send_event(dev
, IWEVCUSTOM
, &wrqu
, buf
);
394 nl80211_michael_mic_failure(rdev
, dev
, addr
, key_type
, key_id
, tsc
, gfp
);
396 EXPORT_SYMBOL(cfg80211_michael_mic_failure
);
398 /* some MLME handling for userspace SME */
399 int __cfg80211_mlme_auth(struct cfg80211_registered_device
*rdev
,
400 struct net_device
*dev
,
401 struct ieee80211_channel
*chan
,
402 enum nl80211_auth_type auth_type
,
404 const u8
*ssid
, int ssid_len
,
405 const u8
*ie
, int ie_len
,
406 const u8
*key
, int key_len
, int key_idx
,
407 bool local_state_change
)
409 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
410 struct cfg80211_auth_request req
;
411 struct cfg80211_internal_bss
*bss
;
412 int i
, err
, slot
= -1, nfree
= 0;
414 ASSERT_WDEV_LOCK(wdev
);
416 if (auth_type
== NL80211_AUTHTYPE_SHARED_KEY
)
417 if (!key
|| !key_len
|| key_idx
< 0 || key_idx
> 4)
420 if (wdev
->current_bss
&&
421 memcmp(bssid
, wdev
->current_bss
->pub
.bssid
, ETH_ALEN
) == 0)
424 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
425 if (wdev
->authtry_bsses
[i
] &&
426 memcmp(bssid
, wdev
->authtry_bsses
[i
]->pub
.bssid
,
429 if (wdev
->auth_bsses
[i
] &&
430 memcmp(bssid
, wdev
->auth_bsses
[i
]->pub
.bssid
,
435 memset(&req
, 0, sizeof(req
));
437 req
.local_state_change
= local_state_change
;
440 req
.auth_type
= auth_type
;
441 req
.bss
= cfg80211_get_bss(&rdev
->wiphy
, chan
, bssid
, ssid
, ssid_len
,
442 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
444 req
.key_len
= key_len
;
445 req
.key_idx
= key_idx
;
449 bss
= bss_from_pub(req
.bss
);
451 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
452 if (!wdev
->auth_bsses
[i
] && !wdev
->authtry_bsses
[i
]) {
458 /* we need one free slot for disassoc and one for this auth */
464 if (local_state_change
)
465 wdev
->auth_bsses
[slot
] = bss
;
467 wdev
->authtry_bsses
[slot
] = bss
;
468 cfg80211_hold_bss(bss
);
470 err
= rdev
->ops
->auth(&rdev
->wiphy
, dev
, &req
);
472 if (local_state_change
)
473 wdev
->auth_bsses
[slot
] = NULL
;
475 wdev
->authtry_bsses
[slot
] = NULL
;
476 cfg80211_unhold_bss(bss
);
481 cfg80211_put_bss(req
.bss
);
485 int cfg80211_mlme_auth(struct cfg80211_registered_device
*rdev
,
486 struct net_device
*dev
, struct ieee80211_channel
*chan
,
487 enum nl80211_auth_type auth_type
, const u8
*bssid
,
488 const u8
*ssid
, int ssid_len
,
489 const u8
*ie
, int ie_len
,
490 const u8
*key
, int key_len
, int key_idx
,
491 bool local_state_change
)
495 wdev_lock(dev
->ieee80211_ptr
);
496 err
= __cfg80211_mlme_auth(rdev
, dev
, chan
, auth_type
, bssid
,
497 ssid
, ssid_len
, ie
, ie_len
,
498 key
, key_len
, key_idx
, local_state_change
);
499 wdev_unlock(dev
->ieee80211_ptr
);
504 /* Do a logical ht_capa &= ht_capa_mask. */
505 void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap
*ht_capa
,
506 const struct ieee80211_ht_cap
*ht_capa_mask
)
511 memset(ht_capa
, 0, sizeof(*ht_capa
));
516 p2
= (u8
*)(ht_capa_mask
);
517 for (i
= 0; i
<sizeof(*ht_capa
); i
++)
521 int __cfg80211_mlme_assoc(struct cfg80211_registered_device
*rdev
,
522 struct net_device
*dev
,
523 struct ieee80211_channel
*chan
,
524 const u8
*bssid
, const u8
*prev_bssid
,
525 const u8
*ssid
, int ssid_len
,
526 const u8
*ie
, int ie_len
, bool use_mfp
,
527 struct cfg80211_crypto_settings
*crypt
,
528 u32 assoc_flags
, struct ieee80211_ht_cap
*ht_capa
,
529 struct ieee80211_ht_cap
*ht_capa_mask
)
531 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
532 struct cfg80211_assoc_request req
;
533 struct cfg80211_internal_bss
*bss
;
534 int i
, err
, slot
= -1;
535 bool was_connected
= false;
537 ASSERT_WDEV_LOCK(wdev
);
539 memset(&req
, 0, sizeof(req
));
541 if (wdev
->current_bss
&& prev_bssid
&&
542 memcmp(wdev
->current_bss
->pub
.bssid
, prev_bssid
, ETH_ALEN
) == 0) {
544 * Trying to reassociate: Allow this to proceed and let the old
545 * association to be dropped when the new one is completed.
547 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
) {
548 was_connected
= true;
549 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
551 } else if (wdev
->current_bss
)
556 memcpy(&req
.crypto
, crypt
, sizeof(req
.crypto
));
557 req
.use_mfp
= use_mfp
;
558 req
.prev_bssid
= prev_bssid
;
559 req
.flags
= assoc_flags
;
561 memcpy(&req
.ht_capa
, ht_capa
, sizeof(req
.ht_capa
));
563 memcpy(&req
.ht_capa_mask
, ht_capa_mask
,
564 sizeof(req
.ht_capa_mask
));
565 cfg80211_oper_and_ht_capa(&req
.ht_capa_mask
,
566 rdev
->wiphy
.ht_capa_mod_mask
);
568 req
.bss
= cfg80211_get_bss(&rdev
->wiphy
, chan
, bssid
, ssid
, ssid_len
,
569 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
572 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
576 bss
= bss_from_pub(req
.bss
);
578 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
579 if (bss
== wdev
->auth_bsses
[i
]) {
590 err
= rdev
->ops
->assoc(&rdev
->wiphy
, dev
, &req
);
592 if (err
&& was_connected
)
593 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
594 /* still a reference in wdev->auth_bsses[slot] */
595 cfg80211_put_bss(req
.bss
);
599 int cfg80211_mlme_assoc(struct cfg80211_registered_device
*rdev
,
600 struct net_device
*dev
,
601 struct ieee80211_channel
*chan
,
602 const u8
*bssid
, const u8
*prev_bssid
,
603 const u8
*ssid
, int ssid_len
,
604 const u8
*ie
, int ie_len
, bool use_mfp
,
605 struct cfg80211_crypto_settings
*crypt
,
606 u32 assoc_flags
, struct ieee80211_ht_cap
*ht_capa
,
607 struct ieee80211_ht_cap
*ht_capa_mask
)
609 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
613 err
= __cfg80211_mlme_assoc(rdev
, dev
, chan
, bssid
, prev_bssid
,
614 ssid
, ssid_len
, ie
, ie_len
, use_mfp
, crypt
,
615 assoc_flags
, ht_capa
, ht_capa_mask
);
621 int __cfg80211_mlme_deauth(struct cfg80211_registered_device
*rdev
,
622 struct net_device
*dev
, const u8
*bssid
,
623 const u8
*ie
, int ie_len
, u16 reason
,
624 bool local_state_change
)
626 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
627 struct cfg80211_deauth_request req
;
630 ASSERT_WDEV_LOCK(wdev
);
632 memset(&req
, 0, sizeof(req
));
633 req
.reason_code
= reason
;
634 req
.local_state_change
= local_state_change
;
637 if (wdev
->current_bss
&&
638 memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
639 req
.bss
= &wdev
->current_bss
->pub
;
640 } else for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
641 if (wdev
->auth_bsses
[i
] &&
642 memcmp(bssid
, wdev
->auth_bsses
[i
]->pub
.bssid
, ETH_ALEN
) == 0) {
643 req
.bss
= &wdev
->auth_bsses
[i
]->pub
;
646 if (wdev
->authtry_bsses
[i
] &&
647 memcmp(bssid
, wdev
->authtry_bsses
[i
]->pub
.bssid
, ETH_ALEN
) == 0) {
648 req
.bss
= &wdev
->authtry_bsses
[i
]->pub
;
656 return rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
659 int cfg80211_mlme_deauth(struct cfg80211_registered_device
*rdev
,
660 struct net_device
*dev
, const u8
*bssid
,
661 const u8
*ie
, int ie_len
, u16 reason
,
662 bool local_state_change
)
664 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
668 err
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, ie
, ie_len
, reason
,
675 static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device
*rdev
,
676 struct net_device
*dev
, const u8
*bssid
,
677 const u8
*ie
, int ie_len
, u16 reason
,
678 bool local_state_change
)
680 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
681 struct cfg80211_disassoc_request req
;
683 ASSERT_WDEV_LOCK(wdev
);
685 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
688 if (WARN_ON(!wdev
->current_bss
))
691 memset(&req
, 0, sizeof(req
));
692 req
.reason_code
= reason
;
693 req
.local_state_change
= local_state_change
;
696 if (memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0)
697 req
.bss
= &wdev
->current_bss
->pub
;
701 return rdev
->ops
->disassoc(&rdev
->wiphy
, dev
, &req
, wdev
);
704 int cfg80211_mlme_disassoc(struct cfg80211_registered_device
*rdev
,
705 struct net_device
*dev
, const u8
*bssid
,
706 const u8
*ie
, int ie_len
, u16 reason
,
707 bool local_state_change
)
709 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
713 err
= __cfg80211_mlme_disassoc(rdev
, dev
, bssid
, ie
, ie_len
, reason
,
720 void cfg80211_mlme_down(struct cfg80211_registered_device
*rdev
,
721 struct net_device
*dev
)
723 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
724 struct cfg80211_deauth_request req
;
727 ASSERT_WDEV_LOCK(wdev
);
729 if (!rdev
->ops
->deauth
)
732 memset(&req
, 0, sizeof(req
));
733 req
.reason_code
= WLAN_REASON_DEAUTH_LEAVING
;
737 if (wdev
->current_bss
) {
738 req
.bss
= &wdev
->current_bss
->pub
;
739 rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
740 if (wdev
->current_bss
) {
741 cfg80211_unhold_bss(wdev
->current_bss
);
742 cfg80211_put_bss(&wdev
->current_bss
->pub
);
743 wdev
->current_bss
= NULL
;
747 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
748 if (wdev
->auth_bsses
[i
]) {
749 req
.bss
= &wdev
->auth_bsses
[i
]->pub
;
750 rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
751 if (wdev
->auth_bsses
[i
]) {
752 cfg80211_unhold_bss(wdev
->auth_bsses
[i
]);
753 cfg80211_put_bss(&wdev
->auth_bsses
[i
]->pub
);
754 wdev
->auth_bsses
[i
] = NULL
;
757 if (wdev
->authtry_bsses
[i
]) {
758 req
.bss
= &wdev
->authtry_bsses
[i
]->pub
;
759 rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
760 if (wdev
->authtry_bsses
[i
]) {
761 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
762 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
763 wdev
->authtry_bsses
[i
] = NULL
;
769 void cfg80211_ready_on_channel(struct net_device
*dev
, u64 cookie
,
770 struct ieee80211_channel
*chan
,
771 enum nl80211_channel_type channel_type
,
772 unsigned int duration
, gfp_t gfp
)
774 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
775 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
777 nl80211_send_remain_on_channel(rdev
, dev
, cookie
, chan
, channel_type
,
780 EXPORT_SYMBOL(cfg80211_ready_on_channel
);
782 void cfg80211_remain_on_channel_expired(struct net_device
*dev
,
784 struct ieee80211_channel
*chan
,
785 enum nl80211_channel_type channel_type
,
788 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
789 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
791 nl80211_send_remain_on_channel_cancel(rdev
, dev
, cookie
, chan
,
794 EXPORT_SYMBOL(cfg80211_remain_on_channel_expired
);
796 void cfg80211_new_sta(struct net_device
*dev
, const u8
*mac_addr
,
797 struct station_info
*sinfo
, gfp_t gfp
)
799 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
800 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
802 nl80211_send_sta_event(rdev
, dev
, mac_addr
, sinfo
, gfp
);
804 EXPORT_SYMBOL(cfg80211_new_sta
);
806 void cfg80211_del_sta(struct net_device
*dev
, const u8
*mac_addr
, gfp_t gfp
)
808 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
809 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
811 nl80211_send_sta_del_event(rdev
, dev
, mac_addr
, gfp
);
813 EXPORT_SYMBOL(cfg80211_del_sta
);
815 struct cfg80211_mgmt_registration
{
816 struct list_head list
;
827 int cfg80211_mlme_register_mgmt(struct wireless_dev
*wdev
, u32 snd_pid
,
828 u16 frame_type
, const u8
*match_data
,
831 struct wiphy
*wiphy
= wdev
->wiphy
;
832 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
833 struct cfg80211_mgmt_registration
*reg
, *nreg
;
837 if (!wdev
->wiphy
->mgmt_stypes
)
840 if ((frame_type
& IEEE80211_FCTL_FTYPE
) != IEEE80211_FTYPE_MGMT
)
843 if (frame_type
& ~(IEEE80211_FCTL_FTYPE
| IEEE80211_FCTL_STYPE
))
846 mgmt_type
= (frame_type
& IEEE80211_FCTL_STYPE
) >> 4;
847 if (!(wdev
->wiphy
->mgmt_stypes
[wdev
->iftype
].rx
& BIT(mgmt_type
)))
850 nreg
= kzalloc(sizeof(*reg
) + match_len
, GFP_KERNEL
);
854 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
856 list_for_each_entry(reg
, &wdev
->mgmt_registrations
, list
) {
857 int mlen
= min(match_len
, reg
->match_len
);
859 if (frame_type
!= le16_to_cpu(reg
->frame_type
))
862 if (memcmp(reg
->match
, match_data
, mlen
) == 0) {
873 memcpy(nreg
->match
, match_data
, match_len
);
874 nreg
->match_len
= match_len
;
875 nreg
->nlpid
= snd_pid
;
876 nreg
->frame_type
= cpu_to_le16(frame_type
);
877 list_add(&nreg
->list
, &wdev
->mgmt_registrations
);
879 if (rdev
->ops
->mgmt_frame_register
)
880 rdev
->ops
->mgmt_frame_register(wiphy
, wdev
->netdev
,
884 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
889 void cfg80211_mlme_unregister_socket(struct wireless_dev
*wdev
, u32 nlpid
)
891 struct wiphy
*wiphy
= wdev
->wiphy
;
892 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
893 struct cfg80211_mgmt_registration
*reg
, *tmp
;
895 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
897 list_for_each_entry_safe(reg
, tmp
, &wdev
->mgmt_registrations
, list
) {
898 if (reg
->nlpid
!= nlpid
)
901 if (rdev
->ops
->mgmt_frame_register
) {
902 u16 frame_type
= le16_to_cpu(reg
->frame_type
);
904 rdev
->ops
->mgmt_frame_register(wiphy
, wdev
->netdev
,
908 list_del(®
->list
);
912 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
914 if (nlpid
== wdev
->ap_unexpected_nlpid
)
915 wdev
->ap_unexpected_nlpid
= 0;
918 void cfg80211_mlme_purge_registrations(struct wireless_dev
*wdev
)
920 struct cfg80211_mgmt_registration
*reg
, *tmp
;
922 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
924 list_for_each_entry_safe(reg
, tmp
, &wdev
->mgmt_registrations
, list
) {
925 list_del(®
->list
);
929 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
932 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device
*rdev
,
933 struct net_device
*dev
,
934 struct ieee80211_channel
*chan
, bool offchan
,
935 enum nl80211_channel_type channel_type
,
936 bool channel_type_valid
, unsigned int wait
,
937 const u8
*buf
, size_t len
, bool no_cck
,
938 bool dont_wait_for_ack
, u64
*cookie
)
940 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
941 const struct ieee80211_mgmt
*mgmt
;
944 if (!wdev
->wiphy
->mgmt_stypes
)
947 if (!rdev
->ops
->mgmt_tx
)
953 mgmt
= (const struct ieee80211_mgmt
*) buf
;
955 if (!ieee80211_is_mgmt(mgmt
->frame_control
))
958 stype
= le16_to_cpu(mgmt
->frame_control
) & IEEE80211_FCTL_STYPE
;
959 if (!(wdev
->wiphy
->mgmt_stypes
[wdev
->iftype
].tx
& BIT(stype
>> 4)))
962 if (ieee80211_is_action(mgmt
->frame_control
) &&
963 mgmt
->u
.action
.category
!= WLAN_CATEGORY_PUBLIC
) {
968 switch (wdev
->iftype
) {
969 case NL80211_IFTYPE_ADHOC
:
970 case NL80211_IFTYPE_STATION
:
971 case NL80211_IFTYPE_P2P_CLIENT
:
972 if (!wdev
->current_bss
) {
977 if (memcmp(wdev
->current_bss
->pub
.bssid
,
978 mgmt
->bssid
, ETH_ALEN
)) {
984 * check for IBSS DA must be done by driver as
985 * cfg80211 doesn't track the stations
987 if (wdev
->iftype
== NL80211_IFTYPE_ADHOC
)
990 /* for station, check that DA is the AP */
991 if (memcmp(wdev
->current_bss
->pub
.bssid
,
992 mgmt
->da
, ETH_ALEN
)) {
997 case NL80211_IFTYPE_AP
:
998 case NL80211_IFTYPE_P2P_GO
:
999 case NL80211_IFTYPE_AP_VLAN
:
1000 if (memcmp(mgmt
->bssid
, dev
->dev_addr
, ETH_ALEN
))
1003 case NL80211_IFTYPE_MESH_POINT
:
1004 if (memcmp(mgmt
->sa
, mgmt
->bssid
, ETH_ALEN
)) {
1009 * check for mesh DA must be done by driver as
1010 * cfg80211 doesn't track the stations
1023 if (memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0)
1026 /* Transmit the Action frame as requested by user space */
1027 return rdev
->ops
->mgmt_tx(&rdev
->wiphy
, dev
, chan
, offchan
,
1028 channel_type
, channel_type_valid
,
1029 wait
, buf
, len
, no_cck
, dont_wait_for_ack
,
1033 bool cfg80211_rx_mgmt(struct net_device
*dev
, int freq
, const u8
*buf
,
1034 size_t len
, gfp_t gfp
)
1036 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1037 struct wiphy
*wiphy
= wdev
->wiphy
;
1038 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1039 struct cfg80211_mgmt_registration
*reg
;
1040 const struct ieee80211_txrx_stypes
*stypes
=
1041 &wiphy
->mgmt_stypes
[wdev
->iftype
];
1042 struct ieee80211_mgmt
*mgmt
= (void *)buf
;
1045 bool result
= false;
1046 __le16 ftype
= mgmt
->frame_control
&
1047 cpu_to_le16(IEEE80211_FCTL_FTYPE
| IEEE80211_FCTL_STYPE
);
1050 stype
= (le16_to_cpu(mgmt
->frame_control
) & IEEE80211_FCTL_STYPE
) >> 4;
1052 if (!(stypes
->rx
& BIT(stype
)))
1055 data
= buf
+ ieee80211_hdrlen(mgmt
->frame_control
);
1056 data_len
= len
- ieee80211_hdrlen(mgmt
->frame_control
);
1058 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
1060 list_for_each_entry(reg
, &wdev
->mgmt_registrations
, list
) {
1061 if (reg
->frame_type
!= ftype
)
1064 if (reg
->match_len
> data_len
)
1067 if (memcmp(reg
->match
, data
, reg
->match_len
))
1072 /* Indicate the received Action frame to user space */
1073 if (nl80211_send_mgmt(rdev
, dev
, reg
->nlpid
, freq
,
1081 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
1085 EXPORT_SYMBOL(cfg80211_rx_mgmt
);
1087 void cfg80211_mgmt_tx_status(struct net_device
*dev
, u64 cookie
,
1088 const u8
*buf
, size_t len
, bool ack
, gfp_t gfp
)
1090 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1091 struct wiphy
*wiphy
= wdev
->wiphy
;
1092 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1094 /* Indicate TX status of the Action frame to user space */
1095 nl80211_send_mgmt_tx_status(rdev
, dev
, cookie
, buf
, len
, ack
, gfp
);
1097 EXPORT_SYMBOL(cfg80211_mgmt_tx_status
);
1099 void cfg80211_cqm_rssi_notify(struct net_device
*dev
,
1100 enum nl80211_cqm_rssi_threshold_event rssi_event
,
1103 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1104 struct wiphy
*wiphy
= wdev
->wiphy
;
1105 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1107 /* Indicate roaming trigger event to user space */
1108 nl80211_send_cqm_rssi_notify(rdev
, dev
, rssi_event
, gfp
);
1110 EXPORT_SYMBOL(cfg80211_cqm_rssi_notify
);
1112 void cfg80211_cqm_pktloss_notify(struct net_device
*dev
,
1113 const u8
*peer
, u32 num_packets
, gfp_t gfp
)
1115 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1116 struct wiphy
*wiphy
= wdev
->wiphy
;
1117 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1119 /* Indicate roaming trigger event to user space */
1120 nl80211_send_cqm_pktloss_notify(rdev
, dev
, peer
, num_packets
, gfp
);
1122 EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify
);
1124 void cfg80211_gtk_rekey_notify(struct net_device
*dev
, const u8
*bssid
,
1125 const u8
*replay_ctr
, gfp_t gfp
)
1127 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1128 struct wiphy
*wiphy
= wdev
->wiphy
;
1129 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1131 nl80211_gtk_rekey_notify(rdev
, dev
, bssid
, replay_ctr
, gfp
);
1133 EXPORT_SYMBOL(cfg80211_gtk_rekey_notify
);
1135 void cfg80211_pmksa_candidate_notify(struct net_device
*dev
, int index
,
1136 const u8
*bssid
, bool preauth
, gfp_t gfp
)
1138 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1139 struct wiphy
*wiphy
= wdev
->wiphy
;
1140 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
1142 nl80211_pmksa_candidate_notify(rdev
, dev
, index
, bssid
, preauth
, gfp
);
1144 EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify
);
1146 bool cfg80211_rx_spurious_frame(struct net_device
*dev
,
1147 const u8
*addr
, gfp_t gfp
)
1149 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1151 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_AP
&&
1152 wdev
->iftype
!= NL80211_IFTYPE_P2P_GO
))
1155 return nl80211_unexpected_frame(dev
, addr
, gfp
);
1157 EXPORT_SYMBOL(cfg80211_rx_spurious_frame
);
1159 bool cfg80211_rx_unexpected_4addr_frame(struct net_device
*dev
,
1160 const u8
*addr
, gfp_t gfp
)
1162 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
1164 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_AP
&&
1165 wdev
->iftype
!= NL80211_IFTYPE_P2P_GO
&&
1166 wdev
->iftype
!= NL80211_IFTYPE_AP_VLAN
))
1169 return nl80211_unexpected_4addr_frame(dev
, addr
, gfp
);
1171 EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame
);