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
,
30 u8 bssid
[ETH_ALEN
], prev_bssid
[ETH_ALEN
];
33 bool auto_auth
, prev_bssid_valid
;
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 if (wdev
->conn
->params
.channel
)
69 request
->channels
[0] = wdev
->conn
->params
.channel
;
72 enum ieee80211_band band
;
74 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
75 if (!wdev
->wiphy
->bands
[band
])
77 for (j
= 0; j
< wdev
->wiphy
->bands
[band
]->n_channels
;
79 request
->channels
[i
] =
80 &wdev
->wiphy
->bands
[band
]->channels
[j
];
83 request
->n_channels
= n_channels
;
84 request
->ssids
= (void *)&request
->channels
[n_channels
];
87 memcpy(request
->ssids
[0].ssid
, wdev
->conn
->params
.ssid
,
88 wdev
->conn
->params
.ssid_len
);
89 request
->ssids
[0].ssid_len
= wdev
->conn
->params
.ssid_len
;
91 request
->dev
= wdev
->netdev
;
92 request
->wiphy
= &rdev
->wiphy
;
94 rdev
->scan_req
= request
;
96 err
= rdev
->ops
->scan(wdev
->wiphy
, wdev
->netdev
, request
);
98 wdev
->conn
->state
= CFG80211_CONN_SCANNING
;
99 nl80211_send_scan_start(rdev
, wdev
->netdev
);
100 dev_hold(wdev
->netdev
);
102 rdev
->scan_req
= NULL
;
108 static int cfg80211_conn_do_work(struct wireless_dev
*wdev
)
110 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
111 struct cfg80211_connect_params
*params
;
112 const u8
*prev_bssid
= NULL
;
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
;
138 if (wdev
->conn
->prev_bssid_valid
)
139 prev_bssid
= wdev
->conn
->prev_bssid
;
140 err
= __cfg80211_mlme_assoc(rdev
, wdev
->netdev
,
141 params
->channel
, params
->bssid
,
143 params
->ssid
, params
->ssid_len
,
144 params
->ie
, params
->ie_len
,
145 false, ¶ms
->crypto
);
147 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
149 WLAN_REASON_DEAUTH_LEAVING
);
156 void cfg80211_conn_work(struct work_struct
*work
)
158 struct cfg80211_registered_device
*rdev
=
159 container_of(work
, struct cfg80211_registered_device
, conn_work
);
160 struct wireless_dev
*wdev
;
163 cfg80211_lock_rdev(rdev
);
164 mutex_lock(&rdev
->devlist_mtx
);
166 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
168 if (!netif_running(wdev
->netdev
)) {
172 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
) {
176 if (cfg80211_conn_do_work(wdev
))
177 __cfg80211_connect_result(
179 wdev
->conn
->params
.bssid
,
181 WLAN_STATUS_UNSPECIFIED_FAILURE
,
186 mutex_unlock(&rdev
->devlist_mtx
);
187 cfg80211_unlock_rdev(rdev
);
191 static bool cfg80211_get_conn_bss(struct wireless_dev
*wdev
)
193 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
194 struct cfg80211_bss
*bss
;
195 u16 capa
= WLAN_CAPABILITY_ESS
;
197 ASSERT_WDEV_LOCK(wdev
);
199 if (wdev
->conn
->params
.privacy
)
200 capa
|= WLAN_CAPABILITY_PRIVACY
;
202 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, wdev
->conn
->params
.bssid
,
203 wdev
->conn
->params
.ssid
,
204 wdev
->conn
->params
.ssid_len
,
205 WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_PRIVACY
,
210 memcpy(wdev
->conn
->bssid
, bss
->bssid
, ETH_ALEN
);
211 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
212 wdev
->conn
->params
.channel
= bss
->channel
;
213 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
214 schedule_work(&rdev
->conn_work
);
216 cfg80211_put_bss(bss
);
220 static void __cfg80211_sme_scan_done(struct net_device
*dev
)
222 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
223 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
225 ASSERT_WDEV_LOCK(wdev
);
227 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
233 if (wdev
->conn
->state
!= CFG80211_CONN_SCANNING
&&
234 wdev
->conn
->state
!= CFG80211_CONN_SCAN_AGAIN
)
237 if (!cfg80211_get_conn_bss(wdev
)) {
239 if (wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)
240 schedule_work(&rdev
->conn_work
);
242 __cfg80211_connect_result(
244 wdev
->conn
->params
.bssid
,
246 WLAN_STATUS_UNSPECIFIED_FAILURE
,
251 void cfg80211_sme_scan_done(struct net_device
*dev
)
253 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
255 mutex_lock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
257 __cfg80211_sme_scan_done(dev
);
259 mutex_unlock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
262 void cfg80211_sme_rx_auth(struct net_device
*dev
,
263 const u8
*buf
, size_t len
)
265 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
266 struct wiphy
*wiphy
= wdev
->wiphy
;
267 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
268 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
269 u16 status_code
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
271 ASSERT_WDEV_LOCK(wdev
);
273 /* should only RX auth frames when connecting */
274 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
277 if (WARN_ON(!wdev
->conn
))
280 if (status_code
== WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
&&
281 wdev
->conn
->auto_auth
&&
282 wdev
->conn
->params
.auth_type
!= NL80211_AUTHTYPE_NETWORK_EAP
) {
283 /* select automatically between only open, shared, leap */
284 switch (wdev
->conn
->params
.auth_type
) {
285 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
286 if (wdev
->connect_keys
)
287 wdev
->conn
->params
.auth_type
=
288 NL80211_AUTHTYPE_SHARED_KEY
;
290 wdev
->conn
->params
.auth_type
=
291 NL80211_AUTHTYPE_NETWORK_EAP
;
293 case NL80211_AUTHTYPE_SHARED_KEY
:
294 wdev
->conn
->params
.auth_type
=
295 NL80211_AUTHTYPE_NETWORK_EAP
;
299 wdev
->conn
->params
.auth_type
=
300 NL80211_AUTHTYPE_OPEN_SYSTEM
;
303 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
304 schedule_work(&rdev
->conn_work
);
305 } else if (status_code
!= WLAN_STATUS_SUCCESS
) {
306 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
307 status_code
, false, NULL
);
308 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
309 wdev
->conn
->state
== CFG80211_CONN_AUTHENTICATING
) {
310 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
311 schedule_work(&rdev
->conn_work
);
315 bool cfg80211_sme_failed_reassoc(struct wireless_dev
*wdev
)
317 struct wiphy
*wiphy
= wdev
->wiphy
;
318 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
320 if (WARN_ON(!wdev
->conn
))
323 if (!wdev
->conn
->prev_bssid_valid
)
327 * Some stupid APs don't accept reassoc, so we
328 * need to fall back to trying regular assoc.
330 wdev
->conn
->prev_bssid_valid
= false;
331 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
332 schedule_work(&rdev
->conn_work
);
337 void __cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
338 const u8
*req_ie
, size_t req_ie_len
,
339 const u8
*resp_ie
, size_t resp_ie_len
,
340 u16 status
, bool wextev
,
341 struct cfg80211_bss
*bss
)
343 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
345 #ifdef CONFIG_WIRELESS_EXT
346 union iwreq_data wrqu
;
349 ASSERT_WDEV_LOCK(wdev
);
351 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
354 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
357 nl80211_send_connect_result(wiphy_to_dev(wdev
->wiphy
), dev
,
358 bssid
, req_ie
, req_ie_len
,
359 resp_ie
, resp_ie_len
,
362 #ifdef CONFIG_WIRELESS_EXT
364 if (req_ie
&& status
== WLAN_STATUS_SUCCESS
) {
365 memset(&wrqu
, 0, sizeof(wrqu
));
366 wrqu
.data
.length
= req_ie_len
;
367 wireless_send_event(dev
, IWEVASSOCREQIE
, &wrqu
, req_ie
);
370 if (resp_ie
&& status
== WLAN_STATUS_SUCCESS
) {
371 memset(&wrqu
, 0, sizeof(wrqu
));
372 wrqu
.data
.length
= resp_ie_len
;
373 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
376 memset(&wrqu
, 0, sizeof(wrqu
));
377 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
378 if (bssid
&& status
== WLAN_STATUS_SUCCESS
) {
379 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
380 memcpy(wdev
->wext
.prev_bssid
, bssid
, ETH_ALEN
);
381 wdev
->wext
.prev_bssid_valid
= true;
383 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
387 if (wdev
->current_bss
) {
388 cfg80211_unhold_bss(wdev
->current_bss
);
389 cfg80211_put_bss(&wdev
->current_bss
->pub
);
390 wdev
->current_bss
= NULL
;
394 wdev
->conn
->state
= CFG80211_CONN_IDLE
;
396 if (status
!= WLAN_STATUS_SUCCESS
) {
397 wdev
->sme_state
= CFG80211_SME_IDLE
;
399 kfree(wdev
->conn
->ie
);
402 kfree(wdev
->connect_keys
);
403 wdev
->connect_keys
= NULL
;
409 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
410 wdev
->ssid
, wdev
->ssid_len
,
412 WLAN_CAPABILITY_ESS
);
417 cfg80211_hold_bss(bss_from_pub(bss
));
418 wdev
->current_bss
= bss_from_pub(bss
);
420 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
421 cfg80211_upload_connect_keys(wdev
);
423 country_ie
= (u8
*) ieee80211_bss_get_ie(bss
, WLAN_EID_COUNTRY
);
429 * ieee80211_bss_get_ie() ensures we can access:
430 * - country_ie + 2, the start of the country ie data, and
431 * - and country_ie[1] which is the IE length
433 regulatory_hint_11d(wdev
->wiphy
,
438 void cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
439 const u8
*req_ie
, size_t req_ie_len
,
440 const u8
*resp_ie
, size_t resp_ie_len
,
441 u16 status
, gfp_t gfp
)
443 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
444 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
445 struct cfg80211_event
*ev
;
448 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTING
);
450 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
454 ev
->type
= EVENT_CONNECT_RESULT
;
456 memcpy(ev
->cr
.bssid
, bssid
, ETH_ALEN
);
457 ev
->cr
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
458 ev
->cr
.req_ie_len
= req_ie_len
;
459 memcpy((void *)ev
->cr
.req_ie
, req_ie
, req_ie_len
);
460 ev
->cr
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
461 ev
->cr
.resp_ie_len
= resp_ie_len
;
462 memcpy((void *)ev
->cr
.resp_ie
, resp_ie
, resp_ie_len
);
463 ev
->cr
.status
= status
;
465 spin_lock_irqsave(&wdev
->event_lock
, flags
);
466 list_add_tail(&ev
->list
, &wdev
->event_list
);
467 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
468 schedule_work(&rdev
->event_work
);
470 EXPORT_SYMBOL(cfg80211_connect_result
);
472 void __cfg80211_roamed(struct wireless_dev
*wdev
, const u8
*bssid
,
473 const u8
*req_ie
, size_t req_ie_len
,
474 const u8
*resp_ie
, size_t resp_ie_len
)
476 struct cfg80211_bss
*bss
;
477 #ifdef CONFIG_WIRELESS_EXT
478 union iwreq_data wrqu
;
481 ASSERT_WDEV_LOCK(wdev
);
483 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
486 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
489 /* internal error -- how did we get to CONNECTED w/o BSS? */
490 if (WARN_ON(!wdev
->current_bss
)) {
494 cfg80211_unhold_bss(wdev
->current_bss
);
495 cfg80211_put_bss(&wdev
->current_bss
->pub
);
496 wdev
->current_bss
= NULL
;
498 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
499 wdev
->ssid
, wdev
->ssid_len
,
500 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
505 cfg80211_hold_bss(bss_from_pub(bss
));
506 wdev
->current_bss
= bss_from_pub(bss
);
508 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), wdev
->netdev
, bssid
,
509 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
,
512 #ifdef CONFIG_WIRELESS_EXT
514 memset(&wrqu
, 0, sizeof(wrqu
));
515 wrqu
.data
.length
= req_ie_len
;
516 wireless_send_event(wdev
->netdev
, IWEVASSOCREQIE
,
521 memset(&wrqu
, 0, sizeof(wrqu
));
522 wrqu
.data
.length
= resp_ie_len
;
523 wireless_send_event(wdev
->netdev
, IWEVASSOCRESPIE
,
527 memset(&wrqu
, 0, sizeof(wrqu
));
528 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
529 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
530 memcpy(wdev
->wext
.prev_bssid
, bssid
, ETH_ALEN
);
531 wdev
->wext
.prev_bssid_valid
= true;
532 wireless_send_event(wdev
->netdev
, SIOCGIWAP
, &wrqu
, NULL
);
536 void cfg80211_roamed(struct net_device
*dev
, const u8
*bssid
,
537 const u8
*req_ie
, size_t req_ie_len
,
538 const u8
*resp_ie
, size_t resp_ie_len
, gfp_t gfp
)
540 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
541 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
542 struct cfg80211_event
*ev
;
545 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
);
547 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
551 ev
->type
= EVENT_ROAMED
;
552 memcpy(ev
->rm
.bssid
, bssid
, ETH_ALEN
);
553 ev
->rm
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
554 ev
->rm
.req_ie_len
= req_ie_len
;
555 memcpy((void *)ev
->rm
.req_ie
, req_ie
, req_ie_len
);
556 ev
->rm
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
557 ev
->rm
.resp_ie_len
= resp_ie_len
;
558 memcpy((void *)ev
->rm
.resp_ie
, resp_ie
, resp_ie_len
);
560 spin_lock_irqsave(&wdev
->event_lock
, flags
);
561 list_add_tail(&ev
->list
, &wdev
->event_list
);
562 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
563 schedule_work(&rdev
->event_work
);
565 EXPORT_SYMBOL(cfg80211_roamed
);
567 void __cfg80211_disconnected(struct net_device
*dev
, const u8
*ie
,
568 size_t ie_len
, u16 reason
, bool from_ap
)
570 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
571 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
573 #ifdef CONFIG_WIRELESS_EXT
574 union iwreq_data wrqu
;
577 ASSERT_WDEV_LOCK(wdev
);
579 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
582 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
585 if (wdev
->current_bss
) {
586 cfg80211_unhold_bss(wdev
->current_bss
);
587 cfg80211_put_bss(&wdev
->current_bss
->pub
);
590 wdev
->current_bss
= NULL
;
591 wdev
->sme_state
= CFG80211_SME_IDLE
;
598 kfree(wdev
->conn
->ie
);
599 wdev
->conn
->ie
= NULL
;
604 * If this disconnect was due to a disassoc, we
605 * we might still have an auth BSS around. For
606 * the userspace SME that's currently expected,
607 * but for the kernel SME (nl80211 CONNECT or
608 * wireless extensions) we want to clear up all
611 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
612 if (!wdev
->auth_bsses
[i
])
614 bssid
= wdev
->auth_bsses
[i
]->pub
.bssid
;
615 ret
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, NULL
, 0,
616 WLAN_REASON_DEAUTH_LEAVING
);
617 WARN(ret
, "deauth failed: %d\n", ret
);
621 nl80211_send_disconnected(rdev
, dev
, reason
, ie
, ie_len
, from_ap
);
624 * Delete all the keys ... pairwise keys can't really
625 * exist any more anyway, but default keys might.
627 if (rdev
->ops
->del_key
)
628 for (i
= 0; i
< 6; i
++)
629 rdev
->ops
->del_key(wdev
->wiphy
, dev
, i
, NULL
);
631 #ifdef CONFIG_WIRELESS_EXT
632 memset(&wrqu
, 0, sizeof(wrqu
));
633 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
634 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
638 void cfg80211_disconnected(struct net_device
*dev
, u16 reason
,
639 u8
*ie
, size_t ie_len
, gfp_t gfp
)
641 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
642 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
643 struct cfg80211_event
*ev
;
646 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
);
648 ev
= kzalloc(sizeof(*ev
) + ie_len
, gfp
);
652 ev
->type
= EVENT_DISCONNECTED
;
653 ev
->dc
.ie
= ((u8
*)ev
) + sizeof(*ev
);
654 ev
->dc
.ie_len
= ie_len
;
655 memcpy((void *)ev
->dc
.ie
, ie
, ie_len
);
656 ev
->dc
.reason
= reason
;
658 spin_lock_irqsave(&wdev
->event_lock
, flags
);
659 list_add_tail(&ev
->list
, &wdev
->event_list
);
660 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
661 schedule_work(&rdev
->event_work
);
663 EXPORT_SYMBOL(cfg80211_disconnected
);
665 int __cfg80211_connect(struct cfg80211_registered_device
*rdev
,
666 struct net_device
*dev
,
667 struct cfg80211_connect_params
*connect
,
668 struct cfg80211_cached_keys
*connkeys
,
669 const u8
*prev_bssid
)
671 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
672 struct ieee80211_channel
*chan
;
675 ASSERT_WDEV_LOCK(wdev
);
677 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
680 chan
= rdev_fixed_channel(rdev
, wdev
);
681 if (chan
&& chan
!= connect
->channel
)
684 if (WARN_ON(wdev
->connect_keys
)) {
685 kfree(wdev
->connect_keys
);
686 wdev
->connect_keys
= NULL
;
689 if (connkeys
&& connkeys
->def
>= 0) {
694 cipher
= connkeys
->params
[idx
].cipher
;
695 /* If given a WEP key we may need it for shared key auth */
696 if (cipher
== WLAN_CIPHER_SUITE_WEP40
||
697 cipher
== WLAN_CIPHER_SUITE_WEP104
) {
698 connect
->key_idx
= idx
;
699 connect
->key
= connkeys
->params
[idx
].key
;
700 connect
->key_len
= connkeys
->params
[idx
].key_len
;
703 * If ciphers are not set (e.g. when going through
704 * iwconfig), we have to set them appropriately here.
706 if (connect
->crypto
.cipher_group
== 0)
707 connect
->crypto
.cipher_group
= cipher
;
709 if (connect
->crypto
.n_ciphers_pairwise
== 0) {
710 connect
->crypto
.n_ciphers_pairwise
= 1;
711 connect
->crypto
.ciphers_pairwise
[0] = cipher
;
716 if (!rdev
->ops
->connect
) {
717 if (!rdev
->ops
->auth
|| !rdev
->ops
->assoc
)
720 if (WARN_ON(wdev
->conn
))
723 wdev
->conn
= kzalloc(sizeof(*wdev
->conn
), GFP_KERNEL
);
728 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
730 memcpy(&wdev
->conn
->params
, connect
, sizeof(*connect
));
731 if (connect
->bssid
) {
732 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
733 memcpy(wdev
->conn
->bssid
, connect
->bssid
, ETH_ALEN
);
737 wdev
->conn
->ie
= kmemdup(connect
->ie
, connect
->ie_len
,
739 wdev
->conn
->params
.ie
= wdev
->conn
->ie
;
740 if (!wdev
->conn
->ie
) {
747 if (connect
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) {
748 wdev
->conn
->auto_auth
= true;
749 /* start with open system ... should mostly work */
750 wdev
->conn
->params
.auth_type
=
751 NL80211_AUTHTYPE_OPEN_SYSTEM
;
753 wdev
->conn
->auto_auth
= false;
756 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
757 wdev
->ssid_len
= connect
->ssid_len
;
758 wdev
->conn
->params
.ssid
= wdev
->ssid
;
759 wdev
->conn
->params
.ssid_len
= connect
->ssid_len
;
761 /* don't care about result -- but fill bssid & channel */
762 if (!wdev
->conn
->params
.bssid
|| !wdev
->conn
->params
.channel
)
763 cfg80211_get_conn_bss(wdev
);
765 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
766 wdev
->connect_keys
= connkeys
;
769 memcpy(wdev
->conn
->prev_bssid
, prev_bssid
, ETH_ALEN
);
770 wdev
->conn
->prev_bssid_valid
= true;
773 /* we're good if we have both BSSID and channel */
774 if (wdev
->conn
->params
.bssid
&& wdev
->conn
->params
.channel
) {
775 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
776 err
= cfg80211_conn_do_work(wdev
);
778 /* otherwise we'll need to scan for the AP first */
779 err
= cfg80211_conn_scan(wdev
);
781 * If we can't scan right now, then we need to scan again
782 * after the current scan finished, since the parameters
783 * changed (unless we find a good AP anyway).
787 wdev
->conn
->state
= CFG80211_CONN_SCAN_AGAIN
;
791 kfree(wdev
->conn
->ie
);
794 wdev
->sme_state
= CFG80211_SME_IDLE
;
795 wdev
->connect_keys
= NULL
;
801 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
802 wdev
->connect_keys
= connkeys
;
803 err
= rdev
->ops
->connect(&rdev
->wiphy
, dev
, connect
);
805 wdev
->connect_keys
= NULL
;
806 wdev
->sme_state
= CFG80211_SME_IDLE
;
810 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
811 wdev
->ssid_len
= connect
->ssid_len
;
817 int cfg80211_connect(struct cfg80211_registered_device
*rdev
,
818 struct net_device
*dev
,
819 struct cfg80211_connect_params
*connect
,
820 struct cfg80211_cached_keys
*connkeys
)
824 mutex_lock(&rdev
->devlist_mtx
);
825 wdev_lock(dev
->ieee80211_ptr
);
826 err
= __cfg80211_connect(rdev
, dev
, connect
, connkeys
, NULL
);
827 wdev_unlock(dev
->ieee80211_ptr
);
828 mutex_unlock(&rdev
->devlist_mtx
);
833 int __cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
834 struct net_device
*dev
, u16 reason
, bool wextev
)
836 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
839 ASSERT_WDEV_LOCK(wdev
);
841 if (wdev
->sme_state
== CFG80211_SME_IDLE
)
844 kfree(wdev
->connect_keys
);
845 wdev
->connect_keys
= NULL
;
847 if (!rdev
->ops
->disconnect
) {
848 if (!rdev
->ops
->deauth
)
851 /* was it connected by userspace SME? */
853 cfg80211_mlme_down(rdev
, dev
);
857 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
858 (wdev
->conn
->state
== CFG80211_CONN_SCANNING
||
859 wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)) {
860 wdev
->sme_state
= CFG80211_SME_IDLE
;
861 kfree(wdev
->conn
->ie
);
868 /* wdev->conn->params.bssid must be set if > SCANNING */
869 err
= __cfg80211_mlme_deauth(rdev
, dev
,
870 wdev
->conn
->params
.bssid
,
875 err
= rdev
->ops
->disconnect(&rdev
->wiphy
, dev
, reason
);
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
,
890 int cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
891 struct net_device
*dev
,
892 u16 reason
, bool wextev
)
896 wdev_lock(dev
->ieee80211_ptr
);
897 err
= __cfg80211_disconnect(rdev
, dev
, reason
, wextev
);
898 wdev_unlock(dev
->ieee80211_ptr
);
903 void cfg80211_sme_disassoc(struct net_device
*dev
, int idx
)
905 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
906 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
909 ASSERT_WDEV_LOCK(wdev
);
914 if (wdev
->conn
->state
== CFG80211_CONN_IDLE
)
918 * Ok, so the association was made by this SME -- we don't
919 * want it any more so deauthenticate too.
922 if (!wdev
->auth_bsses
[idx
])
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
;