cfg80211: use reassociation when possible
[pandora-kernel.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 <linux/wireless.h>
12 #include <net/iw_handler.h>
13 #include <net/cfg80211.h>
14 #include <net/rtnetlink.h>
15 #include "nl80211.h"
16 #include "reg.h"
17
18 struct cfg80211_conn {
19         struct cfg80211_connect_params params;
20         /* these are sub-states of the _CONNECTING sme_state */
21         enum {
22                 CFG80211_CONN_IDLE,
23                 CFG80211_CONN_SCANNING,
24                 CFG80211_CONN_SCAN_AGAIN,
25                 CFG80211_CONN_AUTHENTICATE_NEXT,
26                 CFG80211_CONN_AUTHENTICATING,
27                 CFG80211_CONN_ASSOCIATE_NEXT,
28                 CFG80211_CONN_ASSOCIATING,
29         } state;
30         u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
31         u8 *ie;
32         size_t ie_len;
33         bool auto_auth, prev_bssid_valid;
34 };
35
36
37 static int cfg80211_conn_scan(struct wireless_dev *wdev)
38 {
39         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
40         struct cfg80211_scan_request *request;
41         int n_channels, err;
42
43         ASSERT_RTNL();
44         ASSERT_RDEV_LOCK(rdev);
45         ASSERT_WDEV_LOCK(wdev);
46
47         if (rdev->scan_req)
48                 return -EBUSY;
49
50         if (wdev->conn->params.channel) {
51                 n_channels = 1;
52         } else {
53                 enum ieee80211_band band;
54                 n_channels = 0;
55
56                 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
57                         if (!wdev->wiphy->bands[band])
58                                 continue;
59                         n_channels += wdev->wiphy->bands[band]->n_channels;
60                 }
61         }
62         request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
63                           sizeof(request->channels[0]) * n_channels,
64                           GFP_KERNEL);
65         if (!request)
66                 return -ENOMEM;
67
68         request->channels = (void *)((char *)request + sizeof(*request));
69         if (wdev->conn->params.channel)
70                 request->channels[0] = wdev->conn->params.channel;
71         else {
72                 int i = 0, j;
73                 enum ieee80211_band band;
74
75                 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
76                         if (!wdev->wiphy->bands[band])
77                                 continue;
78                         for (j = 0; j < wdev->wiphy->bands[band]->n_channels;
79                              i++, j++)
80                                 request->channels[i] =
81                                         &wdev->wiphy->bands[band]->channels[j];
82                 }
83         }
84         request->n_channels = n_channels;
85         request->ssids = (void *)(request->channels + n_channels);
86         request->n_ssids = 1;
87
88         memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
89                 wdev->conn->params.ssid_len);
90         request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
91
92         request->dev = wdev->netdev;
93         request->wiphy = &rdev->wiphy;
94
95         rdev->scan_req = request;
96
97         err = rdev->ops->scan(wdev->wiphy, wdev->netdev, request);
98         if (!err) {
99                 wdev->conn->state = CFG80211_CONN_SCANNING;
100                 nl80211_send_scan_start(rdev, wdev->netdev);
101                 dev_hold(wdev->netdev);
102         } else {
103                 rdev->scan_req = NULL;
104                 kfree(request);
105         }
106         return err;
107 }
108
109 static int cfg80211_conn_do_work(struct wireless_dev *wdev)
110 {
111         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
112         struct cfg80211_connect_params *params;
113         const u8 *prev_bssid = NULL;
114         int err;
115
116         ASSERT_WDEV_LOCK(wdev);
117
118         if (!wdev->conn)
119                 return 0;
120
121         params = &wdev->conn->params;
122
123         switch (wdev->conn->state) {
124         case CFG80211_CONN_SCAN_AGAIN:
125                 return cfg80211_conn_scan(wdev);
126         case CFG80211_CONN_AUTHENTICATE_NEXT:
127                 BUG_ON(!rdev->ops->auth);
128                 wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
129                 return __cfg80211_mlme_auth(rdev, wdev->netdev,
130                                             params->channel, params->auth_type,
131                                             params->bssid,
132                                             params->ssid, params->ssid_len,
133                                             NULL, 0,
134                                             params->key, params->key_len,
135                                             params->key_idx);
136         case CFG80211_CONN_ASSOCIATE_NEXT:
137                 BUG_ON(!rdev->ops->assoc);
138                 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
139                 if (wdev->conn->prev_bssid_valid)
140                         prev_bssid = wdev->conn->prev_bssid;
141                 err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
142                                             params->channel, params->bssid,
143                                             prev_bssid,
144                                             params->ssid, params->ssid_len,
145                                             params->ie, params->ie_len,
146                                             false, &params->crypto);
147                 if (err)
148                         __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
149                                                NULL, 0,
150                                                WLAN_REASON_DEAUTH_LEAVING);
151                 return err;
152         default:
153                 return 0;
154         }
155 }
156
157 void cfg80211_conn_work(struct work_struct *work)
158 {
159         struct cfg80211_registered_device *rdev =
160                 container_of(work, struct cfg80211_registered_device, conn_work);
161         struct wireless_dev *wdev;
162
163         rtnl_lock();
164         cfg80211_lock_rdev(rdev);
165         mutex_lock(&rdev->devlist_mtx);
166
167         list_for_each_entry(wdev, &rdev->netdev_list, list) {
168                 wdev_lock(wdev);
169                 if (!netif_running(wdev->netdev)) {
170                         wdev_unlock(wdev);
171                         continue;
172                 }
173                 if (wdev->sme_state != CFG80211_SME_CONNECTING) {
174                         wdev_unlock(wdev);
175                         continue;
176                 }
177                 if (cfg80211_conn_do_work(wdev))
178                         __cfg80211_connect_result(
179                                         wdev->netdev,
180                                         wdev->conn->params.bssid,
181                                         NULL, 0, NULL, 0,
182                                         WLAN_STATUS_UNSPECIFIED_FAILURE,
183                                         false, NULL);
184                 wdev_unlock(wdev);
185         }
186
187         mutex_unlock(&rdev->devlist_mtx);
188         cfg80211_unlock_rdev(rdev);
189         rtnl_unlock();
190 }
191
192 static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
193 {
194         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
195         struct cfg80211_bss *bss;
196         u16 capa = WLAN_CAPABILITY_ESS;
197
198         ASSERT_WDEV_LOCK(wdev);
199
200         if (wdev->conn->params.privacy)
201                 capa |= WLAN_CAPABILITY_PRIVACY;
202
203         bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid,
204                                wdev->conn->params.ssid,
205                                wdev->conn->params.ssid_len,
206                                WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
207                                capa);
208         if (!bss)
209                 return false;
210
211         memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
212         wdev->conn->params.bssid = wdev->conn->bssid;
213         wdev->conn->params.channel = bss->channel;
214         wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
215         schedule_work(&rdev->conn_work);
216
217         cfg80211_put_bss(bss);
218         return true;
219 }
220
221 static void __cfg80211_sme_scan_done(struct net_device *dev)
222 {
223         struct wireless_dev *wdev = dev->ieee80211_ptr;
224         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
225
226         ASSERT_WDEV_LOCK(wdev);
227
228         if (wdev->sme_state != CFG80211_SME_CONNECTING)
229                 return;
230
231         if (!wdev->conn)
232                 return;
233
234         if (wdev->conn->state != CFG80211_CONN_SCANNING &&
235             wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
236                 return;
237
238         if (!cfg80211_get_conn_bss(wdev)) {
239                 /* not found */
240                 if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
241                         schedule_work(&rdev->conn_work);
242                 else
243                         __cfg80211_connect_result(
244                                         wdev->netdev,
245                                         wdev->conn->params.bssid,
246                                         NULL, 0, NULL, 0,
247                                         WLAN_STATUS_UNSPECIFIED_FAILURE,
248                                         false, NULL);
249         }
250 }
251
252 void cfg80211_sme_scan_done(struct net_device *dev)
253 {
254         struct wireless_dev *wdev = dev->ieee80211_ptr;
255
256         mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
257         wdev_lock(wdev);
258         __cfg80211_sme_scan_done(dev);
259         wdev_unlock(wdev);
260         mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
261 }
262
263 void cfg80211_sme_rx_auth(struct net_device *dev,
264                           const u8 *buf, size_t len)
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         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
270         u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
271
272         ASSERT_WDEV_LOCK(wdev);
273
274         /* should only RX auth frames when connecting */
275         if (wdev->sme_state != CFG80211_SME_CONNECTING)
276                 return;
277
278         if (WARN_ON(!wdev->conn))
279                 return;
280
281         if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
282             wdev->conn->auto_auth &&
283             wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
284                 /* select automatically between only open, shared, leap */
285                 switch (wdev->conn->params.auth_type) {
286                 case NL80211_AUTHTYPE_OPEN_SYSTEM:
287                         if (wdev->connect_keys)
288                                 wdev->conn->params.auth_type =
289                                         NL80211_AUTHTYPE_SHARED_KEY;
290                         else
291                                 wdev->conn->params.auth_type =
292                                         NL80211_AUTHTYPE_NETWORK_EAP;
293                         break;
294                 case NL80211_AUTHTYPE_SHARED_KEY:
295                         wdev->conn->params.auth_type =
296                                 NL80211_AUTHTYPE_NETWORK_EAP;
297                         break;
298                 default:
299                         /* huh? */
300                         wdev->conn->params.auth_type =
301                                 NL80211_AUTHTYPE_OPEN_SYSTEM;
302                         break;
303                 }
304                 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
305                 schedule_work(&rdev->conn_work);
306         } else if (status_code != WLAN_STATUS_SUCCESS) {
307                 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
308                                           status_code, false, NULL);
309         } else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
310                  wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
311                 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
312                 schedule_work(&rdev->conn_work);
313         }
314 }
315
316 bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
317 {
318         struct wiphy *wiphy = wdev->wiphy;
319         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
320
321         if (WARN_ON(!wdev->conn))
322                 return false;
323
324         if (!wdev->conn->prev_bssid_valid)
325                 return false;
326
327         /*
328          * Some stupid APs don't accept reassoc, so we
329          * need to fall back to trying regular assoc.
330          */
331         wdev->conn->prev_bssid_valid = false;
332         wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
333         schedule_work(&rdev->conn_work);
334
335         return true;
336 }
337
338 void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
339                                const u8 *req_ie, size_t req_ie_len,
340                                const u8 *resp_ie, size_t resp_ie_len,
341                                u16 status, bool wextev,
342                                struct cfg80211_bss *bss)
343 {
344         struct wireless_dev *wdev = dev->ieee80211_ptr;
345         u8 *country_ie;
346 #ifdef CONFIG_WIRELESS_EXT
347         union iwreq_data wrqu;
348 #endif
349
350         ASSERT_WDEV_LOCK(wdev);
351
352         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
353                 return;
354
355         if (wdev->sme_state == CFG80211_SME_CONNECTED)
356                 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev,
357                                     bssid, req_ie, req_ie_len,
358                                     resp_ie, resp_ie_len, GFP_KERNEL);
359         else
360                 nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
361                                             bssid, req_ie, req_ie_len,
362                                             resp_ie, resp_ie_len,
363                                             status, GFP_KERNEL);
364
365 #ifdef CONFIG_WIRELESS_EXT
366         if (wextev) {
367                 if (req_ie && status == WLAN_STATUS_SUCCESS) {
368                         memset(&wrqu, 0, sizeof(wrqu));
369                         wrqu.data.length = req_ie_len;
370                         wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, req_ie);
371                 }
372
373                 if (resp_ie && status == WLAN_STATUS_SUCCESS) {
374                         memset(&wrqu, 0, sizeof(wrqu));
375                         wrqu.data.length = resp_ie_len;
376                         wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
377                 }
378
379                 memset(&wrqu, 0, sizeof(wrqu));
380                 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
381                 if (bssid && status == WLAN_STATUS_SUCCESS) {
382                         memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
383                         memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
384                         wdev->wext.prev_bssid_valid = true;
385                 }
386                 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
387         }
388 #endif
389
390         if (wdev->current_bss) {
391                 cfg80211_unhold_bss(wdev->current_bss);
392                 cfg80211_put_bss(&wdev->current_bss->pub);
393                 wdev->current_bss = NULL;
394         }
395
396         if (status == WLAN_STATUS_SUCCESS &&
397             wdev->sme_state == CFG80211_SME_IDLE)
398                 goto success;
399
400         if (wdev->sme_state != CFG80211_SME_CONNECTING)
401                 return;
402
403         if (wdev->conn)
404                 wdev->conn->state = CFG80211_CONN_IDLE;
405
406         if (status != WLAN_STATUS_SUCCESS) {
407                 wdev->sme_state = CFG80211_SME_IDLE;
408                 kfree(wdev->conn);
409                 wdev->conn = NULL;
410                 kfree(wdev->connect_keys);
411                 wdev->connect_keys = NULL;
412                 wdev->ssid_len = 0;
413                 return;
414         }
415
416  success:
417         if (!bss)
418                 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
419                                        wdev->ssid, wdev->ssid_len,
420                                        WLAN_CAPABILITY_ESS,
421                                        WLAN_CAPABILITY_ESS);
422
423         if (WARN_ON(!bss))
424                 return;
425
426         cfg80211_hold_bss(bss_from_pub(bss));
427         wdev->current_bss = bss_from_pub(bss);
428
429         wdev->sme_state = CFG80211_SME_CONNECTED;
430         cfg80211_upload_connect_keys(wdev);
431
432         country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
433
434         if (!country_ie)
435                 return;
436
437         /*
438          * ieee80211_bss_get_ie() ensures we can access:
439          * - country_ie + 2, the start of the country ie data, and
440          * - and country_ie[1] which is the IE length
441          */
442         regulatory_hint_11d(wdev->wiphy,
443                             country_ie + 2,
444                             country_ie[1]);
445 }
446
447 void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
448                              const u8 *req_ie, size_t req_ie_len,
449                              const u8 *resp_ie, size_t resp_ie_len,
450                              u16 status, gfp_t gfp)
451 {
452         struct wireless_dev *wdev = dev->ieee80211_ptr;
453         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
454         struct cfg80211_event *ev;
455         unsigned long flags;
456
457         ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
458         if (!ev)
459                 return;
460
461         ev->type = EVENT_CONNECT_RESULT;
462         memcpy(ev->cr.bssid, bssid, ETH_ALEN);
463         ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
464         ev->cr.req_ie_len = req_ie_len;
465         memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
466         ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
467         ev->cr.resp_ie_len = resp_ie_len;
468         memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
469         ev->cr.status = status;
470
471         spin_lock_irqsave(&wdev->event_lock, flags);
472         list_add_tail(&ev->list, &wdev->event_list);
473         spin_unlock_irqrestore(&wdev->event_lock, flags);
474         schedule_work(&rdev->event_work);
475 }
476 EXPORT_SYMBOL(cfg80211_connect_result);
477
478 void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
479                        const u8 *req_ie, size_t req_ie_len,
480                        const u8 *resp_ie, size_t resp_ie_len)
481 {
482         struct cfg80211_bss *bss;
483 #ifdef CONFIG_WIRELESS_EXT
484         union iwreq_data wrqu;
485 #endif
486
487         ASSERT_WDEV_LOCK(wdev);
488
489         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
490                 return;
491
492         if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
493                 return;
494
495         /* internal error -- how did we get to CONNECTED w/o BSS? */
496         if (WARN_ON(!wdev->current_bss)) {
497                 return;
498         }
499
500         cfg80211_unhold_bss(wdev->current_bss);
501         cfg80211_put_bss(&wdev->current_bss->pub);
502         wdev->current_bss = NULL;
503
504         bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
505                                wdev->ssid, wdev->ssid_len,
506                                WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
507
508         if (WARN_ON(!bss))
509                 return;
510
511         cfg80211_hold_bss(bss_from_pub(bss));
512         wdev->current_bss = bss_from_pub(bss);
513
514         nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid,
515                             req_ie, req_ie_len, resp_ie, resp_ie_len,
516                             GFP_KERNEL);
517
518 #ifdef CONFIG_WIRELESS_EXT
519         if (req_ie) {
520                 memset(&wrqu, 0, sizeof(wrqu));
521                 wrqu.data.length = req_ie_len;
522                 wireless_send_event(wdev->netdev, IWEVASSOCREQIE,
523                                     &wrqu, req_ie);
524         }
525
526         if (resp_ie) {
527                 memset(&wrqu, 0, sizeof(wrqu));
528                 wrqu.data.length = resp_ie_len;
529                 wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
530                                     &wrqu, resp_ie);
531         }
532
533         memset(&wrqu, 0, sizeof(wrqu));
534         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
535         memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
536         memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
537         wdev->wext.prev_bssid_valid = true;
538         wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
539 #endif
540 }
541
542 void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
543                      const u8 *req_ie, size_t req_ie_len,
544                      const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
545 {
546         struct wireless_dev *wdev = dev->ieee80211_ptr;
547         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
548         struct cfg80211_event *ev;
549         unsigned long flags;
550
551         ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
552         if (!ev)
553                 return;
554
555         ev->type = EVENT_ROAMED;
556         memcpy(ev->rm.bssid, bssid, ETH_ALEN);
557         ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
558         ev->rm.req_ie_len = req_ie_len;
559         memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len);
560         ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
561         ev->rm.resp_ie_len = resp_ie_len;
562         memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len);
563
564         spin_lock_irqsave(&wdev->event_lock, flags);
565         list_add_tail(&ev->list, &wdev->event_list);
566         spin_unlock_irqrestore(&wdev->event_lock, flags);
567         schedule_work(&rdev->event_work);
568 }
569 EXPORT_SYMBOL(cfg80211_roamed);
570
571 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
572                              size_t ie_len, u16 reason, bool from_ap)
573 {
574         struct wireless_dev *wdev = dev->ieee80211_ptr;
575         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
576         int i;
577 #ifdef CONFIG_WIRELESS_EXT
578         union iwreq_data wrqu;
579 #endif
580
581         ASSERT_WDEV_LOCK(wdev);
582
583         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
584                 return;
585
586         if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
587                 return;
588
589         if (wdev->current_bss) {
590                 cfg80211_unhold_bss(wdev->current_bss);
591                 cfg80211_put_bss(&wdev->current_bss->pub);
592         }
593
594         wdev->current_bss = NULL;
595         wdev->sme_state = CFG80211_SME_IDLE;
596         wdev->ssid_len = 0;
597
598         if (wdev->conn) {
599                 const u8 *bssid;
600                 int ret;
601
602                 kfree(wdev->conn->ie);
603                 wdev->conn->ie = NULL;
604                 kfree(wdev->conn);
605                 wdev->conn = NULL;
606
607                 /*
608                  * If this disconnect was due to a disassoc, we
609                  * we might still have an auth BSS around. For
610                  * the userspace SME that's currently expected,
611                  * but for the kernel SME (nl80211 CONNECT or
612                  * wireless extensions) we want to clear up all
613                  * state.
614                  */
615                 for (i = 0; i < MAX_AUTH_BSSES; i++) {
616                         if (!wdev->auth_bsses[i])
617                                 continue;
618                         bssid = wdev->auth_bsses[i]->pub.bssid;
619                         ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
620                                                 WLAN_REASON_DEAUTH_LEAVING);
621                         WARN(ret, "deauth failed: %d\n", ret);
622                 }
623         }
624
625         nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
626
627         /*
628          * Delete all the keys ... pairwise keys can't really
629          * exist any more anyway, but default keys might.
630          */
631         if (rdev->ops->del_key)
632                 for (i = 0; i < 6; i++)
633                         rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
634
635 #ifdef CONFIG_WIRELESS_EXT
636         memset(&wrqu, 0, sizeof(wrqu));
637         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
638         wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
639 #endif
640 }
641
642 void cfg80211_disconnected(struct net_device *dev, u16 reason,
643                            u8 *ie, size_t ie_len, gfp_t gfp)
644 {
645         struct wireless_dev *wdev = dev->ieee80211_ptr;
646         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
647         struct cfg80211_event *ev;
648         unsigned long flags;
649
650         ev = kzalloc(sizeof(*ev) + ie_len, gfp);
651         if (!ev)
652                 return;
653
654         ev->type = EVENT_DISCONNECTED;
655         ev->dc.ie = ((u8 *)ev) + sizeof(*ev);
656         ev->dc.ie_len = ie_len;
657         memcpy((void *)ev->dc.ie, ie, ie_len);
658         ev->dc.reason = reason;
659
660         spin_lock_irqsave(&wdev->event_lock, flags);
661         list_add_tail(&ev->list, &wdev->event_list);
662         spin_unlock_irqrestore(&wdev->event_lock, flags);
663         schedule_work(&rdev->event_work);
664 }
665 EXPORT_SYMBOL(cfg80211_disconnected);
666
667 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
668                        struct net_device *dev,
669                        struct cfg80211_connect_params *connect,
670                        struct cfg80211_cached_keys *connkeys,
671                        const u8 *prev_bssid)
672 {
673         struct wireless_dev *wdev = dev->ieee80211_ptr;
674         struct ieee80211_channel *chan;
675         int err;
676
677         ASSERT_WDEV_LOCK(wdev);
678
679         if (wdev->sme_state != CFG80211_SME_IDLE)
680                 return -EALREADY;
681
682         chan = rdev_fixed_channel(rdev, wdev);
683         if (chan && chan != connect->channel)
684                 return -EBUSY;
685
686         if (WARN_ON(wdev->connect_keys)) {
687                 kfree(wdev->connect_keys);
688                 wdev->connect_keys = NULL;
689         }
690
691         if (connkeys && connkeys->def >= 0) {
692                 int idx;
693                 u32 cipher;
694
695                 idx = connkeys->def;
696                 cipher = connkeys->params[idx].cipher;
697                 /* If given a WEP key we may need it for shared key auth */
698                 if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
699                     cipher == WLAN_CIPHER_SUITE_WEP104) {
700                         connect->key_idx = idx;
701                         connect->key = connkeys->params[idx].key;
702                         connect->key_len = connkeys->params[idx].key_len;
703
704                         /*
705                          * If ciphers are not set (e.g. when going through
706                          * iwconfig), we have to set them appropriately here.
707                          */
708                         if (connect->crypto.cipher_group == 0)
709                                 connect->crypto.cipher_group = cipher;
710
711                         if (connect->crypto.n_ciphers_pairwise == 0) {
712                                 connect->crypto.n_ciphers_pairwise = 1;
713                                 connect->crypto.ciphers_pairwise[0] = cipher;
714                         }
715                 }
716         }
717
718         if (!rdev->ops->connect) {
719                 if (!rdev->ops->auth || !rdev->ops->assoc)
720                         return -EOPNOTSUPP;
721
722                 if (WARN_ON(wdev->conn))
723                         return -EINPROGRESS;
724
725                 wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
726                 if (!wdev->conn)
727                         return -ENOMEM;
728
729                 /*
730                  * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
731                  */
732                 memcpy(&wdev->conn->params, connect, sizeof(*connect));
733                 if (connect->bssid) {
734                         wdev->conn->params.bssid = wdev->conn->bssid;
735                         memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
736                 }
737
738                 if (connect->ie) {
739                         wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
740                                                 GFP_KERNEL);
741                         wdev->conn->params.ie = wdev->conn->ie;
742                         if (!wdev->conn->ie) {
743                                 kfree(wdev->conn);
744                                 wdev->conn = NULL;
745                                 return -ENOMEM;
746                         }
747                 }
748
749                 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
750                         wdev->conn->auto_auth = true;
751                         /* start with open system ... should mostly work */
752                         wdev->conn->params.auth_type =
753                                 NL80211_AUTHTYPE_OPEN_SYSTEM;
754                 } else {
755                         wdev->conn->auto_auth = false;
756                 }
757
758                 memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
759                 wdev->ssid_len = connect->ssid_len;
760                 wdev->conn->params.ssid = wdev->ssid;
761                 wdev->conn->params.ssid_len = connect->ssid_len;
762
763                 /* don't care about result -- but fill bssid & channel */
764                 if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
765                         cfg80211_get_conn_bss(wdev);
766
767                 wdev->sme_state = CFG80211_SME_CONNECTING;
768                 wdev->connect_keys = connkeys;
769
770                 if (prev_bssid) {
771                         memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
772                         wdev->conn->prev_bssid_valid = true;
773                 }
774
775                 /* we're good if we have both BSSID and channel */
776                 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
777                         wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
778                         err = cfg80211_conn_do_work(wdev);
779                 } else {
780                         /* otherwise we'll need to scan for the AP first */
781                         err = cfg80211_conn_scan(wdev);
782                         /*
783                          * If we can't scan right now, then we need to scan again
784                          * after the current scan finished, since the parameters
785                          * changed (unless we find a good AP anyway).
786                          */
787                         if (err == -EBUSY) {
788                                 err = 0;
789                                 wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
790                         }
791                 }
792                 if (err) {
793                         kfree(wdev->conn);
794                         wdev->conn = NULL;
795                         wdev->sme_state = CFG80211_SME_IDLE;
796                         wdev->connect_keys = NULL;
797                         wdev->ssid_len = 0;
798                 }
799
800                 return err;
801         } else {
802                 wdev->sme_state = CFG80211_SME_CONNECTING;
803                 wdev->connect_keys = connkeys;
804                 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
805                 if (err) {
806                         wdev->connect_keys = NULL;
807                         wdev->sme_state = CFG80211_SME_IDLE;
808                         return err;
809                 }
810
811                 memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
812                 wdev->ssid_len = connect->ssid_len;
813
814                 return 0;
815         }
816 }
817
818 int cfg80211_connect(struct cfg80211_registered_device *rdev,
819                      struct net_device *dev,
820                      struct cfg80211_connect_params *connect,
821                      struct cfg80211_cached_keys *connkeys)
822 {
823         int err;
824
825         mutex_lock(&rdev->devlist_mtx);
826         wdev_lock(dev->ieee80211_ptr);
827         err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
828         wdev_unlock(dev->ieee80211_ptr);
829         mutex_unlock(&rdev->devlist_mtx);
830
831         return err;
832 }
833
834 int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
835                           struct net_device *dev, u16 reason, bool wextev)
836 {
837         struct wireless_dev *wdev = dev->ieee80211_ptr;
838         int err;
839
840         ASSERT_WDEV_LOCK(wdev);
841
842         if (wdev->sme_state == CFG80211_SME_IDLE)
843                 return -EINVAL;
844
845         kfree(wdev->connect_keys);
846         wdev->connect_keys = NULL;
847
848         if (!rdev->ops->disconnect) {
849                 if (!rdev->ops->deauth)
850                         return -EOPNOTSUPP;
851
852                 /* was it connected by userspace SME? */
853                 if (!wdev->conn) {
854                         cfg80211_mlme_down(rdev, dev);
855                         return 0;
856                 }
857
858                 if (wdev->sme_state == CFG80211_SME_CONNECTING &&
859                     (wdev->conn->state == CFG80211_CONN_SCANNING ||
860                      wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
861                         wdev->sme_state = CFG80211_SME_IDLE;
862                         kfree(wdev->conn);
863                         wdev->conn = NULL;
864                         wdev->ssid_len = 0;
865                         return 0;
866                 }
867
868                 /* wdev->conn->params.bssid must be set if > SCANNING */
869                 err = __cfg80211_mlme_deauth(rdev, dev,
870                                              wdev->conn->params.bssid,
871                                              NULL, 0, reason);
872                 if (err)
873                         return err;
874         } else {
875                 err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
876                 if (err)
877                         return err;
878         }
879
880         if (wdev->sme_state == CFG80211_SME_CONNECTED)
881                 __cfg80211_disconnected(dev, NULL, 0, 0, false);
882         else if (wdev->sme_state == CFG80211_SME_CONNECTING)
883                 __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
884                                           WLAN_STATUS_UNSPECIFIED_FAILURE,
885                                           wextev, NULL);
886
887         return 0;
888 }
889
890 int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
891                         struct net_device *dev,
892                         u16 reason, bool wextev)
893 {
894         int err;
895
896         wdev_lock(dev->ieee80211_ptr);
897         err = __cfg80211_disconnect(rdev, dev, reason, wextev);
898         wdev_unlock(dev->ieee80211_ptr);
899
900         return err;
901 }
902
903 void cfg80211_sme_disassoc(struct net_device *dev, int idx)
904 {
905         struct wireless_dev *wdev = dev->ieee80211_ptr;
906         struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
907         u8 bssid[ETH_ALEN];
908
909         ASSERT_WDEV_LOCK(wdev);
910
911         if (!wdev->conn)
912                 return;
913
914         if (wdev->conn->state == CFG80211_CONN_IDLE)
915                 return;
916
917         /*
918          * Ok, so the association was made by this SME -- we don't
919          * want it any more so deauthenticate too.
920          */
921
922         if (!wdev->auth_bsses[idx])
923                 return;
924
925         memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN);
926         if (__cfg80211_mlme_deauth(rdev, dev, bssid,
927                                    NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) {
928                 /* whatever -- assume gone anyway */
929                 cfg80211_unhold_bss(wdev->auth_bsses[idx]);
930                 cfg80211_put_bss(&wdev->auth_bsses[idx]->pub);
931                 wdev->auth_bsses[idx] = NULL;
932         }
933 }