]> git.karo-electronics.de Git - mv-sheeva.git/blob - net/wireless/sme.c
cfg80211: managed mode wext compatibility
[mv-sheeva.git] / net / wireless / sme.c
1 /*
2  * SME code for cfg80211's connect emulation.
3  *
4  * Copyright 2009       Johannes Berg <johannes@sipsolutions.net>
5  * Copyright (C) 2009   Intel Corporation. All rights reserved.
6  */
7
8 #include <linux/etherdevice.h>
9 #include <linux/if_arp.h>
10 #include <linux/workqueue.h>
11 #include <net/cfg80211.h>
12 #include <net/rtnetlink.h>
13 #include "nl80211.h"
14
15 struct cfg80211_conn {
16         struct cfg80211_connect_params params;
17         /* these are sub-states of the _CONNECTING sme_state */
18         enum {
19                 CFG80211_CONN_IDLE,
20                 CFG80211_CONN_SCANNING,
21                 CFG80211_CONN_SCAN_AGAIN,
22                 CFG80211_CONN_AUTHENTICATE_NEXT,
23                 CFG80211_CONN_AUTHENTICATING,
24                 CFG80211_CONN_ASSOCIATE_NEXT,
25                 CFG80211_CONN_ASSOCIATING,
26         } state;
27         u8 bssid[ETH_ALEN];
28         u8 *ie;
29         size_t ie_len;
30         bool auto_auth;
31 };
32
33
34 static int cfg80211_conn_scan(struct wireless_dev *wdev)
35 {
36         struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
37         struct cfg80211_scan_request *request;
38         int n_channels, err;
39
40         ASSERT_RTNL();
41
42         if (drv->scan_req)
43                 return -EBUSY;
44
45         if (wdev->conn->params.channel) {
46                 n_channels = 1;
47         } else {
48                 enum ieee80211_band band;
49                 n_channels = 0;
50
51                 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
52                         if (!wdev->wiphy->bands[band])
53                                 continue;
54                         n_channels += wdev->wiphy->bands[band]->n_channels;
55                 }
56         }
57         request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
58                           sizeof(request->channels[0]) * n_channels,
59                           GFP_KERNEL);
60         if (!request)
61                 return -ENOMEM;
62
63         request->channels = (void *)((char *)request + sizeof(*request));
64         if (wdev->conn->params.channel)
65                 request->channels[0] = wdev->conn->params.channel;
66         else {
67                 int i = 0, j;
68                 enum ieee80211_band band;
69
70                 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
71                         if (!wdev->wiphy->bands[band])
72                                 continue;
73                         for (j = 0; j < wdev->wiphy->bands[band]->n_channels;
74                              i++, j++)
75                                 request->channels[i] =
76                                         &wdev->wiphy->bands[band]->channels[j];
77                 }
78         }
79         request->n_channels = n_channels;
80         request->ssids = (void *)(request->channels + n_channels);
81         request->n_ssids = 1;
82
83         memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
84                 wdev->conn->params.ssid_len);
85         request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
86
87         request->ifidx = wdev->netdev->ifindex;
88         request->wiphy = &drv->wiphy;
89
90         drv->scan_req = request;
91
92         err = drv->ops->scan(wdev->wiphy, wdev->netdev, request);
93         if (!err) {
94                 wdev->conn->state = CFG80211_CONN_SCANNING;
95                 nl80211_send_scan_start(drv, wdev->netdev);
96         } else {
97                 drv->scan_req = NULL;
98                 kfree(request);
99         }
100         return err;
101 }
102
103 static int cfg80211_conn_do_work(struct wireless_dev *wdev)
104 {
105         struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
106         union {
107                 struct cfg80211_auth_request auth_req;
108                 struct cfg80211_assoc_request assoc_req;
109         } u;
110
111         memset(&u, 0, sizeof(u));
112
113         if (!wdev->conn)
114                 return 0;
115
116         switch (wdev->conn->state) {
117         case CFG80211_CONN_SCAN_AGAIN:
118                 return cfg80211_conn_scan(wdev);
119         case CFG80211_CONN_AUTHENTICATE_NEXT:
120                 u.auth_req.chan = wdev->conn->params.channel;
121                 u.auth_req.peer_addr = wdev->conn->params.bssid;
122                 u.auth_req.ssid = wdev->conn->params.ssid;
123                 u.auth_req.ssid_len = wdev->conn->params.ssid_len;
124                 u.auth_req.auth_type = wdev->conn->params.auth_type;
125                 u.auth_req.ie = NULL;
126                 u.auth_req.ie_len = 0;
127                 wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
128                 BUG_ON(!drv->ops->auth);
129                 return drv->ops->auth(wdev->wiphy, wdev->netdev, &u.auth_req);
130         case CFG80211_CONN_ASSOCIATE_NEXT:
131                 u.assoc_req.chan = wdev->conn->params.channel;
132                 u.assoc_req.peer_addr = wdev->conn->params.bssid;
133                 u.assoc_req.ssid = wdev->conn->params.ssid;
134                 u.assoc_req.ssid_len = wdev->conn->params.ssid_len;
135                 u.assoc_req.ie = wdev->conn->params.ie;
136                 u.assoc_req.ie_len = wdev->conn->params.ie_len;
137                 u.assoc_req.use_mfp = false;
138                 memcpy(&u.assoc_req.crypto, &wdev->conn->params.crypto,
139                         sizeof(u.assoc_req.crypto));
140                 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
141                 BUG_ON(!drv->ops->assoc);
142                 return drv->ops->assoc(wdev->wiphy, wdev->netdev,
143                                         &u.assoc_req);
144         default:
145                 return 0;
146         }
147 }
148
149 void cfg80211_conn_work(struct work_struct *work)
150 {
151         struct cfg80211_registered_device *drv =
152                 container_of(work, struct cfg80211_registered_device, conn_work);
153         struct wireless_dev *wdev;
154
155         rtnl_lock();
156         mutex_lock(&drv->devlist_mtx);
157
158         list_for_each_entry(wdev, &drv->netdev_list, list) {
159                 if (!netif_running(wdev->netdev))
160                         continue;
161                 if (wdev->sme_state != CFG80211_SME_CONNECTING)
162                         continue;
163                 if (cfg80211_conn_do_work(wdev))
164                         cfg80211_connect_result(wdev->netdev,
165                                                 wdev->conn->params.bssid,
166                                                 NULL, 0, NULL, 0,
167                                                 WLAN_STATUS_UNSPECIFIED_FAILURE,
168                                                 GFP_ATOMIC);
169         }
170
171         mutex_unlock(&drv->devlist_mtx);
172         rtnl_unlock();
173 }
174
175 static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
176 {
177         struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
178         struct cfg80211_bss *bss;
179         u16 capa = WLAN_CAPABILITY_ESS;
180
181         if (wdev->conn->params.privacy)
182                 capa |= WLAN_CAPABILITY_PRIVACY;
183
184         bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid,
185                                wdev->conn->params.ssid,
186                                wdev->conn->params.ssid_len,
187                                WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
188                                capa);
189
190         if (!bss)
191                 return false;
192
193         memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
194         wdev->conn->params.bssid = wdev->conn->bssid;
195         wdev->conn->params.channel = bss->channel;
196         wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
197         schedule_work(&drv->conn_work);
198
199         cfg80211_put_bss(bss);
200         return true;
201 }
202
203 void cfg80211_sme_scan_done(struct net_device *dev)
204 {
205         struct wireless_dev *wdev = dev->ieee80211_ptr;
206         struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
207
208         if (wdev->sme_state != CFG80211_SME_CONNECTING)
209                 return;
210
211         if (WARN_ON(!wdev->conn))
212                 return;
213
214         if (wdev->conn->state != CFG80211_CONN_SCANNING &&
215             wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
216                 return;
217
218         if (!cfg80211_get_conn_bss(wdev)) {
219                 /* not found */
220                 if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
221                         schedule_work(&drv->conn_work);
222                 else
223                         cfg80211_connect_result(dev, wdev->conn->params.bssid,
224                                                 NULL, 0, NULL, 0,
225                                                 WLAN_STATUS_UNSPECIFIED_FAILURE,
226                                                 GFP_ATOMIC);
227                 return;
228         }
229 }
230
231 void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
232 {
233         struct wireless_dev *wdev = dev->ieee80211_ptr;
234         struct wiphy *wiphy = wdev->wiphy;
235         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
236         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
237         u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
238
239         /* should only RX auth frames when connecting */
240         if (wdev->sme_state != CFG80211_SME_CONNECTING)
241                 return;
242
243         if (WARN_ON(!wdev->conn))
244                 return;
245
246         if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
247             wdev->conn->auto_auth &&
248             wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
249                 /* select automatically between only open, shared, leap */
250                 switch (wdev->conn->params.auth_type) {
251                 case NL80211_AUTHTYPE_OPEN_SYSTEM:
252                         wdev->conn->params.auth_type =
253                                 NL80211_AUTHTYPE_SHARED_KEY;
254                         break;
255                 case NL80211_AUTHTYPE_SHARED_KEY:
256                         wdev->conn->params.auth_type =
257                                 NL80211_AUTHTYPE_NETWORK_EAP;
258                         break;
259                 default:
260                         /* huh? */
261                         wdev->conn->params.auth_type =
262                                 NL80211_AUTHTYPE_OPEN_SYSTEM;
263                         break;
264                 }
265                 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
266                 schedule_work(&rdev->conn_work);
267         } else if (status_code != WLAN_STATUS_SUCCESS)
268                 wdev->sme_state = CFG80211_SME_IDLE;
269         else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
270                  wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
271                 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
272                 schedule_work(&rdev->conn_work);
273         }
274 }
275
276 static void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
277                                       const u8 *req_ie, size_t req_ie_len,
278                                       const u8 *resp_ie, size_t resp_ie_len,
279                                       u16 status, bool wextev, gfp_t gfp)
280 {
281         struct wireless_dev *wdev = dev->ieee80211_ptr;
282         struct cfg80211_bss *bss;
283 #ifdef CONFIG_WIRELESS_EXT
284         union iwreq_data wrqu;
285 #endif
286
287         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
288                 return;
289
290         if (wdev->sme_state != CFG80211_SME_CONNECTING)
291                 return;
292
293         if (wdev->current_bss) {
294                 cfg80211_unhold_bss(wdev->current_bss);
295                 cfg80211_put_bss(wdev->current_bss);
296                 wdev->current_bss = NULL;
297         }
298
299         if (status == WLAN_STATUS_SUCCESS) {
300                 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
301                                        wdev->ssid, wdev->ssid_len,
302                                        WLAN_CAPABILITY_ESS,
303                                        WLAN_CAPABILITY_ESS);
304
305                 if (WARN_ON(!bss))
306                         return;
307
308                 cfg80211_hold_bss(bss);
309                 wdev->current_bss = bss;
310
311                 wdev->sme_state = CFG80211_SME_CONNECTED;
312         } else {
313                 wdev->sme_state = CFG80211_SME_IDLE;
314         }
315
316         if (wdev->conn)
317                 wdev->conn->state = CFG80211_CONN_IDLE;
318
319         nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid,
320                                     req_ie, req_ie_len, resp_ie, resp_ie_len,
321                                     status, gfp);
322
323 #ifdef CONFIG_WIRELESS_EXT
324         if (wextev) {
325                 if (req_ie && status == WLAN_STATUS_SUCCESS) {
326                         memset(&wrqu, 0, sizeof(wrqu));
327                         wrqu.data.length = req_ie_len;
328                         wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
329                 }
330
331                 if (resp_ie && status == WLAN_STATUS_SUCCESS) {
332                         memset(&wrqu, 0, sizeof(wrqu));
333                         wrqu.data.length = resp_ie_len;
334                         wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
335                 }
336
337                 memset(&wrqu, 0, sizeof(wrqu));
338                 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
339                 if (bssid && status == WLAN_STATUS_SUCCESS)
340                         memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
341                 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
342         }
343 #endif
344 }
345
346 void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
347                              const u8 *req_ie, size_t req_ie_len,
348                              const u8 *resp_ie, size_t resp_ie_len,
349                              u16 status, gfp_t gfp)
350 {
351         bool wextev = status == WLAN_STATUS_SUCCESS;
352         __cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, status, wextev, gfp);
353 }
354 EXPORT_SYMBOL(cfg80211_connect_result);
355
356 void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
357                      const u8 *req_ie, size_t req_ie_len,
358                      const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
359 {
360         struct wireless_dev *wdev = dev->ieee80211_ptr;
361         struct cfg80211_bss *bss;
362 #ifdef CONFIG_WIRELESS_EXT
363         union iwreq_data wrqu;
364 #endif
365
366         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
367                 return;
368
369         if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
370                 return;
371
372         /* internal error -- how did we get to CONNECTED w/o BSS? */
373         if (WARN_ON(!wdev->current_bss)) {
374                 return;
375         }
376
377         cfg80211_unhold_bss(wdev->current_bss);
378         cfg80211_put_bss(wdev->current_bss);
379         wdev->current_bss = NULL;
380
381         bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
382                                wdev->ssid, wdev->ssid_len,
383                                WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
384
385         if (WARN_ON(!bss))
386                 return;
387
388         cfg80211_hold_bss(bss);
389         wdev->current_bss = bss;
390
391         nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, bssid,
392                             req_ie, req_ie_len, resp_ie, resp_ie_len, gfp);
393
394 #ifdef CONFIG_WIRELESS_EXT
395         if (req_ie) {
396                 memset(&wrqu, 0, sizeof(wrqu));
397                 wrqu.data.length = req_ie_len;
398                 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
399         }
400
401         if (resp_ie) {
402                 memset(&wrqu, 0, sizeof(wrqu));
403                 wrqu.data.length = resp_ie_len;
404                 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
405         }
406
407         memset(&wrqu, 0, sizeof(wrqu));
408         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
409         memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
410         wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
411 #endif
412 }
413 EXPORT_SYMBOL(cfg80211_roamed);
414
415 void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
416                              size_t ie_len, u16 reason, bool from_ap)
417 {
418         struct wireless_dev *wdev = dev->ieee80211_ptr;
419 #ifdef CONFIG_WIRELESS_EXT
420         union iwreq_data wrqu;
421 #endif
422
423         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
424                 return;
425
426         if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
427                 return;
428
429         if (wdev->current_bss) {
430                 cfg80211_unhold_bss(wdev->current_bss);
431                 cfg80211_put_bss(wdev->current_bss);
432         }
433
434         wdev->current_bss = NULL;
435         wdev->sme_state = CFG80211_SME_IDLE;
436
437         if (wdev->conn) {
438                 kfree(wdev->conn->ie);
439                 wdev->conn->ie = NULL;
440         }
441
442         nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
443                                   reason, ie, ie_len, from_ap, gfp);
444
445 #ifdef CONFIG_WIRELESS_EXT
446         memset(&wrqu, 0, sizeof(wrqu));
447         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
448         wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
449 #endif
450 }
451
452 void cfg80211_disconnected(struct net_device *dev, u16 reason,
453                            u8 *ie, size_t ie_len, gfp_t gfp)
454 {
455         __cfg80211_disconnected(dev, gfp, ie, ie_len, reason, true);
456 }
457 EXPORT_SYMBOL(cfg80211_disconnected);
458
459 int cfg80211_connect(struct cfg80211_registered_device *rdev,
460                      struct net_device *dev,
461                      struct cfg80211_connect_params *connect)
462 {
463         int err;
464         struct wireless_dev *wdev = dev->ieee80211_ptr;
465
466         if (wdev->sme_state != CFG80211_SME_IDLE)
467                 return -EALREADY;
468
469         if (!rdev->ops->connect) {
470                 if (!rdev->ops->auth || !rdev->ops->assoc)
471                         return -EOPNOTSUPP;
472
473                 if (!wdev->conn) {
474                         wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
475                         if (!wdev->conn)
476                                 return -ENOMEM;
477                 } else
478                         memset(wdev->conn, 0, sizeof(*wdev->conn));
479
480                 /*
481                  * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
482                  */
483                 memcpy(&wdev->conn->params, connect, sizeof(*connect));
484                 if (connect->bssid) {
485                         wdev->conn->params.bssid = wdev->conn->bssid;
486                         memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
487                 }
488
489                 if (connect->ie) {
490                         wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
491                                                 GFP_KERNEL);
492                         wdev->conn->params.ie = wdev->conn->ie;
493                         if (!wdev->conn->ie)
494                                 return -ENOMEM;
495                 }
496
497                 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
498                         wdev->conn->auto_auth = true;
499                         /* start with open system ... should mostly work */
500                         wdev->conn->params.auth_type =
501                                 NL80211_AUTHTYPE_OPEN_SYSTEM;
502                 } else {
503                         wdev->conn->auto_auth = false;
504                 }
505
506                 memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
507                 wdev->ssid_len = connect->ssid_len;
508                 wdev->conn->params.ssid = wdev->ssid;
509                 wdev->conn->params.ssid_len = connect->ssid_len;
510
511                 /* don't care about result -- but fill bssid & channel */
512                 if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
513                         cfg80211_get_conn_bss(wdev);
514
515                 wdev->sme_state = CFG80211_SME_CONNECTING;
516
517                 /* we're good if we have both BSSID and channel */
518                 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
519                         wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
520                         err = cfg80211_conn_do_work(wdev);
521                 } else {
522                         /* otherwise we'll need to scan for the AP first */
523                         err = cfg80211_conn_scan(wdev);
524                         /*
525                          * If we can't scan right now, then we need to scan again
526                          * after the current scan finished, since the parameters
527                          * changed (unless we find a good AP anyway).
528                          */
529                         if (err == -EBUSY) {
530                                 err = 0;
531                                 wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
532                         }
533                 }
534                 if (err)
535                         wdev->sme_state = CFG80211_SME_IDLE;
536
537                 return err;
538         } else {
539                 wdev->sme_state = CFG80211_SME_CONNECTING;
540                 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
541                 if (err) {
542                         wdev->sme_state = CFG80211_SME_IDLE;
543                         return err;
544                 }
545
546                 memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
547                 wdev->ssid_len = connect->ssid_len;
548
549                 return 0;
550         }
551 }
552
553 int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
554                         struct net_device *dev, u16 reason, bool wextev)
555 {
556         struct wireless_dev *wdev = dev->ieee80211_ptr;
557         int err;
558
559         if (wdev->sme_state == CFG80211_SME_IDLE)
560                 return -EINVAL;
561
562         if (!rdev->ops->disconnect) {
563                 struct cfg80211_deauth_request deauth;
564                 u8 bssid[ETH_ALEN];
565
566                 /* internal bug. */
567                 if (WARN_ON(!wdev->conn))
568                         return -EINVAL;
569
570                 if (wdev->sme_state == CFG80211_SME_CONNECTING &&
571                     (wdev->conn->state == CFG80211_CONN_SCANNING ||
572                      wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
573                         wdev->sme_state = CFG80211_SME_IDLE;
574                         return 0;
575                 }
576
577                 if (!rdev->ops->deauth)
578                         return -EOPNOTSUPP;
579
580                 memset(&deauth, 0, sizeof(deauth));
581
582                 /* wdev->conn->params.bssid must be set if > SCANNING */
583                 memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN);
584                 deauth.peer_addr = bssid;
585                 deauth.reason_code = reason;
586
587                 err = rdev->ops->deauth(&rdev->wiphy, dev, &deauth);
588                 if (err)
589                         return err;
590         } else {
591                 err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
592                 if (err)
593                         return err;
594         }
595
596         if (wdev->sme_state == CFG80211_SME_CONNECTED)
597                 __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false);
598         else if (wdev->sme_state == CFG80211_SME_CONNECTING)
599                 __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
600                                           WLAN_STATUS_UNSPECIFIED_FAILURE,
601                                           wextev, GFP_KERNEL);
602
603         return 0;
604 }