2 * SME code for cfg80211's connect emulation.
4 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
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>
18 struct cfg80211_conn
{
19 struct cfg80211_connect_params params
;
20 /* these are sub-states of the _CONNECTING sme_state */
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 CFG80211_CONN_DEAUTH_ASSOC_FAIL
,
31 u8 bssid
[ETH_ALEN
], prev_bssid
[ETH_ALEN
];
34 bool auto_auth
, prev_bssid_valid
;
37 bool cfg80211_is_all_idle(void)
39 struct cfg80211_registered_device
*rdev
;
40 struct wireless_dev
*wdev
;
41 bool is_all_idle
= true;
43 mutex_lock(&cfg80211_mutex
);
46 * All devices must be idle as otherwise if you are actively
47 * scanning some new beacon hints could be learned and would
48 * count as new regulatory hints.
50 list_for_each_entry(rdev
, &cfg80211_rdev_list
, list
) {
51 cfg80211_lock_rdev(rdev
);
52 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
54 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
58 cfg80211_unlock_rdev(rdev
);
61 mutex_unlock(&cfg80211_mutex
);
66 static void disconnect_work(struct work_struct
*work
)
68 if (!cfg80211_is_all_idle())
71 regulatory_hint_disconnect();
74 static DECLARE_WORK(cfg80211_disconnect_work
, disconnect_work
);
76 static int cfg80211_conn_scan(struct wireless_dev
*wdev
)
78 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
79 struct cfg80211_scan_request
*request
;
83 ASSERT_RDEV_LOCK(rdev
);
84 ASSERT_WDEV_LOCK(wdev
);
89 if (wdev
->conn
->params
.channel
) {
92 enum ieee80211_band band
;
95 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
96 if (!wdev
->wiphy
->bands
[band
])
98 n_channels
+= wdev
->wiphy
->bands
[band
]->n_channels
;
101 request
= kzalloc(sizeof(*request
) + sizeof(request
->ssids
[0]) +
102 sizeof(request
->channels
[0]) * n_channels
,
107 if (wdev
->conn
->params
.channel
)
108 request
->channels
[0] = wdev
->conn
->params
.channel
;
111 enum ieee80211_band band
;
113 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
114 if (!wdev
->wiphy
->bands
[band
])
116 for (j
= 0; j
< wdev
->wiphy
->bands
[band
]->n_channels
;
118 request
->channels
[i
] =
119 &wdev
->wiphy
->bands
[band
]->channels
[j
];
122 request
->n_channels
= n_channels
;
123 request
->ssids
= (void *)&request
->channels
[n_channels
];
124 request
->n_ssids
= 1;
126 memcpy(request
->ssids
[0].ssid
, wdev
->conn
->params
.ssid
,
127 wdev
->conn
->params
.ssid_len
);
128 request
->ssids
[0].ssid_len
= wdev
->conn
->params
.ssid_len
;
130 request
->dev
= wdev
->netdev
;
131 request
->wiphy
= &rdev
->wiphy
;
133 rdev
->scan_req
= request
;
135 err
= rdev
->ops
->scan(wdev
->wiphy
, wdev
->netdev
, request
);
137 wdev
->conn
->state
= CFG80211_CONN_SCANNING
;
138 nl80211_send_scan_start(rdev
, wdev
->netdev
);
139 dev_hold(wdev
->netdev
);
141 rdev
->scan_req
= NULL
;
147 static int cfg80211_conn_do_work(struct wireless_dev
*wdev
)
149 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
150 struct cfg80211_connect_params
*params
;
151 const u8
*prev_bssid
= NULL
;
154 ASSERT_WDEV_LOCK(wdev
);
159 params
= &wdev
->conn
->params
;
161 switch (wdev
->conn
->state
) {
162 case CFG80211_CONN_SCAN_AGAIN
:
163 return cfg80211_conn_scan(wdev
);
164 case CFG80211_CONN_AUTHENTICATE_NEXT
:
165 BUG_ON(!rdev
->ops
->auth
);
166 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATING
;
167 return __cfg80211_mlme_auth(rdev
, wdev
->netdev
,
168 params
->channel
, params
->auth_type
,
170 params
->ssid
, params
->ssid_len
,
172 params
->key
, params
->key_len
,
174 case CFG80211_CONN_ASSOCIATE_NEXT
:
175 BUG_ON(!rdev
->ops
->assoc
);
176 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATING
;
177 if (wdev
->conn
->prev_bssid_valid
)
178 prev_bssid
= wdev
->conn
->prev_bssid
;
179 err
= __cfg80211_mlme_assoc(rdev
, wdev
->netdev
,
180 params
->channel
, params
->bssid
,
182 params
->ssid
, params
->ssid_len
,
183 params
->ie
, params
->ie_len
,
184 false, ¶ms
->crypto
);
186 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
188 WLAN_REASON_DEAUTH_LEAVING
);
190 case CFG80211_CONN_DEAUTH_ASSOC_FAIL
:
191 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
193 WLAN_REASON_DEAUTH_LEAVING
);
194 /* return an error so that we call __cfg80211_connect_result() */
201 void cfg80211_conn_work(struct work_struct
*work
)
203 struct cfg80211_registered_device
*rdev
=
204 container_of(work
, struct cfg80211_registered_device
, conn_work
);
205 struct wireless_dev
*wdev
;
206 u8 bssid_buf
[ETH_ALEN
], *bssid
= NULL
;
209 cfg80211_lock_rdev(rdev
);
210 mutex_lock(&rdev
->devlist_mtx
);
212 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
214 if (!netif_running(wdev
->netdev
)) {
218 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
) {
222 if (wdev
->conn
->params
.bssid
) {
223 memcpy(bssid_buf
, wdev
->conn
->params
.bssid
, ETH_ALEN
);
226 if (cfg80211_conn_do_work(wdev
))
227 __cfg80211_connect_result(
230 WLAN_STATUS_UNSPECIFIED_FAILURE
,
235 mutex_unlock(&rdev
->devlist_mtx
);
236 cfg80211_unlock_rdev(rdev
);
240 static struct cfg80211_bss
*cfg80211_get_conn_bss(struct wireless_dev
*wdev
)
242 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
243 struct cfg80211_bss
*bss
;
244 u16 capa
= WLAN_CAPABILITY_ESS
;
246 ASSERT_WDEV_LOCK(wdev
);
248 if (wdev
->conn
->params
.privacy
)
249 capa
|= WLAN_CAPABILITY_PRIVACY
;
251 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, wdev
->conn
->params
.bssid
,
252 wdev
->conn
->params
.ssid
,
253 wdev
->conn
->params
.ssid_len
,
254 WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_PRIVACY
,
259 memcpy(wdev
->conn
->bssid
, bss
->bssid
, ETH_ALEN
);
260 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
261 wdev
->conn
->params
.channel
= bss
->channel
;
262 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
263 schedule_work(&rdev
->conn_work
);
268 static void __cfg80211_sme_scan_done(struct net_device
*dev
)
270 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
271 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
272 struct cfg80211_bss
*bss
;
274 ASSERT_WDEV_LOCK(wdev
);
276 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
282 if (wdev
->conn
->state
!= CFG80211_CONN_SCANNING
&&
283 wdev
->conn
->state
!= CFG80211_CONN_SCAN_AGAIN
)
286 bss
= cfg80211_get_conn_bss(wdev
);
288 cfg80211_put_bss(bss
);
291 if (wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)
292 schedule_work(&rdev
->conn_work
);
294 __cfg80211_connect_result(
296 wdev
->conn
->params
.bssid
,
298 WLAN_STATUS_UNSPECIFIED_FAILURE
,
303 void cfg80211_sme_scan_done(struct net_device
*dev
)
305 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
307 mutex_lock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
309 __cfg80211_sme_scan_done(dev
);
311 mutex_unlock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
314 void cfg80211_sme_rx_auth(struct net_device
*dev
,
315 const u8
*buf
, size_t len
)
317 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
318 struct wiphy
*wiphy
= wdev
->wiphy
;
319 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
320 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
321 u16 status_code
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
323 ASSERT_WDEV_LOCK(wdev
);
325 /* should only RX auth frames when connecting */
326 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
329 if (WARN_ON(!wdev
->conn
))
332 if (status_code
== WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
&&
333 wdev
->conn
->auto_auth
&&
334 wdev
->conn
->params
.auth_type
!= NL80211_AUTHTYPE_NETWORK_EAP
) {
335 /* select automatically between only open, shared, leap */
336 switch (wdev
->conn
->params
.auth_type
) {
337 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
338 if (wdev
->connect_keys
)
339 wdev
->conn
->params
.auth_type
=
340 NL80211_AUTHTYPE_SHARED_KEY
;
342 wdev
->conn
->params
.auth_type
=
343 NL80211_AUTHTYPE_NETWORK_EAP
;
345 case NL80211_AUTHTYPE_SHARED_KEY
:
346 wdev
->conn
->params
.auth_type
=
347 NL80211_AUTHTYPE_NETWORK_EAP
;
351 wdev
->conn
->params
.auth_type
=
352 NL80211_AUTHTYPE_OPEN_SYSTEM
;
355 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
356 schedule_work(&rdev
->conn_work
);
357 } else if (status_code
!= WLAN_STATUS_SUCCESS
) {
358 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
359 status_code
, false, NULL
);
360 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
361 wdev
->conn
->state
== CFG80211_CONN_AUTHENTICATING
) {
362 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
363 schedule_work(&rdev
->conn_work
);
367 bool cfg80211_sme_failed_reassoc(struct wireless_dev
*wdev
)
369 struct wiphy
*wiphy
= wdev
->wiphy
;
370 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
372 if (WARN_ON(!wdev
->conn
))
375 if (!wdev
->conn
->prev_bssid_valid
)
379 * Some stupid APs don't accept reassoc, so we
380 * need to fall back to trying regular assoc.
382 wdev
->conn
->prev_bssid_valid
= false;
383 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
384 schedule_work(&rdev
->conn_work
);
389 void cfg80211_sme_failed_assoc(struct wireless_dev
*wdev
)
391 struct wiphy
*wiphy
= wdev
->wiphy
;
392 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
394 wdev
->conn
->state
= CFG80211_CONN_DEAUTH_ASSOC_FAIL
;
395 schedule_work(&rdev
->conn_work
);
398 void __cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
399 const u8
*req_ie
, size_t req_ie_len
,
400 const u8
*resp_ie
, size_t resp_ie_len
,
401 u16 status
, bool wextev
,
402 struct cfg80211_bss
*bss
)
404 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
406 #ifdef CONFIG_CFG80211_WEXT
407 union iwreq_data wrqu
;
410 ASSERT_WDEV_LOCK(wdev
);
412 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
415 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
418 nl80211_send_connect_result(wiphy_to_dev(wdev
->wiphy
), dev
,
419 bssid
, req_ie
, req_ie_len
,
420 resp_ie
, resp_ie_len
,
423 #ifdef CONFIG_CFG80211_WEXT
425 if (req_ie
&& status
== WLAN_STATUS_SUCCESS
) {
426 memset(&wrqu
, 0, sizeof(wrqu
));
427 wrqu
.data
.length
= req_ie_len
;
428 wireless_send_event(dev
, IWEVASSOCREQIE
, &wrqu
, req_ie
);
431 if (resp_ie
&& status
== WLAN_STATUS_SUCCESS
) {
432 memset(&wrqu
, 0, sizeof(wrqu
));
433 wrqu
.data
.length
= resp_ie_len
;
434 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
437 memset(&wrqu
, 0, sizeof(wrqu
));
438 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
439 if (bssid
&& status
== WLAN_STATUS_SUCCESS
) {
440 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
441 memcpy(wdev
->wext
.prev_bssid
, bssid
, ETH_ALEN
);
442 wdev
->wext
.prev_bssid_valid
= true;
444 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
448 if (wdev
->current_bss
) {
449 cfg80211_unhold_bss(wdev
->current_bss
);
450 cfg80211_put_bss(&wdev
->current_bss
->pub
);
451 wdev
->current_bss
= NULL
;
455 wdev
->conn
->state
= CFG80211_CONN_IDLE
;
457 if (status
!= WLAN_STATUS_SUCCESS
) {
458 wdev
->sme_state
= CFG80211_SME_IDLE
;
460 kfree(wdev
->conn
->ie
);
463 kfree(wdev
->connect_keys
);
464 wdev
->connect_keys
= NULL
;
470 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
471 wdev
->ssid
, wdev
->ssid_len
,
473 WLAN_CAPABILITY_ESS
);
478 cfg80211_hold_bss(bss_from_pub(bss
));
479 wdev
->current_bss
= bss_from_pub(bss
);
481 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
482 cfg80211_upload_connect_keys(wdev
);
484 country_ie
= (u8
*) ieee80211_bss_get_ie(bss
, WLAN_EID_COUNTRY
);
490 * ieee80211_bss_get_ie() ensures we can access:
491 * - country_ie + 2, the start of the country ie data, and
492 * - and country_ie[1] which is the IE length
494 regulatory_hint_11d(wdev
->wiphy
,
500 void cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
501 const u8
*req_ie
, size_t req_ie_len
,
502 const u8
*resp_ie
, size_t resp_ie_len
,
503 u16 status
, gfp_t gfp
)
505 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
506 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
507 struct cfg80211_event
*ev
;
510 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTING
);
512 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
516 ev
->type
= EVENT_CONNECT_RESULT
;
518 memcpy(ev
->cr
.bssid
, bssid
, ETH_ALEN
);
519 ev
->cr
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
520 ev
->cr
.req_ie_len
= req_ie_len
;
521 memcpy((void *)ev
->cr
.req_ie
, req_ie
, req_ie_len
);
522 ev
->cr
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
523 ev
->cr
.resp_ie_len
= resp_ie_len
;
524 memcpy((void *)ev
->cr
.resp_ie
, resp_ie
, resp_ie_len
);
525 ev
->cr
.status
= status
;
527 spin_lock_irqsave(&wdev
->event_lock
, flags
);
528 list_add_tail(&ev
->list
, &wdev
->event_list
);
529 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
530 queue_work(cfg80211_wq
, &rdev
->event_work
);
532 EXPORT_SYMBOL(cfg80211_connect_result
);
534 void __cfg80211_roamed(struct wireless_dev
*wdev
, const u8
*bssid
,
535 const u8
*req_ie
, size_t req_ie_len
,
536 const u8
*resp_ie
, size_t resp_ie_len
)
538 struct cfg80211_bss
*bss
;
539 #ifdef CONFIG_CFG80211_WEXT
540 union iwreq_data wrqu
;
543 ASSERT_WDEV_LOCK(wdev
);
545 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
548 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
551 /* internal error -- how did we get to CONNECTED w/o BSS? */
552 if (WARN_ON(!wdev
->current_bss
)) {
556 cfg80211_unhold_bss(wdev
->current_bss
);
557 cfg80211_put_bss(&wdev
->current_bss
->pub
);
558 wdev
->current_bss
= NULL
;
560 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
561 wdev
->ssid
, wdev
->ssid_len
,
562 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
567 cfg80211_hold_bss(bss_from_pub(bss
));
568 wdev
->current_bss
= bss_from_pub(bss
);
570 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), wdev
->netdev
, bssid
,
571 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
,
574 #ifdef CONFIG_CFG80211_WEXT
576 memset(&wrqu
, 0, sizeof(wrqu
));
577 wrqu
.data
.length
= req_ie_len
;
578 wireless_send_event(wdev
->netdev
, IWEVASSOCREQIE
,
583 memset(&wrqu
, 0, sizeof(wrqu
));
584 wrqu
.data
.length
= resp_ie_len
;
585 wireless_send_event(wdev
->netdev
, IWEVASSOCRESPIE
,
589 memset(&wrqu
, 0, sizeof(wrqu
));
590 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
591 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
592 memcpy(wdev
->wext
.prev_bssid
, bssid
, ETH_ALEN
);
593 wdev
->wext
.prev_bssid_valid
= true;
594 wireless_send_event(wdev
->netdev
, SIOCGIWAP
, &wrqu
, NULL
);
598 void cfg80211_roamed(struct net_device
*dev
, const u8
*bssid
,
599 const u8
*req_ie
, size_t req_ie_len
,
600 const u8
*resp_ie
, size_t resp_ie_len
, gfp_t gfp
)
602 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
603 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
604 struct cfg80211_event
*ev
;
607 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
);
609 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
613 ev
->type
= EVENT_ROAMED
;
614 memcpy(ev
->rm
.bssid
, bssid
, ETH_ALEN
);
615 ev
->rm
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
616 ev
->rm
.req_ie_len
= req_ie_len
;
617 memcpy((void *)ev
->rm
.req_ie
, req_ie
, req_ie_len
);
618 ev
->rm
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
619 ev
->rm
.resp_ie_len
= resp_ie_len
;
620 memcpy((void *)ev
->rm
.resp_ie
, resp_ie
, resp_ie_len
);
622 spin_lock_irqsave(&wdev
->event_lock
, flags
);
623 list_add_tail(&ev
->list
, &wdev
->event_list
);
624 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
625 queue_work(cfg80211_wq
, &rdev
->event_work
);
627 EXPORT_SYMBOL(cfg80211_roamed
);
629 void __cfg80211_disconnected(struct net_device
*dev
, const u8
*ie
,
630 size_t ie_len
, u16 reason
, bool from_ap
)
632 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
633 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
635 #ifdef CONFIG_CFG80211_WEXT
636 union iwreq_data wrqu
;
639 ASSERT_WDEV_LOCK(wdev
);
641 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
644 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
647 if (wdev
->current_bss
) {
648 cfg80211_unhold_bss(wdev
->current_bss
);
649 cfg80211_put_bss(&wdev
->current_bss
->pub
);
652 wdev
->current_bss
= NULL
;
653 wdev
->sme_state
= CFG80211_SME_IDLE
;
660 kfree(wdev
->conn
->ie
);
661 wdev
->conn
->ie
= NULL
;
666 * If this disconnect was due to a disassoc, we
667 * we might still have an auth BSS around. For
668 * the userspace SME that's currently expected,
669 * but for the kernel SME (nl80211 CONNECT or
670 * wireless extensions) we want to clear up all
673 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
674 if (!wdev
->auth_bsses
[i
])
676 bssid
= wdev
->auth_bsses
[i
]->pub
.bssid
;
677 ret
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, NULL
, 0,
678 WLAN_REASON_DEAUTH_LEAVING
);
679 WARN(ret
, "deauth failed: %d\n", ret
);
683 nl80211_send_disconnected(rdev
, dev
, reason
, ie
, ie_len
, from_ap
);
686 * Delete all the keys ... pairwise keys can't really
687 * exist any more anyway, but default keys might.
689 if (rdev
->ops
->del_key
)
690 for (i
= 0; i
< 6; i
++)
691 rdev
->ops
->del_key(wdev
->wiphy
, dev
, i
, NULL
);
693 #ifdef CONFIG_CFG80211_WEXT
694 memset(&wrqu
, 0, sizeof(wrqu
));
695 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
696 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
697 wdev
->wext
.connect
.ssid_len
= 0;
700 schedule_work(&cfg80211_disconnect_work
);
703 void cfg80211_disconnected(struct net_device
*dev
, u16 reason
,
704 u8
*ie
, size_t ie_len
, gfp_t gfp
)
706 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
707 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
708 struct cfg80211_event
*ev
;
711 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
);
713 ev
= kzalloc(sizeof(*ev
) + ie_len
, gfp
);
717 ev
->type
= EVENT_DISCONNECTED
;
718 ev
->dc
.ie
= ((u8
*)ev
) + sizeof(*ev
);
719 ev
->dc
.ie_len
= ie_len
;
720 memcpy((void *)ev
->dc
.ie
, ie
, ie_len
);
721 ev
->dc
.reason
= reason
;
723 spin_lock_irqsave(&wdev
->event_lock
, flags
);
724 list_add_tail(&ev
->list
, &wdev
->event_list
);
725 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
726 queue_work(cfg80211_wq
, &rdev
->event_work
);
728 EXPORT_SYMBOL(cfg80211_disconnected
);
730 int __cfg80211_connect(struct cfg80211_registered_device
*rdev
,
731 struct net_device
*dev
,
732 struct cfg80211_connect_params
*connect
,
733 struct cfg80211_cached_keys
*connkeys
,
734 const u8
*prev_bssid
)
736 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
737 struct ieee80211_channel
*chan
;
738 struct cfg80211_bss
*bss
= NULL
;
741 ASSERT_WDEV_LOCK(wdev
);
743 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
746 chan
= rdev_fixed_channel(rdev
, wdev
);
747 if (chan
&& chan
!= connect
->channel
)
750 if (WARN_ON(wdev
->connect_keys
)) {
751 kfree(wdev
->connect_keys
);
752 wdev
->connect_keys
= NULL
;
755 if (connkeys
&& connkeys
->def
>= 0) {
760 cipher
= connkeys
->params
[idx
].cipher
;
761 /* If given a WEP key we may need it for shared key auth */
762 if (cipher
== WLAN_CIPHER_SUITE_WEP40
||
763 cipher
== WLAN_CIPHER_SUITE_WEP104
) {
764 connect
->key_idx
= idx
;
765 connect
->key
= connkeys
->params
[idx
].key
;
766 connect
->key_len
= connkeys
->params
[idx
].key_len
;
769 * If ciphers are not set (e.g. when going through
770 * iwconfig), we have to set them appropriately here.
772 if (connect
->crypto
.cipher_group
== 0)
773 connect
->crypto
.cipher_group
= cipher
;
775 if (connect
->crypto
.n_ciphers_pairwise
== 0) {
776 connect
->crypto
.n_ciphers_pairwise
= 1;
777 connect
->crypto
.ciphers_pairwise
[0] = cipher
;
782 if (!rdev
->ops
->connect
) {
783 if (!rdev
->ops
->auth
|| !rdev
->ops
->assoc
)
786 if (WARN_ON(wdev
->conn
))
789 wdev
->conn
= kzalloc(sizeof(*wdev
->conn
), GFP_KERNEL
);
794 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
796 memcpy(&wdev
->conn
->params
, connect
, sizeof(*connect
));
797 if (connect
->bssid
) {
798 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
799 memcpy(wdev
->conn
->bssid
, connect
->bssid
, ETH_ALEN
);
803 wdev
->conn
->ie
= kmemdup(connect
->ie
, connect
->ie_len
,
805 wdev
->conn
->params
.ie
= wdev
->conn
->ie
;
806 if (!wdev
->conn
->ie
) {
813 if (connect
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) {
814 wdev
->conn
->auto_auth
= true;
815 /* start with open system ... should mostly work */
816 wdev
->conn
->params
.auth_type
=
817 NL80211_AUTHTYPE_OPEN_SYSTEM
;
819 wdev
->conn
->auto_auth
= false;
822 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
823 wdev
->ssid_len
= connect
->ssid_len
;
824 wdev
->conn
->params
.ssid
= wdev
->ssid
;
825 wdev
->conn
->params
.ssid_len
= connect
->ssid_len
;
827 /* see if we have the bss already */
828 bss
= cfg80211_get_conn_bss(wdev
);
830 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
831 wdev
->connect_keys
= connkeys
;
834 memcpy(wdev
->conn
->prev_bssid
, prev_bssid
, ETH_ALEN
);
835 wdev
->conn
->prev_bssid_valid
= true;
838 /* we're good if we have a matching bss struct */
840 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
841 err
= cfg80211_conn_do_work(wdev
);
842 cfg80211_put_bss(bss
);
844 /* otherwise we'll need to scan for the AP first */
845 err
= cfg80211_conn_scan(wdev
);
847 * If we can't scan right now, then we need to scan again
848 * after the current scan finished, since the parameters
849 * changed (unless we find a good AP anyway).
853 wdev
->conn
->state
= CFG80211_CONN_SCAN_AGAIN
;
857 kfree(wdev
->conn
->ie
);
860 wdev
->sme_state
= CFG80211_SME_IDLE
;
861 wdev
->connect_keys
= NULL
;
867 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
868 wdev
->connect_keys
= connkeys
;
869 err
= rdev
->ops
->connect(&rdev
->wiphy
, dev
, connect
);
871 wdev
->connect_keys
= NULL
;
872 wdev
->sme_state
= CFG80211_SME_IDLE
;
876 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
877 wdev
->ssid_len
= connect
->ssid_len
;
883 int cfg80211_connect(struct cfg80211_registered_device
*rdev
,
884 struct net_device
*dev
,
885 struct cfg80211_connect_params
*connect
,
886 struct cfg80211_cached_keys
*connkeys
)
890 mutex_lock(&rdev
->devlist_mtx
);
891 wdev_lock(dev
->ieee80211_ptr
);
892 err
= __cfg80211_connect(rdev
, dev
, connect
, connkeys
, NULL
);
893 wdev_unlock(dev
->ieee80211_ptr
);
894 mutex_unlock(&rdev
->devlist_mtx
);
899 int __cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
900 struct net_device
*dev
, u16 reason
, bool wextev
)
902 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
905 ASSERT_WDEV_LOCK(wdev
);
907 if (wdev
->sme_state
== CFG80211_SME_IDLE
)
910 kfree(wdev
->connect_keys
);
911 wdev
->connect_keys
= NULL
;
913 if (!rdev
->ops
->disconnect
) {
914 if (!rdev
->ops
->deauth
)
917 /* was it connected by userspace SME? */
919 cfg80211_mlme_down(rdev
, dev
);
923 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
924 (wdev
->conn
->state
== CFG80211_CONN_SCANNING
||
925 wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)) {
926 wdev
->sme_state
= CFG80211_SME_IDLE
;
927 kfree(wdev
->conn
->ie
);
934 /* wdev->conn->params.bssid must be set if > SCANNING */
935 err
= __cfg80211_mlme_deauth(rdev
, dev
,
936 wdev
->conn
->params
.bssid
,
941 err
= rdev
->ops
->disconnect(&rdev
->wiphy
, dev
, reason
);
946 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
947 __cfg80211_disconnected(dev
, NULL
, 0, 0, false);
948 else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
949 __cfg80211_connect_result(dev
, NULL
, NULL
, 0, NULL
, 0,
950 WLAN_STATUS_UNSPECIFIED_FAILURE
,
956 int cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
957 struct net_device
*dev
,
958 u16 reason
, bool wextev
)
962 wdev_lock(dev
->ieee80211_ptr
);
963 err
= __cfg80211_disconnect(rdev
, dev
, reason
, wextev
);
964 wdev_unlock(dev
->ieee80211_ptr
);
969 void cfg80211_sme_disassoc(struct net_device
*dev
, int idx
)
971 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
972 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
975 ASSERT_WDEV_LOCK(wdev
);
980 if (wdev
->conn
->state
== CFG80211_CONN_IDLE
)
984 * Ok, so the association was made by this SME -- we don't
985 * want it any more so deauthenticate too.
988 if (!wdev
->auth_bsses
[idx
])
991 memcpy(bssid
, wdev
->auth_bsses
[idx
]->pub
.bssid
, ETH_ALEN
);
992 if (__cfg80211_mlme_deauth(rdev
, dev
, bssid
,
993 NULL
, 0, WLAN_REASON_DEAUTH_LEAVING
)) {
994 /* whatever -- assume gone anyway */
995 cfg80211_unhold_bss(wdev
->auth_bsses
[idx
]);
996 cfg80211_put_bss(&wdev
->auth_bsses
[idx
]->pub
);
997 wdev
->auth_bsses
[idx
] = NULL
;