sme.c revision f7969969f416e593bcc7dc24abf3f9fd6c27136d
1/* 2 * SME code for cfg80211's connect emulation. 3 * 4 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright (C) 2009 Intel Corporation. All rights reserved. 6 */ 7 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> 15#include "nl80211.h" 16#include "reg.h" 17 18struct cfg80211_conn { 19 struct cfg80211_connect_params params; 20 /* these are sub-states of the _CONNECTING sme_state */ 21 enum { 22 CFG80211_CONN_IDLE, 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, 29 } state; 30 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; 31 u8 *ie; 32 size_t ie_len; 33 bool auto_auth, prev_bssid_valid; 34}; 35 36 37static int cfg80211_conn_scan(struct wireless_dev *wdev) 38{ 39 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 40 struct cfg80211_scan_request *request; 41 int n_channels, err; 42 43 ASSERT_RTNL(); 44 ASSERT_RDEV_LOCK(rdev); 45 ASSERT_WDEV_LOCK(wdev); 46 47 if (rdev->scan_req) 48 return -EBUSY; 49 50 if (wdev->conn->params.channel) { 51 n_channels = 1; 52 } else { 53 enum ieee80211_band band; 54 n_channels = 0; 55 56 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 57 if (!wdev->wiphy->bands[band]) 58 continue; 59 n_channels += wdev->wiphy->bands[band]->n_channels; 60 } 61 } 62 request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) + 63 sizeof(request->channels[0]) * n_channels, 64 GFP_KERNEL); 65 if (!request) 66 return -ENOMEM; 67 68 if (wdev->conn->params.channel) 69 request->channels[0] = wdev->conn->params.channel; 70 else { 71 int i = 0, j; 72 enum ieee80211_band band; 73 74 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 75 if (!wdev->wiphy->bands[band]) 76 continue; 77 for (j = 0; j < wdev->wiphy->bands[band]->n_channels; 78 i++, j++) 79 request->channels[i] = 80 &wdev->wiphy->bands[band]->channels[j]; 81 } 82 } 83 request->n_channels = n_channels; 84 request->ssids = (void *)&request->channels[n_channels]; 85 request->n_ssids = 1; 86 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; 90 91 request->dev = wdev->netdev; 92 request->wiphy = &rdev->wiphy; 93 94 rdev->scan_req = request; 95 96 err = rdev->ops->scan(wdev->wiphy, wdev->netdev, request); 97 if (!err) { 98 wdev->conn->state = CFG80211_CONN_SCANNING; 99 nl80211_send_scan_start(rdev, wdev->netdev); 100 dev_hold(wdev->netdev); 101 } else { 102 rdev->scan_req = NULL; 103 kfree(request); 104 } 105 return err; 106} 107 108static int cfg80211_conn_do_work(struct wireless_dev *wdev) 109{ 110 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 111 struct cfg80211_connect_params *params; 112 const u8 *prev_bssid = NULL; 113 int err; 114 115 ASSERT_WDEV_LOCK(wdev); 116 117 if (!wdev->conn) 118 return 0; 119 120 params = &wdev->conn->params; 121 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, 130 params->bssid, 131 params->ssid, params->ssid_len, 132 NULL, 0, 133 params->key, params->key_len, 134 params->key_idx); 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, 142 prev_bssid, 143 params->ssid, params->ssid_len, 144 params->ie, params->ie_len, 145 false, ¶ms->crypto); 146 if (err) 147 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 148 NULL, 0, 149 WLAN_REASON_DEAUTH_LEAVING); 150 return err; 151 default: 152 return 0; 153 } 154} 155 156void cfg80211_conn_work(struct work_struct *work) 157{ 158 struct cfg80211_registered_device *rdev = 159 container_of(work, struct cfg80211_registered_device, conn_work); 160 struct wireless_dev *wdev; 161 162 rtnl_lock(); 163 cfg80211_lock_rdev(rdev); 164 mutex_lock(&rdev->devlist_mtx); 165 166 list_for_each_entry(wdev, &rdev->netdev_list, list) { 167 wdev_lock(wdev); 168 if (!netif_running(wdev->netdev)) { 169 wdev_unlock(wdev); 170 continue; 171 } 172 if (wdev->sme_state != CFG80211_SME_CONNECTING) { 173 wdev_unlock(wdev); 174 continue; 175 } 176 if (cfg80211_conn_do_work(wdev)) 177 __cfg80211_connect_result( 178 wdev->netdev, 179 wdev->conn->params.bssid, 180 NULL, 0, NULL, 0, 181 WLAN_STATUS_UNSPECIFIED_FAILURE, 182 false, NULL); 183 wdev_unlock(wdev); 184 } 185 186 mutex_unlock(&rdev->devlist_mtx); 187 cfg80211_unlock_rdev(rdev); 188 rtnl_unlock(); 189} 190 191static bool cfg80211_get_conn_bss(struct wireless_dev *wdev) 192{ 193 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 194 struct cfg80211_bss *bss; 195 u16 capa = WLAN_CAPABILITY_ESS; 196 197 ASSERT_WDEV_LOCK(wdev); 198 199 if (wdev->conn->params.privacy) 200 capa |= WLAN_CAPABILITY_PRIVACY; 201 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, 206 capa); 207 if (!bss) 208 return false; 209 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); 215 216 cfg80211_put_bss(bss); 217 return true; 218} 219 220static void __cfg80211_sme_scan_done(struct net_device *dev) 221{ 222 struct wireless_dev *wdev = dev->ieee80211_ptr; 223 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 224 225 ASSERT_WDEV_LOCK(wdev); 226 227 if (wdev->sme_state != CFG80211_SME_CONNECTING) 228 return; 229 230 if (!wdev->conn) 231 return; 232 233 if (wdev->conn->state != CFG80211_CONN_SCANNING && 234 wdev->conn->state != CFG80211_CONN_SCAN_AGAIN) 235 return; 236 237 if (!cfg80211_get_conn_bss(wdev)) { 238 /* not found */ 239 if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) 240 schedule_work(&rdev->conn_work); 241 else 242 __cfg80211_connect_result( 243 wdev->netdev, 244 wdev->conn->params.bssid, 245 NULL, 0, NULL, 0, 246 WLAN_STATUS_UNSPECIFIED_FAILURE, 247 false, NULL); 248 } 249} 250 251void cfg80211_sme_scan_done(struct net_device *dev) 252{ 253 struct wireless_dev *wdev = dev->ieee80211_ptr; 254 255 mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); 256 wdev_lock(wdev); 257 __cfg80211_sme_scan_done(dev); 258 wdev_unlock(wdev); 259 mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); 260} 261 262void cfg80211_sme_rx_auth(struct net_device *dev, 263 const u8 *buf, size_t len) 264{ 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); 270 271 ASSERT_WDEV_LOCK(wdev); 272 273 /* should only RX auth frames when connecting */ 274 if (wdev->sme_state != CFG80211_SME_CONNECTING) 275 return; 276 277 if (WARN_ON(!wdev->conn)) 278 return; 279 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; 289 else 290 wdev->conn->params.auth_type = 291 NL80211_AUTHTYPE_NETWORK_EAP; 292 break; 293 case NL80211_AUTHTYPE_SHARED_KEY: 294 wdev->conn->params.auth_type = 295 NL80211_AUTHTYPE_NETWORK_EAP; 296 break; 297 default: 298 /* huh? */ 299 wdev->conn->params.auth_type = 300 NL80211_AUTHTYPE_OPEN_SYSTEM; 301 break; 302 } 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); 312 } 313} 314 315bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev) 316{ 317 struct wiphy *wiphy = wdev->wiphy; 318 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 319 320 if (WARN_ON(!wdev->conn)) 321 return false; 322 323 if (!wdev->conn->prev_bssid_valid) 324 return false; 325 326 /* 327 * Some stupid APs don't accept reassoc, so we 328 * need to fall back to trying regular assoc. 329 */ 330 wdev->conn->prev_bssid_valid = false; 331 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; 332 schedule_work(&rdev->conn_work); 333 334 return true; 335} 336 337void __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) 342{ 343 struct wireless_dev *wdev = dev->ieee80211_ptr; 344 u8 *country_ie; 345#ifdef CONFIG_WIRELESS_EXT 346 union iwreq_data wrqu; 347#endif 348 349 ASSERT_WDEV_LOCK(wdev); 350 351 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 352 return; 353 354 if (wdev->sme_state != CFG80211_SME_CONNECTING) 355 return; 356 357 nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, 358 bssid, req_ie, req_ie_len, 359 resp_ie, resp_ie_len, 360 status, GFP_KERNEL); 361 362#ifdef CONFIG_WIRELESS_EXT 363 if (wextev) { 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); 368 } 369 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); 374 } 375 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; 382 } 383 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 384 } 385#endif 386 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; 391 } 392 393 if (wdev->conn) 394 wdev->conn->state = CFG80211_CONN_IDLE; 395 396 if (status != WLAN_STATUS_SUCCESS) { 397 wdev->sme_state = CFG80211_SME_IDLE; 398 if (wdev->conn) 399 kfree(wdev->conn->ie); 400 kfree(wdev->conn); 401 wdev->conn = NULL; 402 kfree(wdev->connect_keys); 403 wdev->connect_keys = NULL; 404 wdev->ssid_len = 0; 405 return; 406 } 407 408 if (!bss) 409 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 410 wdev->ssid, wdev->ssid_len, 411 WLAN_CAPABILITY_ESS, 412 WLAN_CAPABILITY_ESS); 413 414 if (WARN_ON(!bss)) 415 return; 416 417 cfg80211_hold_bss(bss_from_pub(bss)); 418 wdev->current_bss = bss_from_pub(bss); 419 420 wdev->sme_state = CFG80211_SME_CONNECTED; 421 cfg80211_upload_connect_keys(wdev); 422 423 country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); 424 425 if (!country_ie) 426 return; 427 428 /* 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 432 */ 433 regulatory_hint_11d(wdev->wiphy, 434 country_ie + 2, 435 country_ie[1]); 436} 437 438void 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) 442{ 443 struct wireless_dev *wdev = dev->ieee80211_ptr; 444 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 445 struct cfg80211_event *ev; 446 unsigned long flags; 447 448 CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); 449 450 ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); 451 if (!ev) 452 return; 453 454 ev->type = EVENT_CONNECT_RESULT; 455 if (bssid) 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; 464 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); 469} 470EXPORT_SYMBOL(cfg80211_connect_result); 471 472void __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) 475{ 476 struct cfg80211_bss *bss; 477#ifdef CONFIG_WIRELESS_EXT 478 union iwreq_data wrqu; 479#endif 480 481 ASSERT_WDEV_LOCK(wdev); 482 483 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 484 return; 485 486 if (wdev->sme_state != CFG80211_SME_CONNECTED) 487 return; 488 489 /* internal error -- how did we get to CONNECTED w/o BSS? */ 490 if (WARN_ON(!wdev->current_bss)) { 491 return; 492 } 493 494 cfg80211_unhold_bss(wdev->current_bss); 495 cfg80211_put_bss(&wdev->current_bss->pub); 496 wdev->current_bss = NULL; 497 498 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 499 wdev->ssid, wdev->ssid_len, 500 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 501 502 if (WARN_ON(!bss)) 503 return; 504 505 cfg80211_hold_bss(bss_from_pub(bss)); 506 wdev->current_bss = bss_from_pub(bss); 507 508 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid, 509 req_ie, req_ie_len, resp_ie, resp_ie_len, 510 GFP_KERNEL); 511 512#ifdef CONFIG_WIRELESS_EXT 513 if (req_ie) { 514 memset(&wrqu, 0, sizeof(wrqu)); 515 wrqu.data.length = req_ie_len; 516 wireless_send_event(wdev->netdev, IWEVASSOCREQIE, 517 &wrqu, req_ie); 518 } 519 520 if (resp_ie) { 521 memset(&wrqu, 0, sizeof(wrqu)); 522 wrqu.data.length = resp_ie_len; 523 wireless_send_event(wdev->netdev, IWEVASSOCRESPIE, 524 &wrqu, resp_ie); 525 } 526 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); 533#endif 534} 535 536void 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) 539{ 540 struct wireless_dev *wdev = dev->ieee80211_ptr; 541 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 542 struct cfg80211_event *ev; 543 unsigned long flags; 544 545 CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); 546 547 ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); 548 if (!ev) 549 return; 550 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); 559 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); 564} 565EXPORT_SYMBOL(cfg80211_roamed); 566 567void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 568 size_t ie_len, u16 reason, bool from_ap) 569{ 570 struct wireless_dev *wdev = dev->ieee80211_ptr; 571 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 572 int i; 573#ifdef CONFIG_WIRELESS_EXT 574 union iwreq_data wrqu; 575#endif 576 577 ASSERT_WDEV_LOCK(wdev); 578 579 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 580 return; 581 582 if (wdev->sme_state != CFG80211_SME_CONNECTED) 583 return; 584 585 if (wdev->current_bss) { 586 cfg80211_unhold_bss(wdev->current_bss); 587 cfg80211_put_bss(&wdev->current_bss->pub); 588 } 589 590 wdev->current_bss = NULL; 591 wdev->sme_state = CFG80211_SME_IDLE; 592 wdev->ssid_len = 0; 593 594 if (wdev->conn) { 595 const u8 *bssid; 596 int ret; 597 598 kfree(wdev->conn->ie); 599 wdev->conn->ie = NULL; 600 kfree(wdev->conn); 601 wdev->conn = NULL; 602 603 /* 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 609 * state. 610 */ 611 for (i = 0; i < MAX_AUTH_BSSES; i++) { 612 if (!wdev->auth_bsses[i]) 613 continue; 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); 618 } 619 } 620 621 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); 622 623 /* 624 * Delete all the keys ... pairwise keys can't really 625 * exist any more anyway, but default keys might. 626 */ 627 if (rdev->ops->del_key) 628 for (i = 0; i < 6; i++) 629 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 630 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); 635#endif 636} 637 638void cfg80211_disconnected(struct net_device *dev, u16 reason, 639 u8 *ie, size_t ie_len, gfp_t gfp) 640{ 641 struct wireless_dev *wdev = dev->ieee80211_ptr; 642 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 643 struct cfg80211_event *ev; 644 unsigned long flags; 645 646 CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); 647 648 ev = kzalloc(sizeof(*ev) + ie_len, gfp); 649 if (!ev) 650 return; 651 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; 657 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); 662} 663EXPORT_SYMBOL(cfg80211_disconnected); 664 665int __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) 670{ 671 struct wireless_dev *wdev = dev->ieee80211_ptr; 672 struct ieee80211_channel *chan; 673 int err; 674 675 ASSERT_WDEV_LOCK(wdev); 676 677 if (wdev->sme_state != CFG80211_SME_IDLE) 678 return -EALREADY; 679 680 chan = rdev_fixed_channel(rdev, wdev); 681 if (chan && chan != connect->channel) 682 return -EBUSY; 683 684 if (WARN_ON(wdev->connect_keys)) { 685 kfree(wdev->connect_keys); 686 wdev->connect_keys = NULL; 687 } 688 689 if (connkeys && connkeys->def >= 0) { 690 int idx; 691 u32 cipher; 692 693 idx = connkeys->def; 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; 701 702 /* 703 * If ciphers are not set (e.g. when going through 704 * iwconfig), we have to set them appropriately here. 705 */ 706 if (connect->crypto.cipher_group == 0) 707 connect->crypto.cipher_group = cipher; 708 709 if (connect->crypto.n_ciphers_pairwise == 0) { 710 connect->crypto.n_ciphers_pairwise = 1; 711 connect->crypto.ciphers_pairwise[0] = cipher; 712 } 713 } 714 } 715 716 if (!rdev->ops->connect) { 717 if (!rdev->ops->auth || !rdev->ops->assoc) 718 return -EOPNOTSUPP; 719 720 if (WARN_ON(wdev->conn)) 721 return -EINPROGRESS; 722 723 wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); 724 if (!wdev->conn) 725 return -ENOMEM; 726 727 /* 728 * Copy all parameters, and treat explicitly IEs, BSSID, SSID. 729 */ 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); 734 } 735 736 if (connect->ie) { 737 wdev->conn->ie = kmemdup(connect->ie, connect->ie_len, 738 GFP_KERNEL); 739 wdev->conn->params.ie = wdev->conn->ie; 740 if (!wdev->conn->ie) { 741 kfree(wdev->conn); 742 wdev->conn = NULL; 743 return -ENOMEM; 744 } 745 } 746 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; 752 } else { 753 wdev->conn->auto_auth = false; 754 } 755 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; 760 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); 764 765 wdev->sme_state = CFG80211_SME_CONNECTING; 766 wdev->connect_keys = connkeys; 767 768 if (prev_bssid) { 769 memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN); 770 wdev->conn->prev_bssid_valid = true; 771 } 772 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); 777 } else { 778 /* otherwise we'll need to scan for the AP first */ 779 err = cfg80211_conn_scan(wdev); 780 /* 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). 784 */ 785 if (err == -EBUSY) { 786 err = 0; 787 wdev->conn->state = CFG80211_CONN_SCAN_AGAIN; 788 } 789 } 790 if (err) { 791 kfree(wdev->conn->ie); 792 kfree(wdev->conn); 793 wdev->conn = NULL; 794 wdev->sme_state = CFG80211_SME_IDLE; 795 wdev->connect_keys = NULL; 796 wdev->ssid_len = 0; 797 } 798 799 return err; 800 } else { 801 wdev->sme_state = CFG80211_SME_CONNECTING; 802 wdev->connect_keys = connkeys; 803 err = rdev->ops->connect(&rdev->wiphy, dev, connect); 804 if (err) { 805 wdev->connect_keys = NULL; 806 wdev->sme_state = CFG80211_SME_IDLE; 807 return err; 808 } 809 810 memcpy(wdev->ssid, connect->ssid, connect->ssid_len); 811 wdev->ssid_len = connect->ssid_len; 812 813 return 0; 814 } 815} 816 817int cfg80211_connect(struct cfg80211_registered_device *rdev, 818 struct net_device *dev, 819 struct cfg80211_connect_params *connect, 820 struct cfg80211_cached_keys *connkeys) 821{ 822 int err; 823 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); 829 830 return err; 831} 832 833int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, 834 struct net_device *dev, u16 reason, bool wextev) 835{ 836 struct wireless_dev *wdev = dev->ieee80211_ptr; 837 int err; 838 839 ASSERT_WDEV_LOCK(wdev); 840 841 if (wdev->sme_state == CFG80211_SME_IDLE) 842 return -EINVAL; 843 844 kfree(wdev->connect_keys); 845 wdev->connect_keys = NULL; 846 847 if (!rdev->ops->disconnect) { 848 if (!rdev->ops->deauth) 849 return -EOPNOTSUPP; 850 851 /* was it connected by userspace SME? */ 852 if (!wdev->conn) { 853 cfg80211_mlme_down(rdev, dev); 854 return 0; 855 } 856 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); 862 kfree(wdev->conn); 863 wdev->conn = NULL; 864 wdev->ssid_len = 0; 865 return 0; 866 } 867 868 /* wdev->conn->params.bssid must be set if > SCANNING */ 869 err = __cfg80211_mlme_deauth(rdev, dev, 870 wdev->conn->params.bssid, 871 NULL, 0, reason); 872 if (err) 873 return err; 874 } else { 875 err = rdev->ops->disconnect(&rdev->wiphy, dev, reason); 876 if (err) 877 return err; 878 } 879 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, 885 wextev, NULL); 886 887 return 0; 888} 889 890int cfg80211_disconnect(struct cfg80211_registered_device *rdev, 891 struct net_device *dev, 892 u16 reason, bool wextev) 893{ 894 int err; 895 896 wdev_lock(dev->ieee80211_ptr); 897 err = __cfg80211_disconnect(rdev, dev, reason, wextev); 898 wdev_unlock(dev->ieee80211_ptr); 899 900 return err; 901} 902 903void cfg80211_sme_disassoc(struct net_device *dev, int idx) 904{ 905 struct wireless_dev *wdev = dev->ieee80211_ptr; 906 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 907 u8 bssid[ETH_ALEN]; 908 909 ASSERT_WDEV_LOCK(wdev); 910 911 if (!wdev->conn) 912 return; 913 914 if (wdev->conn->state == CFG80211_CONN_IDLE) 915 return; 916 917 /* 918 * Ok, so the association was made by this SME -- we don't 919 * want it any more so deauthenticate too. 920 */ 921 922 if (!wdev->auth_bsses[idx]) 923 return; 924 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; 932 } 933} 934