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/wireless.h>
12 #include <net/cfg80211.h>
13 #include <net/iw_handler.h>
17 void cfg80211_send_rx_auth(struct net_device
*dev
, const u8
*buf
, size_t len
)
19 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
20 struct wiphy
*wiphy
= wdev
->wiphy
;
21 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
22 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
23 u8
*bssid
= mgmt
->bssid
;
25 u16 status
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
30 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
31 if (wdev
->authtry_bsses
[i
] &&
32 memcmp(wdev
->authtry_bsses
[i
]->pub
.bssid
, bssid
,
34 if (status
== WLAN_STATUS_SUCCESS
) {
35 wdev
->auth_bsses
[i
] = wdev
->authtry_bsses
[i
];
37 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
38 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
40 wdev
->authtry_bsses
[i
] = NULL
;
48 nl80211_send_rx_auth(rdev
, dev
, buf
, len
, GFP_KERNEL
);
49 cfg80211_sme_rx_auth(dev
, buf
, len
);
53 EXPORT_SYMBOL(cfg80211_send_rx_auth
);
55 void cfg80211_send_rx_assoc(struct net_device
*dev
, const u8
*buf
, size_t len
)
58 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
59 struct wiphy
*wiphy
= wdev
->wiphy
;
60 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
61 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
62 u8
*ie
= mgmt
->u
.assoc_resp
.variable
;
63 int i
, ieoffs
= offsetof(struct ieee80211_mgmt
, u
.assoc_resp
.variable
);
64 struct cfg80211_internal_bss
*bss
= NULL
;
68 status_code
= le16_to_cpu(mgmt
->u
.assoc_resp
.status_code
);
71 * This is a bit of a hack, we don't notify userspace of
72 * a (re-)association reply if we tried to send a reassoc
73 * and got a reject -- we only try again with an assoc
74 * frame instead of reassoc.
76 if (status_code
!= WLAN_STATUS_SUCCESS
&& wdev
->conn
&&
77 cfg80211_sme_failed_reassoc(wdev
))
80 nl80211_send_rx_assoc(rdev
, dev
, buf
, len
, GFP_KERNEL
);
82 if (status_code
== WLAN_STATUS_SUCCESS
) {
83 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
84 if (!wdev
->auth_bsses
[i
])
86 if (memcmp(wdev
->auth_bsses
[i
]->pub
.bssid
, mgmt
->bssid
,
88 bss
= wdev
->auth_bsses
[i
];
89 wdev
->auth_bsses
[i
] = NULL
;
90 /* additional reference to drop hold */
91 cfg80211_ref_bss(bss
);
97 * We might be coming here because the driver reported
98 * a successful association at the same time as the
99 * user requested a deauth. In that case, we will have
100 * removed the BSS from the auth_bsses list due to the
101 * deauth request when the assoc response makes it. If
102 * the two code paths acquire the lock the other way
103 * around, that's just the standard situation of a
104 * deauth being requested while connected.
108 } else if (wdev
->conn
) {
109 cfg80211_sme_failed_assoc(wdev
);
111 * do not call connect_result() now because the
112 * sme will schedule work that does it later.
117 if (!wdev
->conn
&& wdev
->sme_state
== CFG80211_SME_IDLE
) {
119 * This is for the userspace SME, the CONNECTING
120 * state will be changed to CONNECTED by
121 * __cfg80211_connect_result() below.
123 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
126 /* this consumes one bss reference (unless bss is NULL) */
127 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, ie
, len
- ieoffs
,
129 status_code
== WLAN_STATUS_SUCCESS
,
130 bss
? &bss
->pub
: NULL
);
131 /* drop hold now, and also reference acquired above */
133 cfg80211_unhold_bss(bss
);
134 cfg80211_put_bss(&bss
->pub
);
140 EXPORT_SYMBOL(cfg80211_send_rx_assoc
);
142 void __cfg80211_send_deauth(struct net_device
*dev
,
143 const u8
*buf
, size_t len
)
145 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
146 struct wiphy
*wiphy
= wdev
->wiphy
;
147 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
148 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
149 const u8
*bssid
= mgmt
->bssid
;
152 ASSERT_WDEV_LOCK(wdev
);
154 nl80211_send_deauth(rdev
, dev
, buf
, len
, GFP_KERNEL
);
156 if (wdev
->current_bss
&&
157 memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
158 cfg80211_unhold_bss(wdev
->current_bss
);
159 cfg80211_put_bss(&wdev
->current_bss
->pub
);
160 wdev
->current_bss
= NULL
;
161 } else for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
162 if (wdev
->auth_bsses
[i
] &&
163 memcmp(wdev
->auth_bsses
[i
]->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
164 cfg80211_unhold_bss(wdev
->auth_bsses
[i
]);
165 cfg80211_put_bss(&wdev
->auth_bsses
[i
]->pub
);
166 wdev
->auth_bsses
[i
] = NULL
;
169 if (wdev
->authtry_bsses
[i
] &&
170 memcmp(wdev
->authtry_bsses
[i
]->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
171 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
172 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
173 wdev
->authtry_bsses
[i
] = NULL
;
178 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
) {
182 reason_code
= le16_to_cpu(mgmt
->u
.deauth
.reason_code
);
184 from_ap
= memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0;
185 __cfg80211_disconnected(dev
, NULL
, 0, reason_code
, from_ap
);
186 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
) {
187 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
188 WLAN_STATUS_UNSPECIFIED_FAILURE
,
192 EXPORT_SYMBOL(__cfg80211_send_deauth
);
194 void cfg80211_send_deauth(struct net_device
*dev
, const u8
*buf
, size_t len
)
196 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
199 __cfg80211_send_deauth(dev
, buf
, len
);
202 EXPORT_SYMBOL(cfg80211_send_deauth
);
204 void __cfg80211_send_disassoc(struct net_device
*dev
,
205 const u8
*buf
, size_t len
)
207 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
208 struct wiphy
*wiphy
= wdev
->wiphy
;
209 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
210 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
211 const u8
*bssid
= mgmt
->bssid
;
217 ASSERT_WDEV_LOCK(wdev
);
219 nl80211_send_disassoc(rdev
, dev
, buf
, len
, GFP_KERNEL
);
221 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
224 if (wdev
->current_bss
&&
225 memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
226 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
227 if (wdev
->authtry_bsses
[i
] || wdev
->auth_bsses
[i
])
229 wdev
->auth_bsses
[i
] = wdev
->current_bss
;
230 wdev
->current_bss
= NULL
;
232 cfg80211_sme_disassoc(dev
, i
);
240 reason_code
= le16_to_cpu(mgmt
->u
.disassoc
.reason_code
);
242 from_ap
= memcmp(mgmt
->sa
, dev
->dev_addr
, ETH_ALEN
) != 0;
243 __cfg80211_disconnected(dev
, NULL
, 0, reason_code
, from_ap
);
245 EXPORT_SYMBOL(__cfg80211_send_disassoc
);
247 void cfg80211_send_disassoc(struct net_device
*dev
, const u8
*buf
, size_t len
)
249 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
252 __cfg80211_send_disassoc(dev
, buf
, len
);
255 EXPORT_SYMBOL(cfg80211_send_disassoc
);
257 static void __cfg80211_auth_remove(struct wireless_dev
*wdev
, const u8
*addr
)
262 ASSERT_WDEV_LOCK(wdev
);
264 for (i
= 0; addr
&& i
< MAX_AUTH_BSSES
; i
++) {
265 if (wdev
->authtry_bsses
[i
] &&
266 memcmp(wdev
->authtry_bsses
[i
]->pub
.bssid
,
267 addr
, ETH_ALEN
) == 0) {
268 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
269 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
270 wdev
->authtry_bsses
[i
] = NULL
;
279 void __cfg80211_auth_canceled(struct net_device
*dev
, const u8
*addr
)
281 __cfg80211_auth_remove(dev
->ieee80211_ptr
, addr
);
283 EXPORT_SYMBOL(__cfg80211_auth_canceled
);
285 void cfg80211_send_auth_timeout(struct net_device
*dev
, const u8
*addr
)
287 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
288 struct wiphy
*wiphy
= wdev
->wiphy
;
289 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
293 nl80211_send_auth_timeout(rdev
, dev
, addr
, GFP_KERNEL
);
294 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
295 __cfg80211_connect_result(dev
, addr
, NULL
, 0, NULL
, 0,
296 WLAN_STATUS_UNSPECIFIED_FAILURE
,
299 __cfg80211_auth_remove(wdev
, addr
);
303 EXPORT_SYMBOL(cfg80211_send_auth_timeout
);
305 void cfg80211_send_assoc_timeout(struct net_device
*dev
, const u8
*addr
)
307 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
308 struct wiphy
*wiphy
= wdev
->wiphy
;
309 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
315 nl80211_send_assoc_timeout(rdev
, dev
, addr
, GFP_KERNEL
);
316 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
317 __cfg80211_connect_result(dev
, addr
, NULL
, 0, NULL
, 0,
318 WLAN_STATUS_UNSPECIFIED_FAILURE
,
321 for (i
= 0; addr
&& i
< MAX_AUTH_BSSES
; i
++) {
322 if (wdev
->auth_bsses
[i
] &&
323 memcmp(wdev
->auth_bsses
[i
]->pub
.bssid
,
324 addr
, ETH_ALEN
) == 0) {
325 cfg80211_unhold_bss(wdev
->auth_bsses
[i
]);
326 cfg80211_put_bss(&wdev
->auth_bsses
[i
]->pub
);
327 wdev
->auth_bsses
[i
] = NULL
;
337 EXPORT_SYMBOL(cfg80211_send_assoc_timeout
);
339 void cfg80211_michael_mic_failure(struct net_device
*dev
, const u8
*addr
,
340 enum nl80211_key_type key_type
, int key_id
,
341 const u8
*tsc
, gfp_t gfp
)
343 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
344 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
345 #ifdef CONFIG_CFG80211_WEXT
346 union iwreq_data wrqu
;
347 char *buf
= kmalloc(128, gfp
);
350 sprintf(buf
, "MLME-MICHAELMICFAILURE.indication("
351 "keyid=%d %scast addr=%pM)", key_id
,
352 key_type
== NL80211_KEYTYPE_GROUP
? "broad" : "uni",
354 memset(&wrqu
, 0, sizeof(wrqu
));
355 wrqu
.data
.length
= strlen(buf
);
356 wireless_send_event(dev
, IWEVCUSTOM
, &wrqu
, buf
);
361 nl80211_michael_mic_failure(rdev
, dev
, addr
, key_type
, key_id
, tsc
, gfp
);
363 EXPORT_SYMBOL(cfg80211_michael_mic_failure
);
365 /* some MLME handling for userspace SME */
366 int __cfg80211_mlme_auth(struct cfg80211_registered_device
*rdev
,
367 struct net_device
*dev
,
368 struct ieee80211_channel
*chan
,
369 enum nl80211_auth_type auth_type
,
371 const u8
*ssid
, int ssid_len
,
372 const u8
*ie
, int ie_len
,
373 const u8
*key
, int key_len
, int key_idx
)
375 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
376 struct cfg80211_auth_request req
;
377 struct cfg80211_internal_bss
*bss
;
378 int i
, err
, slot
= -1, nfree
= 0;
380 ASSERT_WDEV_LOCK(wdev
);
382 if (auth_type
== NL80211_AUTHTYPE_SHARED_KEY
)
383 if (!key
|| !key_len
|| key_idx
< 0 || key_idx
> 4)
386 if (wdev
->current_bss
&&
387 memcmp(bssid
, wdev
->current_bss
->pub
.bssid
, ETH_ALEN
) == 0)
390 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
391 if (wdev
->authtry_bsses
[i
] &&
392 memcmp(bssid
, wdev
->authtry_bsses
[i
]->pub
.bssid
,
395 if (wdev
->auth_bsses
[i
] &&
396 memcmp(bssid
, wdev
->auth_bsses
[i
]->pub
.bssid
,
401 memset(&req
, 0, sizeof(req
));
405 req
.auth_type
= auth_type
;
406 req
.bss
= cfg80211_get_bss(&rdev
->wiphy
, chan
, bssid
, ssid
, ssid_len
,
407 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
409 req
.key_len
= key_len
;
410 req
.key_idx
= key_idx
;
414 bss
= bss_from_pub(req
.bss
);
416 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
417 if (!wdev
->auth_bsses
[i
] && !wdev
->authtry_bsses
[i
]) {
423 /* we need one free slot for disassoc and one for this auth */
429 wdev
->authtry_bsses
[slot
] = bss
;
430 cfg80211_hold_bss(bss
);
432 err
= rdev
->ops
->auth(&rdev
->wiphy
, dev
, &req
);
434 wdev
->authtry_bsses
[slot
] = NULL
;
435 cfg80211_unhold_bss(bss
);
440 cfg80211_put_bss(req
.bss
);
444 int cfg80211_mlme_auth(struct cfg80211_registered_device
*rdev
,
445 struct net_device
*dev
, struct ieee80211_channel
*chan
,
446 enum nl80211_auth_type auth_type
, const u8
*bssid
,
447 const u8
*ssid
, int ssid_len
,
448 const u8
*ie
, int ie_len
,
449 const u8
*key
, int key_len
, int key_idx
)
453 wdev_lock(dev
->ieee80211_ptr
);
454 err
= __cfg80211_mlme_auth(rdev
, dev
, chan
, auth_type
, bssid
,
455 ssid
, ssid_len
, ie
, ie_len
,
456 key
, key_len
, key_idx
);
457 wdev_unlock(dev
->ieee80211_ptr
);
462 int __cfg80211_mlme_assoc(struct cfg80211_registered_device
*rdev
,
463 struct net_device
*dev
,
464 struct ieee80211_channel
*chan
,
465 const u8
*bssid
, const u8
*prev_bssid
,
466 const u8
*ssid
, int ssid_len
,
467 const u8
*ie
, int ie_len
, bool use_mfp
,
468 struct cfg80211_crypto_settings
*crypt
)
470 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
471 struct cfg80211_assoc_request req
;
472 struct cfg80211_internal_bss
*bss
;
473 int i
, err
, slot
= -1;
474 bool was_connected
= false;
476 ASSERT_WDEV_LOCK(wdev
);
478 memset(&req
, 0, sizeof(req
));
480 if (wdev
->current_bss
&& prev_bssid
&&
481 memcmp(wdev
->current_bss
->pub
.bssid
, prev_bssid
, ETH_ALEN
) == 0) {
483 * Trying to reassociate: Allow this to proceed and let the old
484 * association to be dropped when the new one is completed.
486 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
) {
487 was_connected
= true;
488 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
490 } else if (wdev
->current_bss
)
495 memcpy(&req
.crypto
, crypt
, sizeof(req
.crypto
));
496 req
.use_mfp
= use_mfp
;
497 req
.prev_bssid
= prev_bssid
;
498 req
.bss
= cfg80211_get_bss(&rdev
->wiphy
, chan
, bssid
, ssid
, ssid_len
,
499 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
502 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
506 bss
= bss_from_pub(req
.bss
);
508 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
509 if (bss
== wdev
->auth_bsses
[i
]) {
520 err
= rdev
->ops
->assoc(&rdev
->wiphy
, dev
, &req
);
522 if (err
&& was_connected
)
523 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
524 /* still a reference in wdev->auth_bsses[slot] */
525 cfg80211_put_bss(req
.bss
);
529 int cfg80211_mlme_assoc(struct cfg80211_registered_device
*rdev
,
530 struct net_device
*dev
,
531 struct ieee80211_channel
*chan
,
532 const u8
*bssid
, const u8
*prev_bssid
,
533 const u8
*ssid
, int ssid_len
,
534 const u8
*ie
, int ie_len
, bool use_mfp
,
535 struct cfg80211_crypto_settings
*crypt
)
537 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
541 err
= __cfg80211_mlme_assoc(rdev
, dev
, chan
, bssid
, prev_bssid
,
542 ssid
, ssid_len
, ie
, ie_len
, use_mfp
, crypt
);
548 int __cfg80211_mlme_deauth(struct cfg80211_registered_device
*rdev
,
549 struct net_device
*dev
, const u8
*bssid
,
550 const u8
*ie
, int ie_len
, u16 reason
)
552 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
553 struct cfg80211_deauth_request req
;
556 ASSERT_WDEV_LOCK(wdev
);
558 memset(&req
, 0, sizeof(req
));
559 req
.reason_code
= reason
;
562 if (wdev
->current_bss
&&
563 memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0) {
564 req
.bss
= &wdev
->current_bss
->pub
;
565 } else for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
566 if (wdev
->auth_bsses
[i
] &&
567 memcmp(bssid
, wdev
->auth_bsses
[i
]->pub
.bssid
, ETH_ALEN
) == 0) {
568 req
.bss
= &wdev
->auth_bsses
[i
]->pub
;
571 if (wdev
->authtry_bsses
[i
] &&
572 memcmp(bssid
, wdev
->authtry_bsses
[i
]->pub
.bssid
, ETH_ALEN
) == 0) {
573 req
.bss
= &wdev
->authtry_bsses
[i
]->pub
;
581 return rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
584 int cfg80211_mlme_deauth(struct cfg80211_registered_device
*rdev
,
585 struct net_device
*dev
, const u8
*bssid
,
586 const u8
*ie
, int ie_len
, u16 reason
)
588 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
592 err
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, ie
, ie_len
, reason
);
598 static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device
*rdev
,
599 struct net_device
*dev
, const u8
*bssid
,
600 const u8
*ie
, int ie_len
, u16 reason
)
602 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
603 struct cfg80211_disassoc_request req
;
605 ASSERT_WDEV_LOCK(wdev
);
607 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
610 if (WARN_ON(!wdev
->current_bss
))
613 memset(&req
, 0, sizeof(req
));
614 req
.reason_code
= reason
;
617 if (memcmp(wdev
->current_bss
->pub
.bssid
, bssid
, ETH_ALEN
) == 0)
618 req
.bss
= &wdev
->current_bss
->pub
;
622 return rdev
->ops
->disassoc(&rdev
->wiphy
, dev
, &req
, wdev
);
625 int cfg80211_mlme_disassoc(struct cfg80211_registered_device
*rdev
,
626 struct net_device
*dev
, const u8
*bssid
,
627 const u8
*ie
, int ie_len
, u16 reason
)
629 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
633 err
= __cfg80211_mlme_disassoc(rdev
, dev
, bssid
, ie
, ie_len
, reason
);
639 void cfg80211_mlme_down(struct cfg80211_registered_device
*rdev
,
640 struct net_device
*dev
)
642 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
643 struct cfg80211_deauth_request req
;
646 ASSERT_WDEV_LOCK(wdev
);
648 if (!rdev
->ops
->deauth
)
651 memset(&req
, 0, sizeof(req
));
652 req
.reason_code
= WLAN_REASON_DEAUTH_LEAVING
;
656 if (wdev
->current_bss
) {
657 req
.bss
= &wdev
->current_bss
->pub
;
658 rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
659 if (wdev
->current_bss
) {
660 cfg80211_unhold_bss(wdev
->current_bss
);
661 cfg80211_put_bss(&wdev
->current_bss
->pub
);
662 wdev
->current_bss
= NULL
;
666 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
667 if (wdev
->auth_bsses
[i
]) {
668 req
.bss
= &wdev
->auth_bsses
[i
]->pub
;
669 rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
670 if (wdev
->auth_bsses
[i
]) {
671 cfg80211_unhold_bss(wdev
->auth_bsses
[i
]);
672 cfg80211_put_bss(&wdev
->auth_bsses
[i
]->pub
);
673 wdev
->auth_bsses
[i
] = NULL
;
676 if (wdev
->authtry_bsses
[i
]) {
677 req
.bss
= &wdev
->authtry_bsses
[i
]->pub
;
678 rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &req
, wdev
);
679 if (wdev
->authtry_bsses
[i
]) {
680 cfg80211_unhold_bss(wdev
->authtry_bsses
[i
]);
681 cfg80211_put_bss(&wdev
->authtry_bsses
[i
]->pub
);
682 wdev
->authtry_bsses
[i
] = NULL
;