Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[pandora-kernel.git] / net / wireless / mlme.c
1 /*
2  * cfg80211 MLME SAP interface
3  *
4  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5  */
6
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/nl80211.h>
11 #include <net/cfg80211.h>
12 #include "core.h"
13 #include "nl80211.h"
14
15 void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
16 {
17         struct wireless_dev *wdev = dev->ieee80211_ptr;
18         struct wiphy *wiphy = wdev->wiphy;
19         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
20         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
21         u8 *bssid = mgmt->bssid;
22         int i;
23         u16 status = le16_to_cpu(mgmt->u.auth.status_code);
24         bool done = false;
25
26         wdev_lock(wdev);
27
28         for (i = 0; i < MAX_AUTH_BSSES; i++) {
29                 if (wdev->authtry_bsses[i] &&
30                     memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
31                                                         ETH_ALEN) == 0) {
32                         if (status == WLAN_STATUS_SUCCESS) {
33                                 wdev->auth_bsses[i] = wdev->authtry_bsses[i];
34                         } else {
35                                 cfg80211_unhold_bss(wdev->authtry_bsses[i]);
36                                 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
37                         }
38                         wdev->authtry_bsses[i] = NULL;
39                         done = true;
40                         break;
41                 }
42         }
43
44         WARN_ON(!done);
45
46         nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
47         cfg80211_sme_rx_auth(dev, buf, len);
48
49         wdev_unlock(wdev);
50 }
51 EXPORT_SYMBOL(cfg80211_send_rx_auth);
52
53 void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
54 {
55         u16 status_code;
56         struct wireless_dev *wdev = dev->ieee80211_ptr;
57         struct wiphy *wiphy = wdev->wiphy;
58         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
59         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
60         u8 *ie = mgmt->u.assoc_resp.variable;
61         int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
62         bool done;
63
64         wdev_lock(wdev);
65
66         status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
67
68         nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
69
70         __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
71                                   status_code,
72                                   status_code == WLAN_STATUS_SUCCESS);
73
74         if (status_code == WLAN_STATUS_SUCCESS) {
75                 for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) {
76                         if (wdev->auth_bsses[i] == wdev->current_bss) {
77                                 cfg80211_unhold_bss(wdev->auth_bsses[i]);
78                                 cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
79                                 wdev->auth_bsses[i] = NULL;
80                                 done = true;
81                                 break;
82                         }
83                 }
84
85                 WARN_ON(!done);
86         }
87
88         wdev_unlock(wdev);
89 }
90 EXPORT_SYMBOL(cfg80211_send_rx_assoc);
91
92 static void __cfg80211_send_deauth(struct net_device *dev,
93                                    const u8 *buf, size_t len)
94 {
95         struct wireless_dev *wdev = dev->ieee80211_ptr;
96         struct wiphy *wiphy = wdev->wiphy;
97         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
98         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
99         const u8 *bssid = mgmt->bssid;
100         int i;
101         bool done = false;
102
103         ASSERT_WDEV_LOCK(wdev);
104
105         nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
106
107         if (wdev->current_bss &&
108             memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
109                 done = true;
110                 cfg80211_unhold_bss(wdev->current_bss);
111                 cfg80211_put_bss(&wdev->current_bss->pub);
112                 wdev->current_bss = NULL;
113         } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
114                 if (wdev->auth_bsses[i] &&
115                     memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
116                         cfg80211_unhold_bss(wdev->auth_bsses[i]);
117                         cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
118                         wdev->auth_bsses[i] = NULL;
119                         done = true;
120                         break;
121                 }
122                 if (wdev->authtry_bsses[i] &&
123                     memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
124                         cfg80211_unhold_bss(wdev->authtry_bsses[i]);
125                         cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
126                         wdev->authtry_bsses[i] = NULL;
127                         done = true;
128                         break;
129                 }
130         }
131
132         WARN_ON(!done);
133
134         if (wdev->sme_state == CFG80211_SME_CONNECTED) {
135                 u16 reason_code;
136                 bool from_ap;
137
138                 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
139
140                 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
141                 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
142         } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
143                 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
144                                           WLAN_STATUS_UNSPECIFIED_FAILURE,
145                                           false);
146         }
147 }
148
149
150 void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
151                           void *cookie)
152 {
153         struct wireless_dev *wdev = dev->ieee80211_ptr;
154
155         BUG_ON(cookie && wdev != cookie);
156
157         if (cookie) {
158                 /* called within callback */
159                 __cfg80211_send_deauth(dev, buf, len);
160         } else {
161                 wdev_lock(wdev);
162                 __cfg80211_send_deauth(dev, buf, len);
163                 wdev_unlock(wdev);
164         }
165 }
166 EXPORT_SYMBOL(cfg80211_send_deauth);
167
168 static void __cfg80211_send_disassoc(struct net_device *dev,
169                                      const u8 *buf, size_t len)
170 {
171         struct wireless_dev *wdev = dev->ieee80211_ptr;
172         struct wiphy *wiphy = wdev->wiphy;
173         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
174         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
175         const u8 *bssid = mgmt->bssid;
176         int i;
177         u16 reason_code;
178         bool from_ap;
179         bool done = false;
180
181         wdev_lock(wdev);
182
183         nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
184
185         if (!wdev->sme_state == CFG80211_SME_CONNECTED)
186                 goto out;
187
188         if (wdev->current_bss &&
189             memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) {
190                 for (i = 0; i < MAX_AUTH_BSSES; i++) {
191                         if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
192                                 continue;
193                         wdev->auth_bsses[i] = wdev->current_bss;
194                         wdev->current_bss = NULL;
195                         done = true;
196                         cfg80211_sme_disassoc(dev, i);
197                         break;
198                 }
199                 WARN_ON(!done);
200         } else
201                 WARN_ON(1);
202
203
204         reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
205
206         from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
207         __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
208  out:
209         wdev_unlock(wdev);
210 }
211
212 void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
213                             void *cookie)
214 {
215         struct wireless_dev *wdev = dev->ieee80211_ptr;
216
217         BUG_ON(cookie && wdev != cookie);
218
219         if (cookie) {
220                 /* called within callback */
221                 __cfg80211_send_disassoc(dev, buf, len);
222         } else {
223                 wdev_lock(wdev);
224                 __cfg80211_send_disassoc(dev, buf, len);
225                 wdev_unlock(wdev);
226         }
227 }
228 EXPORT_SYMBOL(cfg80211_send_disassoc);
229
230 void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
231 {
232         struct wireless_dev *wdev = dev->ieee80211_ptr;
233         struct wiphy *wiphy = wdev->wiphy;
234         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
235         int i;
236         bool done = false;
237
238         wdev_lock(wdev);
239
240         nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
241         if (wdev->sme_state == CFG80211_SME_CONNECTING)
242                 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
243                                           WLAN_STATUS_UNSPECIFIED_FAILURE,
244                                           false);
245
246         for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
247                 if (wdev->authtry_bsses[i] &&
248                     memcmp(wdev->authtry_bsses[i]->pub.bssid,
249                            addr, ETH_ALEN) == 0) {
250                         cfg80211_unhold_bss(wdev->authtry_bsses[i]);
251                         cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
252                         wdev->authtry_bsses[i] = NULL;
253                         done = true;
254                         break;
255                 }
256         }
257
258         WARN_ON(!done);
259
260         wdev_unlock(wdev);
261 }
262 EXPORT_SYMBOL(cfg80211_send_auth_timeout);
263
264 void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
265 {
266         struct wireless_dev *wdev = dev->ieee80211_ptr;
267         struct wiphy *wiphy = wdev->wiphy;
268         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
269         int i;
270         bool done = false;
271
272         wdev_lock(wdev);
273
274         nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
275         if (wdev->sme_state == CFG80211_SME_CONNECTING)
276                 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
277                                           WLAN_STATUS_UNSPECIFIED_FAILURE,
278                                           false);
279
280         for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
281                 if (wdev->auth_bsses[i] &&
282                     memcmp(wdev->auth_bsses[i]->pub.bssid,
283                            addr, ETH_ALEN) == 0) {
284                         cfg80211_unhold_bss(wdev->auth_bsses[i]);
285                         cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
286                         wdev->auth_bsses[i] = NULL;
287                         done = true;
288                         break;
289                 }
290         }
291
292         WARN_ON(!done);
293
294         wdev_unlock(wdev);
295 }
296 EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
297
298 void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
299                                   enum nl80211_key_type key_type, int key_id,
300                                   const u8 *tsc, gfp_t gfp)
301 {
302         struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
303         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
304 #ifdef CONFIG_WIRELESS_EXT
305         union iwreq_data wrqu;
306         char *buf = kmalloc(128, gfp);
307
308         if (buf) {
309                 sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
310                         "keyid=%d %scast addr=%pM)", key_id,
311                         key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
312                         addr);
313                 memset(&wrqu, 0, sizeof(wrqu));
314                 wrqu.data.length = strlen(buf);
315                 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
316                 kfree(buf);
317         }
318 #endif
319
320         nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
321 }
322 EXPORT_SYMBOL(cfg80211_michael_mic_failure);
323
324 /* some MLME handling for userspace SME */
325 int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
326                          struct net_device *dev,
327                          struct ieee80211_channel *chan,
328                          enum nl80211_auth_type auth_type,
329                          const u8 *bssid,
330                          const u8 *ssid, int ssid_len,
331                          const u8 *ie, int ie_len)
332 {
333         struct wireless_dev *wdev = dev->ieee80211_ptr;
334         struct cfg80211_auth_request req;
335         struct cfg80211_internal_bss *bss;
336         int i, err, slot = -1, nfree = 0;
337
338         ASSERT_WDEV_LOCK(wdev);
339
340         if (wdev->current_bss &&
341             memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
342                 return -EALREADY;
343
344         for (i = 0; i < MAX_AUTH_BSSES; i++) {
345                 if (wdev->authtry_bsses[i] &&
346                     memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
347                                                 ETH_ALEN) == 0)
348                         return -EALREADY;
349                 if (wdev->auth_bsses[i] &&
350                     memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
351                                                 ETH_ALEN) == 0)
352                         return -EALREADY;
353         }
354
355         memset(&req, 0, sizeof(req));
356
357         req.ie = ie;
358         req.ie_len = ie_len;
359         req.auth_type = auth_type;
360         req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
361                                    WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
362         if (!req.bss)
363                 return -ENOENT;
364
365         bss = bss_from_pub(req.bss);
366
367         for (i = 0; i < MAX_AUTH_BSSES; i++) {
368                 if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
369                         slot = i;
370                         nfree++;
371                 }
372         }
373
374         /* we need one free slot for disassoc and one for this auth */
375         if (nfree < 2) {
376                 err = -ENOSPC;
377                 goto out;
378         }
379
380         wdev->authtry_bsses[slot] = bss;
381         cfg80211_hold_bss(bss);
382
383         err = rdev->ops->auth(&rdev->wiphy, dev, &req);
384         if (err) {
385                 wdev->authtry_bsses[slot] = NULL;
386                 cfg80211_unhold_bss(bss);
387         }
388
389  out:
390         if (err)
391                 cfg80211_put_bss(req.bss);
392         return err;
393 }
394
395 int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
396                        struct net_device *dev, struct ieee80211_channel *chan,
397                        enum nl80211_auth_type auth_type, const u8 *bssid,
398                        const u8 *ssid, int ssid_len,
399                        const u8 *ie, int ie_len)
400 {
401         int err;
402
403         wdev_lock(dev->ieee80211_ptr);
404         err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
405                                    ssid, ssid_len, ie, ie_len);
406         wdev_unlock(dev->ieee80211_ptr);
407
408         return err;
409 }
410
411 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
412                           struct net_device *dev,
413                           struct ieee80211_channel *chan,
414                           const u8 *bssid, const u8 *prev_bssid,
415                           const u8 *ssid, int ssid_len,
416                           const u8 *ie, int ie_len, bool use_mfp,
417                           struct cfg80211_crypto_settings *crypt)
418 {
419         struct wireless_dev *wdev = dev->ieee80211_ptr;
420         struct cfg80211_assoc_request req;
421         struct cfg80211_internal_bss *bss;
422         int i, err, slot = -1;
423
424         ASSERT_WDEV_LOCK(wdev);
425
426         memset(&req, 0, sizeof(req));
427
428         if (wdev->current_bss)
429                 return -EALREADY;
430
431         req.ie = ie;
432         req.ie_len = ie_len;
433         memcpy(&req.crypto, crypt, sizeof(req.crypto));
434         req.use_mfp = use_mfp;
435         req.prev_bssid = prev_bssid;
436         req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
437                                    WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
438         if (!req.bss)
439                 return -ENOENT;
440
441         bss = bss_from_pub(req.bss);
442
443         for (i = 0; i < MAX_AUTH_BSSES; i++) {
444                 if (bss == wdev->auth_bsses[i]) {
445                         slot = i;
446                         break;
447                 }
448         }
449
450         if (slot < 0) {
451                 err = -ENOTCONN;
452                 goto out;
453         }
454
455         err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
456  out:
457         /* still a reference in wdev->auth_bsses[slot] */
458         cfg80211_put_bss(req.bss);
459         return err;
460 }
461
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)
469 {
470         struct wireless_dev *wdev = dev->ieee80211_ptr;
471         int err;
472
473         wdev_lock(wdev);
474         err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
475                                     ssid, ssid_len, ie, ie_len, use_mfp, crypt);
476         wdev_unlock(wdev);
477
478         return err;
479 }
480
481 int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
482                            struct net_device *dev, const u8 *bssid,
483                            const u8 *ie, int ie_len, u16 reason)
484 {
485         struct wireless_dev *wdev = dev->ieee80211_ptr;
486         struct cfg80211_deauth_request req;
487         int i;
488
489         ASSERT_WDEV_LOCK(wdev);
490
491         memset(&req, 0, sizeof(req));
492         req.reason_code = reason;
493         req.ie = ie;
494         req.ie_len = ie_len;
495         if (wdev->current_bss &&
496             memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
497                 req.bss = &wdev->current_bss->pub;
498         } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
499                 if (wdev->auth_bsses[i] &&
500                     memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
501                         req.bss = &wdev->auth_bsses[i]->pub;
502                         break;
503                 }
504                 if (wdev->authtry_bsses[i] &&
505                     memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
506                         req.bss = &wdev->authtry_bsses[i]->pub;
507                         break;
508                 }
509         }
510
511         if (!req.bss)
512                 return -ENOTCONN;
513
514         return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
515 }
516
517 int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
518                          struct net_device *dev, const u8 *bssid,
519                          const u8 *ie, int ie_len, u16 reason)
520 {
521         struct wireless_dev *wdev = dev->ieee80211_ptr;
522         int err;
523
524         wdev_lock(wdev);
525         err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
526         wdev_unlock(wdev);
527
528         return err;
529 }
530
531 static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
532                                     struct net_device *dev, const u8 *bssid,
533                                     const u8 *ie, int ie_len, u16 reason)
534 {
535         struct wireless_dev *wdev = dev->ieee80211_ptr;
536         struct cfg80211_disassoc_request req;
537
538         ASSERT_WDEV_LOCK(wdev);
539
540         memset(&req, 0, sizeof(req));
541         req.reason_code = reason;
542         req.ie = ie;
543         req.ie_len = ie_len;
544         if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
545                 req.bss = &wdev->current_bss->pub;
546         else
547                 return -ENOTCONN;
548
549         return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
550 }
551
552 int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
553                            struct net_device *dev, const u8 *bssid,
554                            const u8 *ie, int ie_len, u16 reason)
555 {
556         struct wireless_dev *wdev = dev->ieee80211_ptr;
557         int err;
558
559         wdev_lock(wdev);
560         err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
561         wdev_unlock(wdev);
562
563         return err;
564 }
565
566 void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
567                         struct net_device *dev)
568 {
569         struct wireless_dev *wdev = dev->ieee80211_ptr;
570         struct cfg80211_deauth_request req;
571         int i;
572
573         ASSERT_WDEV_LOCK(wdev);
574
575         if (!rdev->ops->deauth)
576                 return;
577
578         memset(&req, 0, sizeof(req));
579         req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
580         req.ie = NULL;
581         req.ie_len = 0;
582
583         if (wdev->current_bss) {
584                 req.bss = &wdev->current_bss->pub;
585                 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
586                 if (wdev->current_bss) {
587                         cfg80211_unhold_bss(wdev->current_bss);
588                         cfg80211_put_bss(&wdev->current_bss->pub);
589                         wdev->current_bss = NULL;
590                 }
591         }
592
593         for (i = 0; i < MAX_AUTH_BSSES; i++) {
594                 if (wdev->auth_bsses[i]) {
595                         req.bss = &wdev->auth_bsses[i]->pub;
596                         rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
597                         if (wdev->auth_bsses[i]) {
598                                 cfg80211_unhold_bss(wdev->auth_bsses[i]);
599                                 cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
600                                 wdev->auth_bsses[i] = NULL;
601                         }
602                 }
603                 if (wdev->authtry_bsses[i]) {
604                         req.bss = &wdev->authtry_bsses[i]->pub;
605                         rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
606                         if (wdev->authtry_bsses[i]) {
607                                 cfg80211_unhold_bss(wdev->authtry_bsses[i]);
608                                 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
609                                 wdev->authtry_bsses[i] = NULL;
610                         }
611                 }
612         }
613 }