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
*drv
= wiphy_to_dev(wdev
->wiphy
);
37 struct cfg80211_scan_request
*request
;
45 if (wdev
->conn
->params
.channel
) {
48 enum ieee80211_band band
;
51 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
52 if (!wdev
->wiphy
->bands
[band
])
54 n_channels
+= wdev
->wiphy
->bands
[band
]->n_channels
;
57 request
= kzalloc(sizeof(*request
) + sizeof(request
->ssids
[0]) +
58 sizeof(request
->channels
[0]) * n_channels
,
63 request
->channels
= (void *)((char *)request
+ sizeof(*request
));
64 if (wdev
->conn
->params
.channel
)
65 request
->channels
[0] = wdev
->conn
->params
.channel
;
68 enum ieee80211_band band
;
70 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
71 if (!wdev
->wiphy
->bands
[band
])
73 for (j
= 0; j
< wdev
->wiphy
->bands
[band
]->n_channels
;
75 request
->channels
[i
] =
76 &wdev
->wiphy
->bands
[band
]->channels
[j
];
79 request
->n_channels
= n_channels
;
80 request
->ssids
= (void *)(request
->channels
+ n_channels
);
83 memcpy(request
->ssids
[0].ssid
, wdev
->conn
->params
.ssid
,
84 wdev
->conn
->params
.ssid_len
);
85 request
->ssids
[0].ssid_len
= wdev
->conn
->params
.ssid_len
;
87 request
->ifidx
= wdev
->netdev
->ifindex
;
88 request
->wiphy
= &drv
->wiphy
;
90 drv
->scan_req
= request
;
92 err
= drv
->ops
->scan(wdev
->wiphy
, wdev
->netdev
, request
);
94 wdev
->conn
->state
= CFG80211_CONN_SCANNING
;
95 nl80211_send_scan_start(drv
, wdev
->netdev
);
103 static int cfg80211_conn_do_work(struct wireless_dev
*wdev
)
105 struct cfg80211_registered_device
*drv
= wiphy_to_dev(wdev
->wiphy
);
107 struct cfg80211_auth_request auth_req
;
108 struct cfg80211_assoc_request assoc_req
;
111 memset(&u
, 0, sizeof(u
));
116 switch (wdev
->conn
->state
) {
117 case CFG80211_CONN_SCAN_AGAIN
:
118 return cfg80211_conn_scan(wdev
);
119 case CFG80211_CONN_AUTHENTICATE_NEXT
:
120 u
.auth_req
.chan
= wdev
->conn
->params
.channel
;
121 u
.auth_req
.peer_addr
= wdev
->conn
->params
.bssid
;
122 u
.auth_req
.ssid
= wdev
->conn
->params
.ssid
;
123 u
.auth_req
.ssid_len
= wdev
->conn
->params
.ssid_len
;
124 u
.auth_req
.auth_type
= wdev
->conn
->params
.auth_type
;
125 u
.auth_req
.ie
= NULL
;
126 u
.auth_req
.ie_len
= 0;
127 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATING
;
128 BUG_ON(!drv
->ops
->auth
);
129 return drv
->ops
->auth(wdev
->wiphy
, wdev
->netdev
, &u
.auth_req
);
130 case CFG80211_CONN_ASSOCIATE_NEXT
:
131 u
.assoc_req
.chan
= wdev
->conn
->params
.channel
;
132 u
.assoc_req
.peer_addr
= wdev
->conn
->params
.bssid
;
133 u
.assoc_req
.ssid
= wdev
->conn
->params
.ssid
;
134 u
.assoc_req
.ssid_len
= wdev
->conn
->params
.ssid_len
;
135 u
.assoc_req
.ie
= wdev
->conn
->params
.ie
;
136 u
.assoc_req
.ie_len
= wdev
->conn
->params
.ie_len
;
137 u
.assoc_req
.use_mfp
= false;
138 memcpy(&u
.assoc_req
.crypto
, &wdev
->conn
->params
.crypto
,
139 sizeof(u
.assoc_req
.crypto
));
140 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATING
;
141 BUG_ON(!drv
->ops
->assoc
);
142 return drv
->ops
->assoc(wdev
->wiphy
, wdev
->netdev
,
149 void cfg80211_conn_work(struct work_struct
*work
)
151 struct cfg80211_registered_device
*drv
=
152 container_of(work
, struct cfg80211_registered_device
, conn_work
);
153 struct wireless_dev
*wdev
;
156 mutex_lock(&drv
->devlist_mtx
);
158 list_for_each_entry(wdev
, &drv
->netdev_list
, list
) {
159 if (!netif_running(wdev
->netdev
))
161 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
163 if (cfg80211_conn_do_work(wdev
))
164 cfg80211_connect_result(wdev
->netdev
,
165 wdev
->conn
->params
.bssid
,
167 WLAN_STATUS_UNSPECIFIED_FAILURE
,
171 mutex_unlock(&drv
->devlist_mtx
);
175 static bool cfg80211_get_conn_bss(struct wireless_dev
*wdev
)
177 struct cfg80211_registered_device
*drv
= wiphy_to_dev(wdev
->wiphy
);
178 struct cfg80211_bss
*bss
;
179 u16 capa
= WLAN_CAPABILITY_ESS
;
181 if (wdev
->conn
->params
.privacy
)
182 capa
|= WLAN_CAPABILITY_PRIVACY
;
184 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, wdev
->conn
->params
.bssid
,
185 wdev
->conn
->params
.ssid
,
186 wdev
->conn
->params
.ssid_len
,
187 WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_PRIVACY
,
193 memcpy(wdev
->conn
->bssid
, bss
->bssid
, ETH_ALEN
);
194 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
195 wdev
->conn
->params
.channel
= bss
->channel
;
196 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
197 schedule_work(&drv
->conn_work
);
199 cfg80211_put_bss(bss
);
203 void cfg80211_sme_scan_done(struct net_device
*dev
)
205 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
206 struct cfg80211_registered_device
*drv
= wiphy_to_dev(wdev
->wiphy
);
208 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
211 if (WARN_ON(!wdev
->conn
))
214 if (wdev
->conn
->state
!= CFG80211_CONN_SCANNING
&&
215 wdev
->conn
->state
!= CFG80211_CONN_SCAN_AGAIN
)
218 if (!cfg80211_get_conn_bss(wdev
)) {
220 if (wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)
221 schedule_work(&drv
->conn_work
);
223 cfg80211_connect_result(dev
, wdev
->conn
->params
.bssid
,
225 WLAN_STATUS_UNSPECIFIED_FAILURE
,
231 void cfg80211_sme_rx_auth(struct net_device
*dev
, const u8
*buf
, size_t len
)
233 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
234 struct wiphy
*wiphy
= wdev
->wiphy
;
235 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
236 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
237 u16 status_code
= le16_to_cpu(mgmt
->u
.auth
.status_code
);
239 /* should only RX auth frames when connecting */
240 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
243 if (WARN_ON(!wdev
->conn
))
246 if (status_code
== WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG
&&
247 wdev
->conn
->auto_auth
&&
248 wdev
->conn
->params
.auth_type
!= NL80211_AUTHTYPE_NETWORK_EAP
) {
249 /* select automatically between only open, shared, leap */
250 switch (wdev
->conn
->params
.auth_type
) {
251 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
252 wdev
->conn
->params
.auth_type
=
253 NL80211_AUTHTYPE_SHARED_KEY
;
255 case NL80211_AUTHTYPE_SHARED_KEY
:
256 wdev
->conn
->params
.auth_type
=
257 NL80211_AUTHTYPE_NETWORK_EAP
;
261 wdev
->conn
->params
.auth_type
=
262 NL80211_AUTHTYPE_OPEN_SYSTEM
;
265 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
266 schedule_work(&rdev
->conn_work
);
267 } else if (status_code
!= WLAN_STATUS_SUCCESS
)
268 wdev
->sme_state
= CFG80211_SME_IDLE
;
269 else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
270 wdev
->conn
->state
== CFG80211_CONN_AUTHENTICATING
) {
271 wdev
->conn
->state
= CFG80211_CONN_ASSOCIATE_NEXT
;
272 schedule_work(&rdev
->conn_work
);
276 void cfg80211_connect_result(struct net_device
*dev
, const u8
*bssid
,
277 const u8
*req_ie
, size_t req_ie_len
,
278 const u8
*resp_ie
, size_t resp_ie_len
,
279 u16 status
, gfp_t gfp
)
281 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
282 struct cfg80211_bss
*bss
;
283 #ifdef CONFIG_WIRELESS_EXT
284 union iwreq_data wrqu
;
287 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
290 if (wdev
->sme_state
!= CFG80211_SME_CONNECTING
)
293 if (wdev
->current_bss
) {
294 cfg80211_unhold_bss(wdev
->current_bss
);
295 cfg80211_put_bss(wdev
->current_bss
);
296 wdev
->current_bss
= NULL
;
299 if (status
== WLAN_STATUS_SUCCESS
) {
300 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
301 wdev
->ssid
, wdev
->ssid_len
,
303 WLAN_CAPABILITY_ESS
);
308 cfg80211_hold_bss(bss
);
309 wdev
->current_bss
= bss
;
311 wdev
->sme_state
= CFG80211_SME_CONNECTED
;
313 wdev
->sme_state
= CFG80211_SME_IDLE
;
317 wdev
->conn
->state
= CFG80211_CONN_IDLE
;
319 nl80211_send_connect_result(wiphy_to_dev(wdev
->wiphy
), dev
, bssid
,
320 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
,
323 #ifdef CONFIG_WIRELESS_EXT
324 if (req_ie
&& status
== WLAN_STATUS_SUCCESS
) {
325 memset(&wrqu
, 0, sizeof(wrqu
));
326 wrqu
.data
.length
= req_ie_len
;
327 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, req_ie
);
330 if (resp_ie
&& status
== WLAN_STATUS_SUCCESS
) {
331 memset(&wrqu
, 0, sizeof(wrqu
));
332 wrqu
.data
.length
= resp_ie_len
;
333 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
336 memset(&wrqu
, 0, sizeof(wrqu
));
337 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
338 if (bssid
&& status
== WLAN_STATUS_SUCCESS
)
339 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
340 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
343 EXPORT_SYMBOL(cfg80211_connect_result
);
345 void cfg80211_roamed(struct net_device
*dev
, const u8
*bssid
,
346 const u8
*req_ie
, size_t req_ie_len
,
347 const u8
*resp_ie
, size_t resp_ie_len
, gfp_t gfp
)
349 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
350 struct cfg80211_bss
*bss
;
351 #ifdef CONFIG_WIRELESS_EXT
352 union iwreq_data wrqu
;
355 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
358 if (WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
))
361 /* internal error -- how did we get to CONNECTED w/o BSS? */
362 if (WARN_ON(!wdev
->current_bss
)) {
366 cfg80211_unhold_bss(wdev
->current_bss
);
367 cfg80211_put_bss(wdev
->current_bss
);
368 wdev
->current_bss
= NULL
;
370 bss
= cfg80211_get_bss(wdev
->wiphy
, NULL
, bssid
,
371 wdev
->ssid
, wdev
->ssid_len
,
372 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
377 cfg80211_hold_bss(bss
);
378 wdev
->current_bss
= bss
;
380 nl80211_send_roamed(wiphy_to_dev(wdev
->wiphy
), dev
, bssid
,
381 req_ie
, req_ie_len
, resp_ie
, resp_ie_len
, gfp
);
383 #ifdef CONFIG_WIRELESS_EXT
385 memset(&wrqu
, 0, sizeof(wrqu
));
386 wrqu
.data
.length
= req_ie_len
;
387 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, req_ie
);
391 memset(&wrqu
, 0, sizeof(wrqu
));
392 wrqu
.data
.length
= resp_ie_len
;
393 wireless_send_event(dev
, IWEVASSOCRESPIE
, &wrqu
, resp_ie
);
396 memset(&wrqu
, 0, sizeof(wrqu
));
397 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
398 memcpy(wrqu
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
399 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
402 EXPORT_SYMBOL(cfg80211_roamed
);
404 void __cfg80211_disconnected(struct net_device
*dev
, gfp_t gfp
, u8
*ie
,
405 size_t ie_len
, u16 reason
, bool from_ap
)
407 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
408 #ifdef CONFIG_WIRELESS_EXT
409 union iwreq_data wrqu
;
412 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_STATION
))
415 if (WARN_ON(wdev
->sme_state
!= CFG80211_SME_CONNECTED
))
418 if (wdev
->current_bss
) {
419 cfg80211_unhold_bss(wdev
->current_bss
);
420 cfg80211_put_bss(wdev
->current_bss
);
423 wdev
->current_bss
= NULL
;
424 wdev
->sme_state
= CFG80211_SME_IDLE
;
427 kfree(wdev
->conn
->ie
);
428 wdev
->conn
->ie
= NULL
;
431 nl80211_send_disconnected(wiphy_to_dev(wdev
->wiphy
), dev
,
432 reason
, ie
, ie_len
, from_ap
, gfp
);
434 #ifdef CONFIG_WIRELESS_EXT
435 memset(&wrqu
, 0, sizeof(wrqu
));
436 wrqu
.ap_addr
.sa_family
= ARPHRD_ETHER
;
437 wireless_send_event(dev
, SIOCGIWAP
, &wrqu
, NULL
);
441 void cfg80211_disconnected(struct net_device
*dev
, u16 reason
,
442 u8
*ie
, size_t ie_len
, gfp_t gfp
)
444 __cfg80211_disconnected(dev
, gfp
, ie
, ie_len
, reason
, true);
446 EXPORT_SYMBOL(cfg80211_disconnected
);
448 int cfg80211_connect(struct cfg80211_registered_device
*rdev
,
449 struct net_device
*dev
,
450 struct cfg80211_connect_params
*connect
)
453 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
455 if (wdev
->sme_state
!= CFG80211_SME_IDLE
)
458 if (!rdev
->ops
->connect
) {
459 if (!rdev
->ops
->auth
|| !rdev
->ops
->assoc
)
463 wdev
->conn
= kzalloc(sizeof(*wdev
->conn
), GFP_KERNEL
);
467 memset(wdev
->conn
, 0, sizeof(*wdev
->conn
));
470 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
472 memcpy(&wdev
->conn
->params
, connect
, sizeof(*connect
));
473 if (connect
->bssid
) {
474 wdev
->conn
->params
.bssid
= wdev
->conn
->bssid
;
475 memcpy(wdev
->conn
->bssid
, connect
->bssid
, ETH_ALEN
);
479 wdev
->conn
->ie
= kmemdup(connect
->ie
, connect
->ie_len
,
481 wdev
->conn
->params
.ie
= wdev
->conn
->ie
;
486 if (connect
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) {
487 wdev
->conn
->auto_auth
= true;
488 /* start with open system ... should mostly work */
489 wdev
->conn
->params
.auth_type
=
490 NL80211_AUTHTYPE_OPEN_SYSTEM
;
492 wdev
->conn
->auto_auth
= false;
495 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
496 wdev
->ssid_len
= connect
->ssid_len
;
497 wdev
->conn
->params
.ssid
= wdev
->ssid
;
498 wdev
->conn
->params
.ssid_len
= connect
->ssid_len
;
500 /* don't care about result -- but fill bssid & channel */
501 if (!wdev
->conn
->params
.bssid
|| !wdev
->conn
->params
.channel
)
502 cfg80211_get_conn_bss(wdev
);
504 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
506 /* we're good if we have both BSSID and channel */
507 if (wdev
->conn
->params
.bssid
&& wdev
->conn
->params
.channel
) {
508 wdev
->conn
->state
= CFG80211_CONN_AUTHENTICATE_NEXT
;
509 err
= cfg80211_conn_do_work(wdev
);
511 /* otherwise we'll need to scan for the AP first */
512 err
= cfg80211_conn_scan(wdev
);
514 * If we can't scan right now, then we need to scan again
515 * after the current scan finished, since the parameters
516 * changed (unless we find a good AP anyway).
520 wdev
->conn
->state
= CFG80211_CONN_SCAN_AGAIN
;
524 wdev
->sme_state
= CFG80211_SME_IDLE
;
528 wdev
->sme_state
= CFG80211_SME_CONNECTING
;
529 err
= rdev
->ops
->connect(&rdev
->wiphy
, dev
, connect
);
531 wdev
->sme_state
= CFG80211_SME_IDLE
;
535 memcpy(wdev
->ssid
, connect
->ssid
, connect
->ssid_len
);
536 wdev
->ssid_len
= connect
->ssid_len
;
542 int cfg80211_disconnect(struct cfg80211_registered_device
*rdev
,
543 struct net_device
*dev
, u16 reason
)
545 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
548 if (wdev
->sme_state
== CFG80211_SME_IDLE
)
551 if (!rdev
->ops
->disconnect
) {
552 struct cfg80211_deauth_request deauth
;
556 if (WARN_ON(!wdev
->conn
))
559 if (wdev
->sme_state
== CFG80211_SME_CONNECTING
&&
560 (wdev
->conn
->state
== CFG80211_CONN_SCANNING
||
561 wdev
->conn
->state
== CFG80211_CONN_SCAN_AGAIN
)) {
562 wdev
->sme_state
= CFG80211_SME_IDLE
;
566 if (!rdev
->ops
->deauth
)
569 memset(&deauth
, 0, sizeof(deauth
));
571 /* wdev->conn->params.bssid must be set if > SCANNING */
572 memcpy(bssid
, wdev
->conn
->params
.bssid
, ETH_ALEN
);
573 deauth
.peer_addr
= bssid
;
574 deauth
.reason_code
= reason
;
576 err
= rdev
->ops
->deauth(&rdev
->wiphy
, dev
, &deauth
);
580 err
= rdev
->ops
->disconnect(&rdev
->wiphy
, dev
, reason
);
585 if (wdev
->sme_state
== CFG80211_SME_CONNECTED
)
586 __cfg80211_disconnected(dev
, GFP_KERNEL
, NULL
, 0, 0, false);
587 else if (wdev
->sme_state
== CFG80211_SME_CONNECTING
)
588 cfg80211_connect_result(dev
, NULL
, NULL
, 0, NULL
, 0,
589 WLAN_STATUS_UNSPECIFIED_FAILURE
,