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/slab.h>
11 #include <linux/workqueue.h>
12 #include <linux/wireless.h>
13 #include <net/iw_handler.h>
14 #include <net/cfg80211.h>
15 #include <net/rtnetlink.h>
19 struct cfg80211_conn
{
20 struct cfg80211_connect_params params
;
21 /* these are sub-states of the _CONNECTING sme_state */
24 CFG80211_CONN_SCANNING
,
25 CFG80211_CONN_SCAN_AGAIN
,
26 CFG80211_CONN_AUTHENTICATE_NEXT
,
27 CFG80211_CONN_AUTHENTICATING
,
28 CFG80211_CONN_ASSOCIATE_NEXT
,
29 CFG80211_CONN_ASSOCIATING
,
30 CFG80211_CONN_DEAUTH_ASSOC_FAIL
,
32 u8 bssid
[ETH_ALEN
], prev_bssid
[ETH_ALEN
];
35 bool auto_auth
, prev_bssid_valid
;
38 bool cfg80211_is_all_idle(void)
40 struct cfg80211_registered_device
*rdev
;
41 struct wireless_dev
*wdev
;
42 bool is_all_idle
= true;
44 mutex_lock(&cfg80211_mutex
);
47 * All devices must be idle as otherwise if you are actively
48 * scanning some new beacon hints could be learned and would
49 * count as new regulatory hints.
51 list_for_each_entry(rdev
, &cfg80211_rdev_list
, list
) {
52 cfg80211_lock_rdev(rdev
);
53 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
55 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
59 cfg80211_unlock_rdev(rdev
);
62 mutex_unlock(&cfg80211_mutex
);
67 static void disconnect_work(struct work_struct
*work
)
69 if (!cfg80211_is_all_idle())
72 regulatory_hint_disconnect();
75 static DECLARE_WORK(cfg80211_disconnect_work
, disconnect_work
);
77 static int cfg80211_conn_scan(struct wireless_dev
*wdev
)
79 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
80 struct cfg80211_scan_request
*request
;
84 ASSERT_RDEV_LOCK(rdev
);
85 ASSERT_WDEV_LOCK(wdev
);
90 if (wdev
->conn
->params
.channel
) {
93 enum ieee80211_band band
;
96 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
97 if (!wdev
->wiphy
->bands
[band
])
99 n_channels
+= wdev
->wiphy
->bands
[band
]->n_channels
;
102 request
= kzalloc(sizeof(*request
) + sizeof(request
->ssids
[0]) +
103 sizeof(request
->channels
[0]) * n_channels
,
108 if (wdev
->conn
->params
.channel
)
109 request
->channels
[0] = wdev
->conn
->params
.channel
;
112 enum ieee80211_band band
;
114 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
115 if (!wdev
->wiphy
->bands
[band
])
117 for (j
= 0; j
< wdev
->wiphy
->bands
[band
]->n_channels
;
119 request
->channels
[i
] =
120 &wdev
->wiphy
->bands
[band
]->channels
[j
];
123 request
->n_channels
= n_channels
;
124 request
->ssids
= (void *)&request
->channels
[n_channels
];
125 request
->n_ssids
= 1;
127 memcpy(request
->ssids
[0].ssid
, wdev
->conn
->params
.ssid
,
128 wdev
->conn
->params
.ssid_len
);
129 request
->ssids
[0].ssid_len
= wdev
->conn
->params
.ssid_len
;
131 request
->dev
= wdev
->netdev
;
132 request
->wiphy
= &rdev
->wiphy
;
134 rdev
->scan_req
= request
;
136 err
= rdev
->ops
->scan(wdev
->wiphy
, wdev
->netdev
, request
);
138 wdev
->conn
->state
= CFG80211_CONN_SCANNING
;
139 nl80211_send_scan_start(rdev
, wdev
->netdev
);
140 dev_hold(wdev
->netdev
);
142 rdev
->scan_req
= NULL
;
148 static int cfg80211_conn_do_work(struct wireless_dev
*wdev
)
150 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
151 struct cfg80211_connect_params
*params
;
152 const u8
*prev_bssid
= NULL
;
155 ASSERT_WDEV_LOCK(wdev
);
160 params
= &wdev
->conn
->params
;
162 switch (wdev
->conn
->state
) {
163 case CFG80211_CONN_SCAN_AGAIN
:
164 return cfg80211_conn_scan(wdev
);
165 case CFG80211_CONN_AUTHENTICATE_NEXT
:
166 BUG_ON(!rdev
->ops
->auth
);
167 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATING
;
168 return __cfg80211_mlme_auth(rdev
, wdev
->netdev
,
169 params
->channel
, params
->auth_type
,
171 params
->ssid
, params
->ssid_len
,
173 params
->key
, params
->key_len
,
175 case CFG80211_CONN_ASSOCIATE_NEXT
:
176 BUG_ON(!rdev
->ops
->assoc
);
177 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATING
;
178 if (wdev
->conn
->prev_bssid_valid
)
179 prev_bssid
= wdev
->conn
->prev_bssid
;
180 err
= __cfg80211_mlme_assoc(rdev
, wdev
->netdev
,
181 params
->channel
, params
->bssid
,
183 params
->ssid
, params
->ssid_len
,
184 params
->ie
, params
->ie_len
,
185 false, ¶ms
->crypto
);
187 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
189 WLAN_REASON_DEAUTH_LEAVING
);
191 case CFG80211_CONN_DEAUTH_ASSOC_FAIL
:
192 __cfg80211_mlme_deauth(rdev
, wdev
->netdev
, params
->bssid
,
194 WLAN_REASON_DEAUTH_LEAVING
);
195 /* return an error so that we call __cfg80211_connect_result() */
202 void cfg80211_conn_work(struct work_struct
*work
)
204 struct cfg80211_registered_device
*rdev
=
205 container_of(work
, struct cfg80211_registered_device
, conn_work
);
206 struct wireless_dev
*wdev
;
207 u8 bssid_buf
[ETH_ALEN
], *bssid
= NULL
;
210 cfg80211_lock_rdev(rdev
);
211 mutex_lock(&rdev
->devlist_mtx
);
213 list_for_each_entry(wdev
, &rdev
->netdev_list
, list
) {
215 if (!netif_running(wdev
->netdev
)) {
219 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
) {
223 if (wdev
->conn
->params
.bssid
) {
224 memcpy(bssid_buf
, wdev
->conn
->params
.bssid
, ETH_ALEN
);
227 if (cfg80211_conn_do_work(wdev
))
228 __cfg80211_connect_result(
231 WLAN_STATUS_UNSPECIFIED_FAILURE
,
236 mutex_unlock(&rdev
->devlist_mtx
);
237 cfg80211_unlock_rdev(rdev
);
241 static struct cfg80211_bss
*cfg80211_get_conn_bss(struct wireless_dev
*wdev
)
243 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
244 struct cfg80211_bss
*bss
;
245 u16 capa
= WLAN_CAPABILITY_ESS
;
247 ASSERT_WDEV_LOCK(wdev
);
249 if (wdev
->conn
->params
.privacy
)
250 capa
|= WLAN_CAPABILITY_PRIVACY
;
252 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, wdev
->conn
->params
.bssid
,
253 wdev
->conn
->params
.ssid
,
254 wdev
->conn
->params
.ssid_len
,
255 WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_PRIVACY
,
260 memcpy(wdev
->conn
->bssid
, bss
->bssid
, ETH_ALEN
);
261 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
262 wdev
->conn
->params
.channel
= bss
->channel
;
263 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
264 schedule_work(&rdev
->conn_work
);
269 static void __cfg80211_sme_scan_done(struct net_device
*dev
)
271 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
272 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
273 struct cfg80211_bss
*bss
;
275 ASSERT_WDEV_LOCK(wdev
);
277 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
283 if (wdev
->conn
->state
!= CFG80211_CONN_SCANNING
&&
284 wdev
->conn
->state
!= CFG80211_CONN_SCAN_AGAIN
)
287 bss
= cfg80211_get_conn_bss(wdev
);
289 cfg80211_put_bss(bss
);
292 if (wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)
293 schedule_work(&rdev
->conn_work
);
295 __cfg80211_connect_result(
297 wdev
->conn
->params
.bssid
,
299 WLAN_STATUS_UNSPECIFIED_FAILURE
,
304 void cfg80211_sme_scan_done(struct net_device
*dev
)
306 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
308 mutex_lock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
310 __cfg80211_sme_scan_done(dev
);
312 mutex_unlock(&wiphy_to_dev(wdev
->wiphy
)->devlist_mtx
);
315 void cfg80211_sme_rx_auth(struct net_device
*dev
,
316 const u8
*buf
, size_t len
)
318 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
319 struct wiphy
*wiphy
= wdev
->wiphy
;
320 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
321 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
322 u16 status_code
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
324 ASSERT_WDEV_LOCK(wdev
);
326 /* should only RX auth frames when connecting */
327 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
330 if (WARN_ON(!wdev
->conn
))
333 if (status_code
== WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
&&
334 wdev
->conn
->auto_auth
&&
335 wdev
->conn
->params
.auth_type
!= NL80211_AUTHTYPE_NETWORK_EAP
) {
336 /* select automatically between only open, shared, leap */
337 switch (wdev
->conn
->params
.auth_type
) {
338 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
339 if (wdev
->connect_keys
)
340 wdev
->conn
->params
.auth_type
=
341 NL80211_AUTHTYPE_SHARED_KEY
;
343 wdev
->conn
->params
.auth_type
=
344 NL80211_AUTHTYPE_NETWORK_EAP
;
346 case NL80211_AUTHTYPE_SHARED_KEY
:
347 wdev
->conn
->params
.auth_type
=
348 NL80211_AUTHTYPE_NETWORK_EAP
;
352 wdev
->conn
->params
.auth_type
=
353 NL80211_AUTHTYPE_OPEN_SYSTEM
;
356 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
357 schedule_work(&rdev
->conn_work
);
358 } else if (status_code
!= WLAN_STATUS_SUCCESS
) {
359 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, NULL
, 0,
360 status_code
, false, NULL
);
361 } else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
362 wdev
->conn
->state
== CFG80211_CONN_AUTHENTICATING
) {
363 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
364 schedule_work(&rdev
->conn_work
);
368 bool cfg80211_sme_failed_reassoc(struct wireless_dev
*wdev
)
370 struct wiphy
*wiphy
= wdev
->wiphy
;
371 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
373 if (WARN_ON(!wdev
->conn
))
376 if (!wdev
->conn
->prev_bssid_valid
)
380 * Some stupid APs don't accept reassoc, so we
381 * need to fall back to trying regular assoc.
383 wdev
->conn
->prev_bssid_valid
= false;
384 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
385 schedule_work(&rdev
->conn_work
);
390 void cfg80211_sme_failed_assoc(struct wireless_dev
*wdev
)
392 struct wiphy
*wiphy
= wdev
->wiphy
;
393 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
395 wdev
->conn
->state
= CFG80211_CONN_DEAUTH_ASSOC_FAIL
;
396 schedule_work(&rdev
->conn_work
);
399 void __cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
400 const u8
*req_ie
, size_t req_ie_len
,
401 const u8
*resp_ie
, size_t resp_ie_len
,
402 u16 status
, bool wextev
,
403 struct cfg80211_bss
*bss
)
405 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
407 #ifdef CONFIG_CFG80211_WEXT
408 union iwreq_data wrqu
;
411 ASSERT_WDEV_LOCK(wdev
);
413 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
416 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
419 nl80211_send_connect_result(wiphy_to_dev(wdev
->wiphy
), dev
,
420 bssid
, req_ie
, req_ie_len
,
421 resp_ie
, resp_ie_len
,
424 #ifdef CONFIG_CFG80211_WEXT
426 if (req_ie
&& status
== WLAN_STATUS_SUCCESS
) {
427 memset(&wrqu
, 0, sizeof(wrqu
));
428 wrqu
.data
.length
= req_ie_len
;
429 wireless_send_event(dev
, IWEVASSOCREQIE
, &wrqu
, req_ie
);
432 if (resp_ie
&& status
== WLAN_STATUS_SUCCESS
) {
433 memset(&wrqu
, 0, sizeof(wrqu
));
434 wrqu
.data
.length
= resp_ie_len
;
435 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
438 memset(&wrqu
, 0, sizeof(wrqu
));
439 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
440 if (bssid
&& status
== WLAN_STATUS_SUCCESS
) {
441 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
442 memcpy(wdev
->wext
.prev_bssid
, bssid
, ETH_ALEN
);
443 wdev
->wext
.prev_bssid_valid
= true;
445 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
449 if (wdev
->current_bss
) {
450 cfg80211_unhold_bss(wdev
->current_bss
);
451 cfg80211_put_bss(&wdev
->current_bss
->pub
);
452 wdev
->current_bss
= NULL
;
456 wdev
->conn
->state
= CFG80211_CONN_IDLE
;
458 if (status
!= WLAN_STATUS_SUCCESS
) {
459 wdev
->sme_state
= CFG80211_SME_IDLE
;
461 kfree(wdev
->conn
->ie
);
464 kfree(wdev
->connect_keys
);
465 wdev
->connect_keys
= NULL
;
471 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
472 wdev
->ssid
, wdev
->ssid_len
,
474 WLAN_CAPABILITY_ESS
);
479 cfg80211_hold_bss(bss_from_pub(bss
));
480 wdev
->current_bss
= bss_from_pub(bss
);
482 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
483 cfg80211_upload_connect_keys(wdev
);
485 country_ie
= (u8
*) ieee80211_bss_get_ie(bss
, WLAN_EID_COUNTRY
);
491 * ieee80211_bss_get_ie() ensures we can access:
492 * - country_ie + 2, the start of the country ie data, and
493 * - and country_ie[1] which is the IE length
495 regulatory_hint_11d(wdev
->wiphy
,
501 void cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
502 const u8
*req_ie
, size_t req_ie_len
,
503 const u8
*resp_ie
, size_t resp_ie_len
,
504 u16 status
, gfp_t gfp
)
506 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
507 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
508 struct cfg80211_event
*ev
;
511 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTING
);
513 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
517 ev
->type
= EVENT_CONNECT_RESULT
;
519 memcpy(ev
->cr
.bssid
, bssid
, ETH_ALEN
);
520 ev
->cr
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
521 ev
->cr
.req_ie_len
= req_ie_len
;
522 memcpy((void *)ev
->cr
.req_ie
, req_ie
, req_ie_len
);
523 ev
->cr
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
524 ev
->cr
.resp_ie_len
= resp_ie_len
;
525 memcpy((void *)ev
->cr
.resp_ie
, resp_ie
, resp_ie_len
);
526 ev
->cr
.status
= status
;
528 spin_lock_irqsave(&wdev
->event_lock
, flags
);
529 list_add_tail(&ev
->list
, &wdev
->event_list
);
530 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
531 queue_work(cfg80211_wq
, &rdev
->event_work
);
533 EXPORT_SYMBOL(cfg80211_connect_result
);
535 void __cfg80211_roamed(struct wireless_dev
*wdev
, const u8
*bssid
,
536 const u8
*req_ie
, size_t req_ie_len
,
537 const u8
*resp_ie
, size_t resp_ie_len
)
539 struct cfg80211_bss
*bss
;
540 #ifdef CONFIG_CFG80211_WEXT
541 union iwreq_data wrqu
;
544 ASSERT_WDEV_LOCK(wdev
);
546 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
549 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
552 /* internal error -- how did we get to CONNECTED w/o BSS? */
553 if (WARN_ON(!wdev
->current_bss
)) {
557 cfg80211_unhold_bss(wdev
->current_bss
);
558 cfg80211_put_bss(&wdev
->current_bss
->pub
);
559 wdev
->current_bss
= NULL
;
561 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
562 wdev
->ssid
, wdev
->ssid_len
,
563 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
568 cfg80211_hold_bss(bss_from_pub(bss
));
569 wdev
->current_bss
= bss_from_pub(bss
);
571 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), wdev
->netdev
, bssid
,
572 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
,
575 #ifdef CONFIG_CFG80211_WEXT
577 memset(&wrqu
, 0, sizeof(wrqu
));
578 wrqu
.data
.length
= req_ie_len
;
579 wireless_send_event(wdev
->netdev
, IWEVASSOCREQIE
,
584 memset(&wrqu
, 0, sizeof(wrqu
));
585 wrqu
.data
.length
= resp_ie_len
;
586 wireless_send_event(wdev
->netdev
, IWEVASSOCRESPIE
,
590 memset(&wrqu
, 0, sizeof(wrqu
));
591 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
592 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
593 memcpy(wdev
->wext
.prev_bssid
, bssid
, ETH_ALEN
);
594 wdev
->wext
.prev_bssid_valid
= true;
595 wireless_send_event(wdev
->netdev
, SIOCGIWAP
, &wrqu
, NULL
);
599 void cfg80211_roamed(struct net_device
*dev
, const u8
*bssid
,
600 const u8
*req_ie
, size_t req_ie_len
,
601 const u8
*resp_ie
, size_t resp_ie_len
, gfp_t gfp
)
603 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
604 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
605 struct cfg80211_event
*ev
;
608 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
);
610 ev
= kzalloc(sizeof(*ev
) + req_ie_len
+ resp_ie_len
, gfp
);
614 ev
->type
= EVENT_ROAMED
;
615 memcpy(ev
->rm
.bssid
, bssid
, ETH_ALEN
);
616 ev
->rm
.req_ie
= ((u8
*)ev
) + sizeof(*ev
);
617 ev
->rm
.req_ie_len
= req_ie_len
;
618 memcpy((void *)ev
->rm
.req_ie
, req_ie
, req_ie_len
);
619 ev
->rm
.resp_ie
= ((u8
*)ev
) + sizeof(*ev
) + req_ie_len
;
620 ev
->rm
.resp_ie_len
= resp_ie_len
;
621 memcpy((void *)ev
->rm
.resp_ie
, resp_ie
, resp_ie_len
);
623 spin_lock_irqsave(&wdev
->event_lock
, flags
);
624 list_add_tail(&ev
->list
, &wdev
->event_list
);
625 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
626 queue_work(cfg80211_wq
, &rdev
->event_work
);
628 EXPORT_SYMBOL(cfg80211_roamed
);
630 void __cfg80211_disconnected(struct net_device
*dev
, const u8
*ie
,
631 size_t ie_len
, u16 reason
, bool from_ap
)
633 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
634 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
636 #ifdef CONFIG_CFG80211_WEXT
637 union iwreq_data wrqu
;
640 ASSERT_WDEV_LOCK(wdev
);
642 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
645 if (wdev
->sme_state
!= CFG80211_SME_CONNECTED
)
648 if (wdev
->current_bss
) {
649 cfg80211_unhold_bss(wdev
->current_bss
);
650 cfg80211_put_bss(&wdev
->current_bss
->pub
);
653 wdev
->current_bss
= NULL
;
654 wdev
->sme_state
= CFG80211_SME_IDLE
;
661 kfree(wdev
->conn
->ie
);
662 wdev
->conn
->ie
= NULL
;
667 * If this disconnect was due to a disassoc, we
668 * we might still have an auth BSS around. For
669 * the userspace SME that's currently expected,
670 * but for the kernel SME (nl80211 CONNECT or
671 * wireless extensions) we want to clear up all
674 for (i
= 0; i
< MAX_AUTH_BSSES
; i
++) {
675 if (!wdev
->auth_bsses
[i
])
677 bssid
= wdev
->auth_bsses
[i
]->pub
.bssid
;
678 ret
= __cfg80211_mlme_deauth(rdev
, dev
, bssid
, NULL
, 0,
679 WLAN_REASON_DEAUTH_LEAVING
);
680 WARN(ret
, "deauth failed: %d\n", ret
);
684 nl80211_send_disconnected(rdev
, dev
, reason
, ie
, ie_len
, from_ap
);
687 * Delete all the keys ... pairwise keys can't really
688 * exist any more anyway, but default keys might.
690 if (rdev
->ops
->del_key
)
691 for (i
= 0; i
< 6; i
++)
692 rdev
->ops
->del_key(wdev
->wiphy
, dev
, i
, NULL
);
694 #ifdef CONFIG_CFG80211_WEXT
695 memset(&wrqu
, 0, sizeof(wrqu
));
696 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
697 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
698 wdev
->wext
.connect
.ssid_len
= 0;
701 schedule_work(&cfg80211_disconnect_work
);
704 void cfg80211_disconnected(struct net_device
*dev
, u16 reason
,
705 u8
*ie
, size_t ie_len
, gfp_t gfp
)
707 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
708 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
709 struct cfg80211_event
*ev
;
712 CFG80211_DEV_WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
);
714 ev
= kzalloc(sizeof(*ev
) + ie_len
, gfp
);
718 ev
->type
= EVENT_DISCONNECTED
;
719 ev
->dc
.ie
= ((u8
*)ev
) + sizeof(*ev
);
720 ev
->dc
.ie_len
= ie_len
;
721 memcpy((void *)ev
->dc
.ie
, ie
, ie_len
);
722 ev
->dc
.reason
= reason
;
724 spin_lock_irqsave(&wdev
->event_lock
, flags
);
725 list_add_tail(&ev
->list
, &wdev
->event_list
);
726 spin_unlock_irqrestore(&wdev
->event_lock
, flags
);
727 queue_work(cfg80211_wq
, &rdev
->event_work
);
729 EXPORT_SYMBOL(cfg80211_disconnected
);
731 int __cfg80211_connect(struct cfg80211_registered_device
*rdev
,
732 struct net_device
*dev
,
733 struct cfg80211_connect_params
*connect
,
734 struct cfg80211_cached_keys
*connkeys
,
735 const u8
*prev_bssid
)
737 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
738 struct ieee80211_channel
*chan
;
739 struct cfg80211_bss
*bss
= NULL
;
742 ASSERT_WDEV_LOCK(wdev
);
744 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
747 chan
= rdev_fixed_channel(rdev
, wdev
);
748 if (chan
&& chan
!= connect
->channel
)
751 if (WARN_ON(wdev
->connect_keys
)) {
752 kfree(wdev
->connect_keys
);
753 wdev
->connect_keys
= NULL
;
756 if (connkeys
&& connkeys
->def
>= 0) {
761 cipher
= connkeys
->params
[idx
].cipher
;
762 /* If given a WEP key we may need it for shared key auth */
763 if (cipher
== WLAN_CIPHER_SUITE_WEP40
||
764 cipher
== WLAN_CIPHER_SUITE_WEP104
) {
765 connect
->key_idx
= idx
;
766 connect
->key
= connkeys
->params
[idx
].key
;
767 connect
->key_len
= connkeys
->params
[idx
].key_len
;
770 * If ciphers are not set (e.g. when going through
771 * iwconfig), we have to set them appropriately here.
773 if (connect
->crypto
.cipher_group
== 0)
774 connect
->crypto
.cipher_group
= cipher
;
776 if (connect
->crypto
.n_ciphers_pairwise
== 0) {
777 connect
->crypto
.n_ciphers_pairwise
= 1;
778 connect
->crypto
.ciphers_pairwise
[0] = cipher
;
783 if (!rdev
->ops
->connect
) {
784 if (!rdev
->ops
->auth
|| !rdev
->ops
->assoc
)
787 if (WARN_ON(wdev
->conn
))
790 wdev
->conn
= kzalloc(sizeof(*wdev
->conn
), GFP_KERNEL
);
795 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
797 memcpy(&wdev
->conn
->params
, connect
, sizeof(*connect
));
798 if (connect
->bssid
) {
799 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
800 memcpy(wdev
->conn
->bssid
, connect
->bssid
, ETH_ALEN
);
804 wdev
->conn
->ie
= kmemdup(connect
->ie
, connect
->ie_len
,
806 wdev
->conn
->params
.ie
= wdev
->conn
->ie
;
807 if (!wdev
->conn
->ie
) {
814 if (connect
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) {
815 wdev
->conn
->auto_auth
= true;
816 /* start with open system ... should mostly work */
817 wdev
->conn
->params
.auth_type
=
818 NL80211_AUTHTYPE_OPEN_SYSTEM
;
820 wdev
->conn
->auto_auth
= false;
823 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
824 wdev
->ssid_len
= connect
->ssid_len
;
825 wdev
->conn
->params
.ssid
= wdev
->ssid
;
826 wdev
->conn
->params
.ssid_len
= connect
->ssid_len
;
828 /* see if we have the bss already */
829 bss
= cfg80211_get_conn_bss(wdev
);
831 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
832 wdev
->connect_keys
= connkeys
;
835 memcpy(wdev
->conn
->prev_bssid
, prev_bssid
, ETH_ALEN
);
836 wdev
->conn
->prev_bssid_valid
= true;
839 /* we're good if we have a matching bss struct */
841 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
842 err
= cfg80211_conn_do_work(wdev
);
843 cfg80211_put_bss(bss
);
845 /* otherwise we'll need to scan for the AP first */
846 err
= cfg80211_conn_scan(wdev
);
848 * If we can't scan right now, then we need to scan again
849 * after the current scan finished, since the parameters
850 * changed (unless we find a good AP anyway).
854 wdev
->conn
->state
= CFG80211_CONN_SCAN_AGAIN
;
858 kfree(wdev
->conn
->ie
);
861 wdev
->sme_state
= CFG80211_SME_IDLE
;
862 wdev
->connect_keys
= NULL
;
868 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
869 wdev
->connect_keys
= connkeys
;
870 err
= rdev
->ops
->connect(&rdev
->wiphy
, dev
, connect
);
872 wdev
->connect_keys
= NULL
;
873 wdev
->sme_state
= CFG80211_SME_IDLE
;
877 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
878 wdev
->ssid_len
= connect
->ssid_len
;
884 int cfg80211_connect(struct cfg80211_registered_device
*rdev
,
885 struct net_device
*dev
,
886 struct cfg80211_connect_params
*connect
,
887 struct cfg80211_cached_keys
*connkeys
)
891 mutex_lock(&rdev
->devlist_mtx
);
892 wdev_lock(dev
->ieee80211_ptr
);
893 err
= __cfg80211_connect(rdev
, dev
, connect
, connkeys
, NULL
);
894 wdev_unlock(dev
->ieee80211_ptr
);
895 mutex_unlock(&rdev
->devlist_mtx
);
900 int __cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
901 struct net_device
*dev
, u16 reason
, bool wextev
)
903 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
906 ASSERT_WDEV_LOCK(wdev
);
908 if (wdev
->sme_state
== CFG80211_SME_IDLE
)
911 kfree(wdev
->connect_keys
);
912 wdev
->connect_keys
= NULL
;
914 if (!rdev
->ops
->disconnect
) {
915 if (!rdev
->ops
->deauth
)
918 /* was it connected by userspace SME? */
920 cfg80211_mlme_down(rdev
, dev
);
924 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
925 (wdev
->conn
->state
== CFG80211_CONN_SCANNING
||
926 wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)) {
927 wdev
->sme_state
= CFG80211_SME_IDLE
;
928 kfree(wdev
->conn
->ie
);
935 /* wdev->conn->params.bssid must be set if > SCANNING */
936 err
= __cfg80211_mlme_deauth(rdev
, dev
,
937 wdev
->conn
->params
.bssid
,
942 err
= rdev
->ops
->disconnect(&rdev
->wiphy
, dev
, reason
);
947 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
948 __cfg80211_disconnected(dev
, NULL
, 0, 0, false);
949 else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
950 __cfg80211_connect_result(dev
, NULL
, NULL
, 0, NULL
, 0,
951 WLAN_STATUS_UNSPECIFIED_FAILURE
,
957 int cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
958 struct net_device
*dev
,
959 u16 reason
, bool wextev
)
963 wdev_lock(dev
->ieee80211_ptr
);
964 err
= __cfg80211_disconnect(rdev
, dev
, reason
, wextev
);
965 wdev_unlock(dev
->ieee80211_ptr
);
970 void cfg80211_sme_disassoc(struct net_device
*dev
, int idx
)
972 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
973 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
976 ASSERT_WDEV_LOCK(wdev
);
981 if (wdev
->conn
->state
== CFG80211_CONN_IDLE
)
985 * Ok, so the association was made by this SME -- we don't
986 * want it any more so deauthenticate too.
989 if (!wdev
->auth_bsses
[idx
])
992 memcpy(bssid
, wdev
->auth_bsses
[idx
]->pub
.bssid
, ETH_ALEN
);
993 if (__cfg80211_mlme_deauth(rdev
, dev
, bssid
,
994 NULL
, 0, WLAN_REASON_DEAUTH_LEAVING
)) {
995 /* whatever -- assume gone anyway */
996 cfg80211_unhold_bss(wdev
->auth_bsses
[idx
]);
997 cfg80211_put_bss(&wdev
->auth_bsses
[idx
]->pub
);
998 wdev
->auth_bsses
[idx
] = NULL
;