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 <net/cfg80211.h>
12 #include <net/rtnetlink.h>
15 struct cfg80211_conn
{
16 struct cfg80211_connect_params params
;
17 /* these are sub-states of the _CONNECTING sme_state */
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
,
34 static int cfg80211_conn_scan(struct wireless_dev
*wdev
)
36 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
37 struct cfg80211_scan_request
*request
;
41 ASSERT_RDEV_LOCK(rdev
);
42 ASSERT_WDEV_LOCK(wdev
);
47 if (wdev
->conn
->params
.channel
) {
50 enum ieee80211_band band
;
53 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
54 if (!wdev
->wiphy
->bands
[band
])
56 n_channels
+= wdev
->wiphy
->bands
[band
]->n_channels
;
59 request
= kzalloc(sizeof(*request
) + sizeof(request
->ssids
[0]) +
60 sizeof(request
->channels
[0]) * n_channels
,
65 request
->channels
= (void *)((char *)request
+ sizeof(*request
));
66 if (wdev
->conn
->params
.channel
)
67 request
->channels
[0] = wdev
->conn
->params
.channel
;
70 enum ieee80211_band band
;
72 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
73 if (!wdev
->wiphy
->bands
[band
])
75 for (j
= 0; j
< wdev
->wiphy
->bands
[band
]->n_channels
;
77 request
->channels
[i
] =
78 &wdev
->wiphy
->bands
[band
]->channels
[j
];
81 request
->n_channels
= n_channels
;
82 request
->ssids
= (void *)(request
->channels
+ n_channels
);
85 memcpy(request
->ssids
[0].ssid
, wdev
->conn
->params
.ssid
,
86 wdev
->conn
->params
.ssid_len
);
87 request
->ssids
[0].ssid_len
= wdev
->conn
->params
.ssid_len
;
89 request
->dev
= wdev
->netdev
;
90 request
->wiphy
= &rdev
->wiphy
;
92 rdev
->scan_req
= request
;
94 err
= rdev
->ops
->scan(wdev
->wiphy
, wdev
->netdev
, request
);
96 wdev
->conn
->state
= CFG80211_CONN_SCANNING
;
97 nl80211_send_scan_start(rdev
, wdev
->netdev
);
98 dev_hold(wdev
->netdev
);
100 rdev
->scan_req
= NULL
;
106 static int cfg80211_conn_do_work(struct wireless_dev
*wdev
)
108 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
109 struct cfg80211_connect_params
*params
;
112 ASSERT_WDEV_LOCK(wdev
);
117 params
= &wdev
->conn
->params
;
119 switch (wdev
->conn
->state
) {
120 case CFG80211_CONN_SCAN_AGAIN
:
121 return cfg80211_conn_scan(wdev
);
122 case CFG80211_CONN_AUTHENTICATE_NEXT
:
123 BUG_ON(!rdev
->ops
->auth
);
124 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATING
;
125 return __cfg80211_mlme_auth(rdev
, wdev
->netdev
,
126 params
->channel
, params
->auth_type
,
128 params
->ssid
, params
->ssid_len
,
130 params
->key
, params
->key_len
,
132 case CFG80211_CONN_ASSOCIATE_NEXT
:
133 BUG_ON(!rdev
->ops
->assoc
);
134 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATING
;
136 * We could, later, implement roaming here and then actually
137 * set prev_bssid to non-NULL. But then we need to be aware
138 * that some APs don't like that -- so we'd need to retry
141 err
= __cfg80211_mlme_assoc(rdev
, wdev
->netdev
,
142 params
->channel
, params
->bssid
,
144 params
->ssid
, params
->ssid_len
,
145 params
->ie
, params
->ie_len
,
146 false, ¶ms
->crypto
);
148 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
150 WLAN_REASON_DEAUTH_LEAVING
);
157 void cfg80211_conn_work(struct work_struct
*work
)
159 struct cfg80211_registered_device
*rdev
=
160 container_of(work
, struct cfg80211_registered_device
, conn_work
);
161 struct wireless_dev
*wdev
;
164 cfg80211_lock_rdev(rdev
);
165 mutex_lock(&rdev
->devlist_mtx
);
167 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
169 if (!netif_running(wdev
->netdev
)) {
173 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
) {
177 if (cfg80211_conn_do_work(wdev
))
178 __cfg80211_connect_result(
180 wdev
->conn
->params
.bssid
,
182 WLAN_STATUS_UNSPECIFIED_FAILURE
,
187 mutex_unlock(&rdev
->devlist_mtx
);
188 cfg80211_unlock_rdev(rdev
);
192 static bool cfg80211_get_conn_bss(struct wireless_dev
*wdev
)
194 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
195 struct cfg80211_bss
*bss
;
196 u16 capa
= WLAN_CAPABILITY_ESS
;
198 ASSERT_WDEV_LOCK(wdev
);
200 if (wdev
->conn
->params
.privacy
)
201 capa
|= WLAN_CAPABILITY_PRIVACY
;
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
,
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
);
217 cfg80211_put_bss(bss
);
221 static void __cfg80211_sme_scan_done(struct net_device
*dev
)
223 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
224 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
226 ASSERT_WDEV_LOCK(wdev
);
228 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
234 if (wdev
->conn
->state
!= CFG80211_CONN_SCANNING
&&
235 wdev
->conn
->state
!= CFG80211_CONN_SCAN_AGAIN
)
238 if (!cfg80211_get_conn_bss(wdev
)) {
240 if (wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)
241 schedule_work(&rdev
->conn_work
);
243 __cfg80211_connect_result(
245 wdev
->conn
->params
.bssid
,
247 WLAN_STATUS_UNSPECIFIED_FAILURE
,
252 void cfg80211_sme_scan_done(struct net_device
*dev
)
254 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
257 __cfg80211_sme_scan_done(dev
);
261 void cfg80211_sme_rx_auth(struct net_device
*dev
,
262 const u8
*buf
, size_t len
)
264 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
265 struct wiphy
*wiphy
= wdev
->wiphy
;
266 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
267 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
268 u16 status_code
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
270 ASSERT_WDEV_LOCK(wdev
);
272 /* should only RX auth frames when connecting */
273 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
276 if (WARN_ON(!wdev
->conn
))
279 if (status_code
== WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
&&
280 wdev
->conn
->auto_auth
&&
281 wdev
->conn
->params
.auth_type
!= NL80211_AUTHTYPE_NETWORK_EAP
) {
282 /* select automatically between only open, shared, leap */
283 switch (wdev
->conn
->params
.auth_type
) {
284 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
285 if (wdev
->connect_keys
)
286 wdev
->conn
->params
.auth_type
=
287 NL80211_AUTHTYPE_SHARED_KEY
;
289 wdev
->conn
->params
.auth_type
=
290 NL80211_AUTHTYPE_NETWORK_EAP
;
292 case NL80211_AUTHTYPE_SHARED_KEY
:
293 wdev
->conn
->params
.auth_type
=
294 NL80211_AUTHTYPE_NETWORK_EAP
;
298 wdev
->conn
->params
.auth_type
=
299 NL80211_AUTHTYPE_OPEN_SYSTEM
;
302 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
303 schedule_work(&rdev
->conn_work
);
304 } else if (status_code
!= WLAN_STATUS_SUCCESS
) {
305 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
307 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
308 wdev
->conn
->state
== CFG80211_CONN_AUTHENTICATING
) {
309 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
310 schedule_work(&rdev
->conn_work
);
314 void __cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
315 const u8
*req_ie
, size_t req_ie_len
,
316 const u8
*resp_ie
, size_t resp_ie_len
,
317 u16 status
, bool wextev
)
319 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
320 struct cfg80211_bss
*bss
;
321 #ifdef CONFIG_WIRELESS_EXT
322 union iwreq_data wrqu
;
325 ASSERT_WDEV_LOCK(wdev
);
327 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
330 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
331 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), dev
,
332 bssid
, req_ie
, req_ie_len
,
333 resp_ie
, resp_ie_len
, GFP_KERNEL
);
335 nl80211_send_connect_result(wiphy_to_dev(wdev
->wiphy
), dev
,
336 bssid
, req_ie
, req_ie_len
,
337 resp_ie
, resp_ie_len
,
340 #ifdef CONFIG_WIRELESS_EXT
342 if (req_ie
&& status
== WLAN_STATUS_SUCCESS
) {
343 memset(&wrqu
, 0, sizeof(wrqu
));
344 wrqu
.data
.length
= req_ie_len
;
345 wireless_send_event(dev
, IWEVASSOCREQIE
, &wrqu
, req_ie
);
348 if (resp_ie
&& status
== WLAN_STATUS_SUCCESS
) {
349 memset(&wrqu
, 0, sizeof(wrqu
));
350 wrqu
.data
.length
= resp_ie_len
;
351 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
354 memset(&wrqu
, 0, sizeof(wrqu
));
355 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
356 if (bssid
&& status
== WLAN_STATUS_SUCCESS
)
357 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
358 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
362 if (status
== WLAN_STATUS_SUCCESS
&&
363 wdev
->sme_state
== CFG80211_SME_IDLE
)
366 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
369 if (wdev
->current_bss
) {
370 cfg80211_unhold_bss(wdev
->current_bss
);
371 cfg80211_put_bss(&wdev
->current_bss
->pub
);
372 wdev
->current_bss
= NULL
;
376 wdev
->conn
->state
= CFG80211_CONN_IDLE
;
378 if (status
!= WLAN_STATUS_SUCCESS
) {
379 wdev
->sme_state
= CFG80211_SME_IDLE
;
382 kfree(wdev
->connect_keys
);
383 wdev
->connect_keys
= NULL
;
387 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
388 wdev
->ssid
, wdev
->ssid_len
,
390 WLAN_CAPABILITY_ESS
);
395 cfg80211_hold_bss(bss_from_pub(bss
));
396 wdev
->current_bss
= bss_from_pub(bss
);
399 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
400 cfg80211_upload_connect_keys(wdev
);
403 void cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
404 const u8
*req_ie
, size_t req_ie_len
,
405 const u8
*resp_ie
, size_t resp_ie_len
,
406 u16 status
, gfp_t gfp
)
408 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
409 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
410 struct cfg80211_event
*ev
;
413 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
417 ev
->type
= EVENT_CONNECT_RESULT
;
418 memcpy(ev
->cr
.bssid
, bssid
, ETH_ALEN
);
419 ev
->cr
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
420 ev
->cr
.req_ie_len
= req_ie_len
;
421 memcpy((void *)ev
->cr
.req_ie
, req_ie
, req_ie_len
);
422 ev
->cr
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
423 ev
->cr
.resp_ie_len
= resp_ie_len
;
424 memcpy((void *)ev
->cr
.resp_ie
, resp_ie
, resp_ie_len
);
425 ev
->cr
.status
= status
;
427 spin_lock_irqsave(&wdev
->event_lock
, flags
);
428 list_add_tail(&ev
->list
, &wdev
->event_list
);
429 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
430 schedule_work(&rdev
->event_work
);
432 EXPORT_SYMBOL(cfg80211_connect_result
);
434 void __cfg80211_roamed(struct wireless_dev
*wdev
, const u8
*bssid
,
435 const u8
*req_ie
, size_t req_ie_len
,
436 const u8
*resp_ie
, size_t resp_ie_len
)
438 struct cfg80211_bss
*bss
;
439 #ifdef CONFIG_WIRELESS_EXT
440 union iwreq_data wrqu
;
443 ASSERT_WDEV_LOCK(wdev
);
445 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
448 if (WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
))
451 /* internal error -- how did we get to CONNECTED w/o BSS? */
452 if (WARN_ON(!wdev
->current_bss
)) {
456 cfg80211_unhold_bss(wdev
->current_bss
);
457 cfg80211_put_bss(&wdev
->current_bss
->pub
);
458 wdev
->current_bss
= NULL
;
460 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
461 wdev
->ssid
, wdev
->ssid_len
,
462 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
467 cfg80211_hold_bss(bss_from_pub(bss
));
468 wdev
->current_bss
= bss_from_pub(bss
);
470 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), wdev
->netdev
, bssid
,
471 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
,
474 #ifdef CONFIG_WIRELESS_EXT
476 memset(&wrqu
, 0, sizeof(wrqu
));
477 wrqu
.data
.length
= req_ie_len
;
478 wireless_send_event(wdev
->netdev
, IWEVASSOCREQIE
,
483 memset(&wrqu
, 0, sizeof(wrqu
));
484 wrqu
.data
.length
= resp_ie_len
;
485 wireless_send_event(wdev
->netdev
, IWEVASSOCRESPIE
,
489 memset(&wrqu
, 0, sizeof(wrqu
));
490 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
491 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
492 wireless_send_event(wdev
->netdev
, SIOCGIWAP
, &wrqu
, NULL
);
496 void cfg80211_roamed(struct net_device
*dev
, const u8
*bssid
,
497 const u8
*req_ie
, size_t req_ie_len
,
498 const u8
*resp_ie
, size_t resp_ie_len
, gfp_t gfp
)
500 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
501 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
502 struct cfg80211_event
*ev
;
505 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
509 ev
->type
= EVENT_ROAMED
;
510 memcpy(ev
->rm
.bssid
, bssid
, ETH_ALEN
);
511 ev
->rm
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
512 ev
->rm
.req_ie_len
= req_ie_len
;
513 memcpy((void *)ev
->rm
.req_ie
, req_ie
, req_ie_len
);
514 ev
->rm
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
515 ev
->rm
.resp_ie_len
= resp_ie_len
;
516 memcpy((void *)ev
->rm
.resp_ie
, resp_ie
, resp_ie_len
);
518 spin_lock_irqsave(&wdev
->event_lock
, flags
);
519 list_add_tail(&ev
->list
, &wdev
->event_list
);
520 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
521 schedule_work(&rdev
->event_work
);
523 EXPORT_SYMBOL(cfg80211_roamed
);
525 void __cfg80211_disconnected(struct net_device
*dev
, const u8
*ie
,
526 size_t ie_len
, u16 reason
, bool from_ap
)
528 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
529 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
531 #ifdef CONFIG_WIRELESS_EXT
532 union iwreq_data wrqu
;
535 ASSERT_WDEV_LOCK(wdev
);
537 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
540 if (WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
))
543 if (wdev
->current_bss
) {
544 cfg80211_unhold_bss(wdev
->current_bss
);
545 cfg80211_put_bss(&wdev
->current_bss
->pub
);
548 wdev
->current_bss
= NULL
;
549 wdev
->sme_state
= CFG80211_SME_IDLE
;
552 kfree(wdev
->conn
->ie
);
553 wdev
->conn
->ie
= NULL
;
558 nl80211_send_disconnected(rdev
, dev
, reason
, ie
, ie_len
, from_ap
);
561 * Delete all the keys ... pairwise keys can't really
562 * exist any more anyway, but default keys might.
564 if (rdev
->ops
->del_key
)
565 for (i
= 0; i
< 6; i
++)
566 rdev
->ops
->del_key(wdev
->wiphy
, dev
, i
, NULL
);
568 #ifdef CONFIG_WIRELESS_EXT
569 memset(&wrqu
, 0, sizeof(wrqu
));
570 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
571 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
575 void cfg80211_disconnected(struct net_device
*dev
, u16 reason
,
576 u8
*ie
, size_t ie_len
, gfp_t gfp
)
578 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
579 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
580 struct cfg80211_event
*ev
;
583 ev
= kzalloc(sizeof(*ev
) + ie_len
, gfp
);
587 ev
->type
= EVENT_DISCONNECTED
;
588 ev
->dc
.ie
= ((u8
*)ev
) + sizeof(*ev
);
589 ev
->dc
.ie_len
= ie_len
;
590 memcpy((void *)ev
->dc
.ie
, ie
, ie_len
);
591 ev
->dc
.reason
= reason
;
593 spin_lock_irqsave(&wdev
->event_lock
, flags
);
594 list_add_tail(&ev
->list
, &wdev
->event_list
);
595 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
596 schedule_work(&rdev
->event_work
);
598 EXPORT_SYMBOL(cfg80211_disconnected
);
600 int __cfg80211_connect(struct cfg80211_registered_device
*rdev
,
601 struct net_device
*dev
,
602 struct cfg80211_connect_params
*connect
,
603 struct cfg80211_cached_keys
*connkeys
)
605 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
608 ASSERT_WDEV_LOCK(wdev
);
610 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
613 if (WARN_ON(wdev
->connect_keys
)) {
614 kfree(wdev
->connect_keys
);
615 wdev
->connect_keys
= NULL
;
618 if (connkeys
&& connkeys
->def
>= 0) {
622 /* If given a WEP key we may need it for shared key auth */
623 if (connkeys
->params
[idx
].cipher
== WLAN_CIPHER_SUITE_WEP40
||
624 connkeys
->params
[idx
].cipher
== WLAN_CIPHER_SUITE_WEP104
) {
625 connect
->key_idx
= idx
;
626 connect
->key
= connkeys
->params
[idx
].key
;
627 connect
->key_len
= connkeys
->params
[idx
].key_len
;
631 if (!rdev
->ops
->connect
) {
632 if (!rdev
->ops
->auth
|| !rdev
->ops
->assoc
)
635 if (WARN_ON(wdev
->conn
))
638 wdev
->conn
= kzalloc(sizeof(*wdev
->conn
), GFP_KERNEL
);
643 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
645 memcpy(&wdev
->conn
->params
, connect
, sizeof(*connect
));
646 if (connect
->bssid
) {
647 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
648 memcpy(wdev
->conn
->bssid
, connect
->bssid
, ETH_ALEN
);
652 wdev
->conn
->ie
= kmemdup(connect
->ie
, connect
->ie_len
,
654 wdev
->conn
->params
.ie
= wdev
->conn
->ie
;
655 if (!wdev
->conn
->ie
) {
662 if (connect
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) {
663 wdev
->conn
->auto_auth
= true;
664 /* start with open system ... should mostly work */
665 wdev
->conn
->params
.auth_type
=
666 NL80211_AUTHTYPE_OPEN_SYSTEM
;
668 wdev
->conn
->auto_auth
= false;
671 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
672 wdev
->ssid_len
= connect
->ssid_len
;
673 wdev
->conn
->params
.ssid
= wdev
->ssid
;
674 wdev
->conn
->params
.ssid_len
= connect
->ssid_len
;
676 /* don't care about result -- but fill bssid & channel */
677 if (!wdev
->conn
->params
.bssid
|| !wdev
->conn
->params
.channel
)
678 cfg80211_get_conn_bss(wdev
);
680 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
681 wdev
->connect_keys
= connkeys
;
683 /* we're good if we have both BSSID and channel */
684 if (wdev
->conn
->params
.bssid
&& wdev
->conn
->params
.channel
) {
685 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
686 err
= cfg80211_conn_do_work(wdev
);
688 /* otherwise we'll need to scan for the AP first */
689 err
= cfg80211_conn_scan(wdev
);
691 * If we can't scan right now, then we need to scan again
692 * after the current scan finished, since the parameters
693 * changed (unless we find a good AP anyway).
697 wdev
->conn
->state
= CFG80211_CONN_SCAN_AGAIN
;
703 wdev
->sme_state
= CFG80211_SME_IDLE
;
704 wdev
->connect_keys
= NULL
;
709 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
710 wdev
->connect_keys
= connkeys
;
711 err
= rdev
->ops
->connect(&rdev
->wiphy
, dev
, connect
);
713 wdev
->connect_keys
= NULL
;
714 wdev
->sme_state
= CFG80211_SME_IDLE
;
718 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
719 wdev
->ssid_len
= connect
->ssid_len
;
725 int cfg80211_connect(struct cfg80211_registered_device
*rdev
,
726 struct net_device
*dev
,
727 struct cfg80211_connect_params
*connect
,
728 struct cfg80211_cached_keys
*connkeys
)
732 wdev_lock(dev
->ieee80211_ptr
);
733 err
= __cfg80211_connect(rdev
, dev
, connect
, connkeys
);
734 wdev_unlock(dev
->ieee80211_ptr
);
739 int __cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
740 struct net_device
*dev
, u16 reason
, bool wextev
)
742 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
745 ASSERT_WDEV_LOCK(wdev
);
747 if (wdev
->sme_state
== CFG80211_SME_IDLE
)
750 kfree(wdev
->connect_keys
);
751 wdev
->connect_keys
= NULL
;
753 if (!rdev
->ops
->disconnect
) {
754 if (!rdev
->ops
->deauth
)
757 /* was it connected by userspace SME? */
759 cfg80211_mlme_down(rdev
, dev
);
763 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
764 (wdev
->conn
->state
== CFG80211_CONN_SCANNING
||
765 wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)) {
766 wdev
->sme_state
= CFG80211_SME_IDLE
;
772 /* wdev->conn->params.bssid must be set if > SCANNING */
773 err
= __cfg80211_mlme_deauth(rdev
, dev
,
774 wdev
->conn
->params
.bssid
,
779 err
= rdev
->ops
->disconnect(&rdev
->wiphy
, dev
, reason
);
784 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
785 __cfg80211_disconnected(dev
, NULL
, 0, 0, false);
786 else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
787 __cfg80211_connect_result(dev
, NULL
, NULL
, 0, NULL
, 0,
788 WLAN_STATUS_UNSPECIFIED_FAILURE
,
794 int cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
795 struct net_device
*dev
,
796 u16 reason
, bool wextev
)
800 wdev_lock(dev
->ieee80211_ptr
);
801 err
= __cfg80211_disconnect(rdev
, dev
, reason
, wextev
);
802 wdev_unlock(dev
->ieee80211_ptr
);
807 void cfg80211_sme_disassoc(struct net_device
*dev
, int idx
)
809 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
810 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
813 ASSERT_WDEV_LOCK(wdev
);
818 if (wdev
->conn
->state
== CFG80211_CONN_IDLE
)
822 * Ok, so the association was made by this SME -- we don't
823 * want it any more so deauthenticate too.
826 if (!wdev
->auth_bsses
[idx
])
829 memcpy(bssid
, wdev
->auth_bsses
[idx
]->pub
.bssid
, ETH_ALEN
);
830 if (__cfg80211_mlme_deauth(rdev
, dev
, bssid
,
831 NULL
, 0, WLAN_REASON_DEAUTH_LEAVING
)) {
832 /* whatever -- assume gone anyway */
833 cfg80211_unhold_bss(wdev
->auth_bsses
[idx
]);
834 cfg80211_put_bss(&wdev
->auth_bsses
[idx
]->pub
);
835 wdev
->auth_bsses
[idx
] = NULL
;