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
,
37 static int cfg80211_conn_scan(struct wireless_dev
*wdev
)
39 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
40 struct cfg80211_scan_request
*request
;
44 ASSERT_RDEV_LOCK(rdev
);
45 ASSERT_WDEV_LOCK(wdev
);
50 if (wdev
->conn
->params
.channel
) {
53 enum ieee80211_band band
;
56 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
57 if (!wdev
->wiphy
->bands
[band
])
59 n_channels
+= wdev
->wiphy
->bands
[band
]->n_channels
;
62 request
= kzalloc(sizeof(*request
) + sizeof(request
->ssids
[0]) +
63 sizeof(request
->channels
[0]) * n_channels
,
68 request
->channels
= (void *)((char *)request
+ sizeof(*request
));
69 if (wdev
->conn
->params
.channel
)
70 request
->channels
[0] = wdev
->conn
->params
.channel
;
73 enum ieee80211_band band
;
75 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
76 if (!wdev
->wiphy
->bands
[band
])
78 for (j
= 0; j
< wdev
->wiphy
->bands
[band
]->n_channels
;
80 request
->channels
[i
] =
81 &wdev
->wiphy
->bands
[band
]->channels
[j
];
84 request
->n_channels
= n_channels
;
85 request
->ssids
= (void *)(request
->channels
+ n_channels
);
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
;
92 request
->dev
= wdev
->netdev
;
93 request
->wiphy
= &rdev
->wiphy
;
95 rdev
->scan_req
= request
;
97 err
= rdev
->ops
->scan(wdev
->wiphy
, wdev
->netdev
, request
);
99 wdev
->conn
->state
= CFG80211_CONN_SCANNING
;
100 nl80211_send_scan_start(rdev
, wdev
->netdev
);
101 dev_hold(wdev
->netdev
);
103 rdev
->scan_req
= NULL
;
109 static int cfg80211_conn_do_work(struct wireless_dev
*wdev
)
111 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
112 struct cfg80211_connect_params
*params
;
115 ASSERT_WDEV_LOCK(wdev
);
120 params
= &wdev
->conn
->params
;
122 switch (wdev
->conn
->state
) {
123 case CFG80211_CONN_SCAN_AGAIN
:
124 return cfg80211_conn_scan(wdev
);
125 case CFG80211_CONN_AUTHENTICATE_NEXT
:
126 BUG_ON(!rdev
->ops
->auth
);
127 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATING
;
128 return __cfg80211_mlme_auth(rdev
, wdev
->netdev
,
129 params
->channel
, params
->auth_type
,
131 params
->ssid
, params
->ssid_len
,
133 params
->key
, params
->key_len
,
135 case CFG80211_CONN_ASSOCIATE_NEXT
:
136 BUG_ON(!rdev
->ops
->assoc
);
137 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATING
;
139 * We could, later, implement roaming here and then actually
140 * set prev_bssid to non-NULL. But then we need to be aware
141 * that some APs don't like that -- so we'd need to retry
144 err
= __cfg80211_mlme_assoc(rdev
, wdev
->netdev
,
145 params
->channel
, params
->bssid
,
147 params
->ssid
, params
->ssid_len
,
148 params
->ie
, params
->ie_len
,
149 false, ¶ms
->crypto
);
151 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
153 WLAN_REASON_DEAUTH_LEAVING
);
160 void cfg80211_conn_work(struct work_struct
*work
)
162 struct cfg80211_registered_device
*rdev
=
163 container_of(work
, struct cfg80211_registered_device
, conn_work
);
164 struct wireless_dev
*wdev
;
167 cfg80211_lock_rdev(rdev
);
168 mutex_lock(&rdev
->devlist_mtx
);
170 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
172 if (!netif_running(wdev
->netdev
)) {
176 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
) {
180 if (cfg80211_conn_do_work(wdev
))
181 __cfg80211_connect_result(
183 wdev
->conn
->params
.bssid
,
185 WLAN_STATUS_UNSPECIFIED_FAILURE
,
190 mutex_unlock(&rdev
->devlist_mtx
);
191 cfg80211_unlock_rdev(rdev
);
195 static bool cfg80211_get_conn_bss(struct wireless_dev
*wdev
)
197 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
198 struct cfg80211_bss
*bss
;
199 u16 capa
= WLAN_CAPABILITY_ESS
;
201 ASSERT_WDEV_LOCK(wdev
);
203 if (wdev
->conn
->params
.privacy
)
204 capa
|= WLAN_CAPABILITY_PRIVACY
;
206 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, wdev
->conn
->params
.bssid
,
207 wdev
->conn
->params
.ssid
,
208 wdev
->conn
->params
.ssid_len
,
209 WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_PRIVACY
,
214 memcpy(wdev
->conn
->bssid
, bss
->bssid
, ETH_ALEN
);
215 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
216 wdev
->conn
->params
.channel
= bss
->channel
;
217 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
218 schedule_work(&rdev
->conn_work
);
220 cfg80211_put_bss(bss
);
224 static void __cfg80211_sme_scan_done(struct net_device
*dev
)
226 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
227 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
229 ASSERT_WDEV_LOCK(wdev
);
231 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
237 if (wdev
->conn
->state
!= CFG80211_CONN_SCANNING
&&
238 wdev
->conn
->state
!= CFG80211_CONN_SCAN_AGAIN
)
241 if (!cfg80211_get_conn_bss(wdev
)) {
243 if (wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)
244 schedule_work(&rdev
->conn_work
);
246 __cfg80211_connect_result(
248 wdev
->conn
->params
.bssid
,
250 WLAN_STATUS_UNSPECIFIED_FAILURE
,
255 void cfg80211_sme_scan_done(struct net_device
*dev
)
257 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
259 mutex_lock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
261 __cfg80211_sme_scan_done(dev
);
263 mutex_unlock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
266 void cfg80211_sme_rx_auth(struct net_device
*dev
,
267 const u8
*buf
, size_t len
)
269 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
270 struct wiphy
*wiphy
= wdev
->wiphy
;
271 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
272 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
273 u16 status_code
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
275 ASSERT_WDEV_LOCK(wdev
);
277 /* should only RX auth frames when connecting */
278 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
281 if (WARN_ON(!wdev
->conn
))
284 if (status_code
== WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
&&
285 wdev
->conn
->auto_auth
&&
286 wdev
->conn
->params
.auth_type
!= NL80211_AUTHTYPE_NETWORK_EAP
) {
287 /* select automatically between only open, shared, leap */
288 switch (wdev
->conn
->params
.auth_type
) {
289 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
290 if (wdev
->connect_keys
)
291 wdev
->conn
->params
.auth_type
=
292 NL80211_AUTHTYPE_SHARED_KEY
;
294 wdev
->conn
->params
.auth_type
=
295 NL80211_AUTHTYPE_NETWORK_EAP
;
297 case NL80211_AUTHTYPE_SHARED_KEY
:
298 wdev
->conn
->params
.auth_type
=
299 NL80211_AUTHTYPE_NETWORK_EAP
;
303 wdev
->conn
->params
.auth_type
=
304 NL80211_AUTHTYPE_OPEN_SYSTEM
;
307 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
308 schedule_work(&rdev
->conn_work
);
309 } else if (status_code
!= WLAN_STATUS_SUCCESS
) {
310 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
311 status_code
, false, NULL
);
312 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
313 wdev
->conn
->state
== CFG80211_CONN_AUTHENTICATING
) {
314 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
315 schedule_work(&rdev
->conn_work
);
319 void __cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
320 const u8
*req_ie
, size_t req_ie_len
,
321 const u8
*resp_ie
, size_t resp_ie_len
,
322 u16 status
, bool wextev
,
323 struct cfg80211_bss
*bss
)
325 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
327 #ifdef CONFIG_WIRELESS_EXT
328 union iwreq_data wrqu
;
331 ASSERT_WDEV_LOCK(wdev
);
333 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
336 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
337 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), dev
,
338 bssid
, req_ie
, req_ie_len
,
339 resp_ie
, resp_ie_len
, GFP_KERNEL
);
341 nl80211_send_connect_result(wiphy_to_dev(wdev
->wiphy
), dev
,
342 bssid
, req_ie
, req_ie_len
,
343 resp_ie
, resp_ie_len
,
346 #ifdef CONFIG_WIRELESS_EXT
348 if (req_ie
&& status
== WLAN_STATUS_SUCCESS
) {
349 memset(&wrqu
, 0, sizeof(wrqu
));
350 wrqu
.data
.length
= req_ie_len
;
351 wireless_send_event(dev
, IWEVASSOCREQIE
, &wrqu
, req_ie
);
354 if (resp_ie
&& status
== WLAN_STATUS_SUCCESS
) {
355 memset(&wrqu
, 0, sizeof(wrqu
));
356 wrqu
.data
.length
= resp_ie_len
;
357 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
360 memset(&wrqu
, 0, sizeof(wrqu
));
361 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
362 if (bssid
&& status
== WLAN_STATUS_SUCCESS
)
363 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
364 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
368 if (wdev
->current_bss
) {
369 cfg80211_unhold_bss(wdev
->current_bss
);
370 cfg80211_put_bss(&wdev
->current_bss
->pub
);
371 wdev
->current_bss
= NULL
;
374 if (status
== WLAN_STATUS_SUCCESS
&&
375 wdev
->sme_state
== CFG80211_SME_IDLE
)
378 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
382 wdev
->conn
->state
= CFG80211_CONN_IDLE
;
384 if (status
!= WLAN_STATUS_SUCCESS
) {
385 wdev
->sme_state
= CFG80211_SME_IDLE
;
388 kfree(wdev
->connect_keys
);
389 wdev
->connect_keys
= NULL
;
396 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
397 wdev
->ssid
, wdev
->ssid_len
,
399 WLAN_CAPABILITY_ESS
);
404 cfg80211_hold_bss(bss_from_pub(bss
));
405 wdev
->current_bss
= bss_from_pub(bss
);
407 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
408 cfg80211_upload_connect_keys(wdev
);
410 country_ie
= (u8
*) ieee80211_bss_get_ie(bss
, WLAN_EID_COUNTRY
);
416 * ieee80211_bss_get_ie() ensures we can access:
417 * - country_ie + 2, the start of the country ie data, and
418 * - and country_ie[1] which is the IE length
420 regulatory_hint_11d(wdev
->wiphy
,
425 void cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
426 const u8
*req_ie
, size_t req_ie_len
,
427 const u8
*resp_ie
, size_t resp_ie_len
,
428 u16 status
, gfp_t gfp
)
430 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
431 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
432 struct cfg80211_event
*ev
;
435 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
439 ev
->type
= EVENT_CONNECT_RESULT
;
440 memcpy(ev
->cr
.bssid
, bssid
, ETH_ALEN
);
441 ev
->cr
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
442 ev
->cr
.req_ie_len
= req_ie_len
;
443 memcpy((void *)ev
->cr
.req_ie
, req_ie
, req_ie_len
);
444 ev
->cr
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
445 ev
->cr
.resp_ie_len
= resp_ie_len
;
446 memcpy((void *)ev
->cr
.resp_ie
, resp_ie
, resp_ie_len
);
447 ev
->cr
.status
= status
;
449 spin_lock_irqsave(&wdev
->event_lock
, flags
);
450 list_add_tail(&ev
->list
, &wdev
->event_list
);
451 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
452 schedule_work(&rdev
->event_work
);
454 EXPORT_SYMBOL(cfg80211_connect_result
);
456 void __cfg80211_roamed(struct wireless_dev
*wdev
, const u8
*bssid
,
457 const u8
*req_ie
, size_t req_ie_len
,
458 const u8
*resp_ie
, size_t resp_ie_len
)
460 struct cfg80211_bss
*bss
;
461 #ifdef CONFIG_WIRELESS_EXT
462 union iwreq_data wrqu
;
465 ASSERT_WDEV_LOCK(wdev
);
467 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
470 if (WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
))
473 /* internal error -- how did we get to CONNECTED w/o BSS? */
474 if (WARN_ON(!wdev
->current_bss
)) {
478 cfg80211_unhold_bss(wdev
->current_bss
);
479 cfg80211_put_bss(&wdev
->current_bss
->pub
);
480 wdev
->current_bss
= NULL
;
482 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
483 wdev
->ssid
, wdev
->ssid_len
,
484 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
489 cfg80211_hold_bss(bss_from_pub(bss
));
490 wdev
->current_bss
= bss_from_pub(bss
);
492 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), wdev
->netdev
, bssid
,
493 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
,
496 #ifdef CONFIG_WIRELESS_EXT
498 memset(&wrqu
, 0, sizeof(wrqu
));
499 wrqu
.data
.length
= req_ie_len
;
500 wireless_send_event(wdev
->netdev
, IWEVASSOCREQIE
,
505 memset(&wrqu
, 0, sizeof(wrqu
));
506 wrqu
.data
.length
= resp_ie_len
;
507 wireless_send_event(wdev
->netdev
, IWEVASSOCRESPIE
,
511 memset(&wrqu
, 0, sizeof(wrqu
));
512 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
513 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
514 wireless_send_event(wdev
->netdev
, SIOCGIWAP
, &wrqu
, NULL
);
518 void cfg80211_roamed(struct net_device
*dev
, const u8
*bssid
,
519 const u8
*req_ie
, size_t req_ie_len
,
520 const u8
*resp_ie
, size_t resp_ie_len
, gfp_t gfp
)
522 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
523 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
524 struct cfg80211_event
*ev
;
527 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
531 ev
->type
= EVENT_ROAMED
;
532 memcpy(ev
->rm
.bssid
, bssid
, ETH_ALEN
);
533 ev
->rm
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
534 ev
->rm
.req_ie_len
= req_ie_len
;
535 memcpy((void *)ev
->rm
.req_ie
, req_ie
, req_ie_len
);
536 ev
->rm
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
537 ev
->rm
.resp_ie_len
= resp_ie_len
;
538 memcpy((void *)ev
->rm
.resp_ie
, resp_ie
, resp_ie_len
);
540 spin_lock_irqsave(&wdev
->event_lock
, flags
);
541 list_add_tail(&ev
->list
, &wdev
->event_list
);
542 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
543 schedule_work(&rdev
->event_work
);
545 EXPORT_SYMBOL(cfg80211_roamed
);
547 void __cfg80211_disconnected(struct net_device
*dev
, const u8
*ie
,
548 size_t ie_len
, u16 reason
, bool from_ap
)
550 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
551 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
553 #ifdef CONFIG_WIRELESS_EXT
554 union iwreq_data wrqu
;
557 ASSERT_WDEV_LOCK(wdev
);
559 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
562 if (WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
))
565 if (wdev
->current_bss
) {
566 cfg80211_unhold_bss(wdev
->current_bss
);
567 cfg80211_put_bss(&wdev
->current_bss
->pub
);
570 wdev
->current_bss
= NULL
;
571 wdev
->sme_state
= CFG80211_SME_IDLE
;
578 kfree(wdev
->conn
->ie
);
579 wdev
->conn
->ie
= NULL
;
584 * If this disconnect was due to a disassoc, we
585 * we might still have an auth BSS around. For
586 * the userspace SME that's currently expected,
587 * but for the kernel SME (nl80211 CONNECT or
588 * wireless extensions) we want to clear up all
591 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
592 if (!wdev
->auth_bsses
[i
])
594 bssid
= wdev
->auth_bsses
[i
]->pub
.bssid
;
595 ret
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, NULL
, 0,
596 WLAN_REASON_DEAUTH_LEAVING
);
597 WARN(ret
, "deauth failed: %d\n", ret
);
601 nl80211_send_disconnected(rdev
, dev
, reason
, ie
, ie_len
, from_ap
);
604 * Delete all the keys ... pairwise keys can't really
605 * exist any more anyway, but default keys might.
607 if (rdev
->ops
->del_key
)
608 for (i
= 0; i
< 6; i
++)
609 rdev
->ops
->del_key(wdev
->wiphy
, dev
, i
, NULL
);
611 #ifdef CONFIG_WIRELESS_EXT
612 memset(&wrqu
, 0, sizeof(wrqu
));
613 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
614 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
618 void cfg80211_disconnected(struct net_device
*dev
, u16 reason
,
619 u8
*ie
, size_t ie_len
, gfp_t gfp
)
621 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
622 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
623 struct cfg80211_event
*ev
;
626 ev
= kzalloc(sizeof(*ev
) + ie_len
, gfp
);
630 ev
->type
= EVENT_DISCONNECTED
;
631 ev
->dc
.ie
= ((u8
*)ev
) + sizeof(*ev
);
632 ev
->dc
.ie_len
= ie_len
;
633 memcpy((void *)ev
->dc
.ie
, ie
, ie_len
);
634 ev
->dc
.reason
= reason
;
636 spin_lock_irqsave(&wdev
->event_lock
, flags
);
637 list_add_tail(&ev
->list
, &wdev
->event_list
);
638 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
639 schedule_work(&rdev
->event_work
);
641 EXPORT_SYMBOL(cfg80211_disconnected
);
643 int __cfg80211_connect(struct cfg80211_registered_device
*rdev
,
644 struct net_device
*dev
,
645 struct cfg80211_connect_params
*connect
,
646 struct cfg80211_cached_keys
*connkeys
)
648 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
649 struct ieee80211_channel
*chan
;
652 ASSERT_WDEV_LOCK(wdev
);
654 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
657 chan
= rdev_fixed_channel(rdev
, wdev
);
658 if (chan
&& chan
!= connect
->channel
)
661 if (WARN_ON(wdev
->connect_keys
)) {
662 kfree(wdev
->connect_keys
);
663 wdev
->connect_keys
= NULL
;
666 if (connkeys
&& connkeys
->def
>= 0) {
671 cipher
= connkeys
->params
[idx
].cipher
;
672 /* If given a WEP key we may need it for shared key auth */
673 if (cipher
== WLAN_CIPHER_SUITE_WEP40
||
674 cipher
== WLAN_CIPHER_SUITE_WEP104
) {
675 connect
->key_idx
= idx
;
676 connect
->key
= connkeys
->params
[idx
].key
;
677 connect
->key_len
= connkeys
->params
[idx
].key_len
;
680 * If ciphers are not set (e.g. when going through
681 * iwconfig), we have to set them appropriately here.
683 if (connect
->crypto
.cipher_group
== 0)
684 connect
->crypto
.cipher_group
= cipher
;
686 if (connect
->crypto
.n_ciphers_pairwise
== 0) {
687 connect
->crypto
.n_ciphers_pairwise
= 1;
688 connect
->crypto
.ciphers_pairwise
[0] = cipher
;
693 if (!rdev
->ops
->connect
) {
694 if (!rdev
->ops
->auth
|| !rdev
->ops
->assoc
)
697 if (WARN_ON(wdev
->conn
))
700 wdev
->conn
= kzalloc(sizeof(*wdev
->conn
), GFP_KERNEL
);
705 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
707 memcpy(&wdev
->conn
->params
, connect
, sizeof(*connect
));
708 if (connect
->bssid
) {
709 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
710 memcpy(wdev
->conn
->bssid
, connect
->bssid
, ETH_ALEN
);
714 wdev
->conn
->ie
= kmemdup(connect
->ie
, connect
->ie_len
,
716 wdev
->conn
->params
.ie
= wdev
->conn
->ie
;
717 if (!wdev
->conn
->ie
) {
724 if (connect
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) {
725 wdev
->conn
->auto_auth
= true;
726 /* start with open system ... should mostly work */
727 wdev
->conn
->params
.auth_type
=
728 NL80211_AUTHTYPE_OPEN_SYSTEM
;
730 wdev
->conn
->auto_auth
= false;
733 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
734 wdev
->ssid_len
= connect
->ssid_len
;
735 wdev
->conn
->params
.ssid
= wdev
->ssid
;
736 wdev
->conn
->params
.ssid_len
= connect
->ssid_len
;
738 /* don't care about result -- but fill bssid & channel */
739 if (!wdev
->conn
->params
.bssid
|| !wdev
->conn
->params
.channel
)
740 cfg80211_get_conn_bss(wdev
);
742 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
743 wdev
->connect_keys
= connkeys
;
745 /* we're good if we have both BSSID and channel */
746 if (wdev
->conn
->params
.bssid
&& wdev
->conn
->params
.channel
) {
747 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
748 err
= cfg80211_conn_do_work(wdev
);
750 /* otherwise we'll need to scan for the AP first */
751 err
= cfg80211_conn_scan(wdev
);
753 * If we can't scan right now, then we need to scan again
754 * after the current scan finished, since the parameters
755 * changed (unless we find a good AP anyway).
759 wdev
->conn
->state
= CFG80211_CONN_SCAN_AGAIN
;
765 wdev
->sme_state
= CFG80211_SME_IDLE
;
766 wdev
->connect_keys
= NULL
;
772 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
773 wdev
->connect_keys
= connkeys
;
774 err
= rdev
->ops
->connect(&rdev
->wiphy
, dev
, connect
);
776 wdev
->connect_keys
= NULL
;
777 wdev
->sme_state
= CFG80211_SME_IDLE
;
781 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
782 wdev
->ssid_len
= connect
->ssid_len
;
788 int cfg80211_connect(struct cfg80211_registered_device
*rdev
,
789 struct net_device
*dev
,
790 struct cfg80211_connect_params
*connect
,
791 struct cfg80211_cached_keys
*connkeys
)
795 mutex_lock(&rdev
->devlist_mtx
);
796 wdev_lock(dev
->ieee80211_ptr
);
797 err
= __cfg80211_connect(rdev
, dev
, connect
, connkeys
);
798 wdev_unlock(dev
->ieee80211_ptr
);
799 mutex_unlock(&rdev
->devlist_mtx
);
804 int __cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
805 struct net_device
*dev
, u16 reason
, bool wextev
)
807 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
810 ASSERT_WDEV_LOCK(wdev
);
812 if (wdev
->sme_state
== CFG80211_SME_IDLE
)
815 kfree(wdev
->connect_keys
);
816 wdev
->connect_keys
= NULL
;
818 if (!rdev
->ops
->disconnect
) {
819 if (!rdev
->ops
->deauth
)
822 /* was it connected by userspace SME? */
824 cfg80211_mlme_down(rdev
, dev
);
828 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
829 (wdev
->conn
->state
== CFG80211_CONN_SCANNING
||
830 wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)) {
831 wdev
->sme_state
= CFG80211_SME_IDLE
;
838 /* wdev->conn->params.bssid must be set if > SCANNING */
839 err
= __cfg80211_mlme_deauth(rdev
, dev
,
840 wdev
->conn
->params
.bssid
,
845 err
= rdev
->ops
->disconnect(&rdev
->wiphy
, dev
, reason
);
850 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
851 __cfg80211_disconnected(dev
, NULL
, 0, 0, false);
852 else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
853 __cfg80211_connect_result(dev
, NULL
, NULL
, 0, NULL
, 0,
854 WLAN_STATUS_UNSPECIFIED_FAILURE
,
860 int cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
861 struct net_device
*dev
,
862 u16 reason
, bool wextev
)
866 wdev_lock(dev
->ieee80211_ptr
);
867 err
= __cfg80211_disconnect(rdev
, dev
, reason
, wextev
);
868 wdev_unlock(dev
->ieee80211_ptr
);
873 void cfg80211_sme_disassoc(struct net_device
*dev
, int idx
)
875 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
876 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
879 ASSERT_WDEV_LOCK(wdev
);
884 if (wdev
->conn
->state
== CFG80211_CONN_IDLE
)
888 * Ok, so the association was made by this SME -- we don't
889 * want it any more so deauthenticate too.
892 if (!wdev
->auth_bsses
[idx
])
895 memcpy(bssid
, wdev
->auth_bsses
[idx
]->pub
.bssid
, ETH_ALEN
);
896 if (__cfg80211_mlme_deauth(rdev
, dev
, bssid
,
897 NULL
, 0, WLAN_REASON_DEAUTH_LEAVING
)) {
898 /* whatever -- assume gone anyway */
899 cfg80211_unhold_bss(wdev
->auth_bsses
[idx
]);
900 cfg80211_put_bss(&wdev
->auth_bsses
[idx
]->pub
);
901 wdev
->auth_bsses
[idx
] = NULL
;