1 /* 2 * cfg80211 MLME SAP interface 3 * 4 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/netdevice.h> 10 #include <linux/nl80211.h> 11 #include <linux/wireless.h> 12 #include <net/cfg80211.h> 13 #include <net/iw_handler.h> 14 #include "core.h" 15 #include "nl80211.h" 16 17 void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) 18 { 19 struct wireless_dev *wdev = dev->ieee80211_ptr; 20 struct wiphy *wiphy = wdev->wiphy; 21 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 22 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; 23 u8 *bssid = mgmt->bssid; 24 int i; 25 u16 status = le16_to_cpu(mgmt->u.auth.status_code); 26 bool done = false; 27 28 wdev_lock(wdev); 29 30 for (i = 0; i < MAX_AUTH_BSSES; i++) { 31 if (wdev->authtry_bsses[i] && 32 memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, 33 ETH_ALEN) == 0) { 34 if (status == WLAN_STATUS_SUCCESS) { 35 wdev->auth_bsses[i] = wdev->authtry_bsses[i]; 36 } else { 37 cfg80211_unhold_bss(wdev->authtry_bsses[i]); 38 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); 39 } 40 wdev->authtry_bsses[i] = NULL; 41 done = true; 42 break; 43 } 44 } 45 46 WARN_ON(!done); 47 48 nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); 49 cfg80211_sme_rx_auth(dev, buf, len); 50 51 wdev_unlock(wdev); 52 } 53 EXPORT_SYMBOL(cfg80211_send_rx_auth); 54 55 void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) 56 { 57 u16 status_code; 58 struct wireless_dev *wdev = dev->ieee80211_ptr; 59 struct wiphy *wiphy = wdev->wiphy; 60 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 61 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; 62 u8 *ie = mgmt->u.assoc_resp.variable; 63 int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); 64 struct cfg80211_internal_bss *bss = NULL; 65 66 wdev_lock(wdev); 67 68 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 69 70 /* 71 * This is a bit of a hack, we don't notify userspace of 72 * a (re-)association reply if we tried to send a reassoc 73 * and got a reject -- we only try again with an assoc 74 * frame instead of reassoc. 75 */ 76 if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && 77 cfg80211_sme_failed_reassoc(wdev)) 78 goto out; 79 80 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); 81 82 if (status_code == WLAN_STATUS_SUCCESS) { 83 for (i = 0; i < MAX_AUTH_BSSES; i++) { 84 if (!wdev->auth_bsses[i]) 85 continue; 86 if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, 87 ETH_ALEN) == 0) { 88 bss = wdev->auth_bsses[i]; 89 wdev->auth_bsses[i] = NULL; 90 /* additional reference to drop hold */ 91 cfg80211_ref_bss(bss); 92 break; 93 } 94 } 95 96 /* 97 * We might be coming here because the driver reported 98 * a successful association at the same time as the 99 * user requested a deauth. In that case, we will have 100 * removed the BSS from the auth_bsses list due to the 101 * deauth request when the assoc response makes it. If 102 * the two code paths acquire the lock the other way 103 * around, that's just the standard situation of a 104 * deauth being requested while connected. 105 */ 106 if (!bss) 107 goto out; 108 } else if (wdev->conn) { 109 cfg80211_sme_failed_assoc(wdev); 110 /* 111 * do not call connect_result() now because the 112 * sme will schedule work that does it later. 113 */ 114 goto out; 115 } 116 117 if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { 118 /* 119 * This is for the userspace SME, the CONNECTING 120 * state will be changed to CONNECTED by 121 * __cfg80211_connect_result() below. 122 */ 123 wdev->sme_state = CFG80211_SME_CONNECTING; 124 } 125 126 /* this consumes one bss reference (unless bss is NULL) */ 127 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, 128 status_code, 129 status_code == WLAN_STATUS_SUCCESS, 130 bss ? &bss->pub : NULL); 131 /* drop hold now, and also reference acquired above */ 132 if (bss) { 133 cfg80211_unhold_bss(bss); 134 cfg80211_put_bss(&bss->pub); 135 } 136 137 out: 138 wdev_unlock(wdev); 139 } 140 EXPORT_SYMBOL(cfg80211_send_rx_assoc); 141 142 void __cfg80211_send_deauth(struct net_device *dev, 143 const u8 *buf, size_t len) 144 { 145 struct wireless_dev *wdev = dev->ieee80211_ptr; 146 struct wiphy *wiphy = wdev->wiphy; 147 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 148 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; 149 const u8 *bssid = mgmt->bssid; 150 int i; 151 bool found = false; 152 153 ASSERT_WDEV_LOCK(wdev); 154 155 if (wdev->current_bss && 156 memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { 157 cfg80211_unhold_bss(wdev->current_bss); 158 cfg80211_put_bss(&wdev->current_bss->pub); 159 wdev->current_bss = NULL; 160 found = true; 161 } else for (i = 0; i < MAX_AUTH_BSSES; i++) { 162 if (wdev->auth_bsses[i] && 163 memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { 164 cfg80211_unhold_bss(wdev->auth_bsses[i]); 165 cfg80211_put_bss(&wdev->auth_bsses[i]->pub); 166 wdev->auth_bsses[i] = NULL; 167 found = true; 168 break; 169 } 170 if (wdev->authtry_bsses[i] && 171 memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { 172 cfg80211_unhold_bss(wdev->authtry_bsses[i]); 173 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); 174 wdev->authtry_bsses[i] = NULL; 175 found = true; 176 break; 177 } 178 } 179 180 if (!found) 181 return; 182 183 nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); 184 185 if (wdev->sme_state == CFG80211_SME_CONNECTED) { 186 u16 reason_code; 187 bool from_ap; 188 189 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); 190 191 from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; 192 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); 193 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { 194 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, 195 WLAN_STATUS_UNSPECIFIED_FAILURE, 196 false, NULL); 197 } 198 } 199 EXPORT_SYMBOL(__cfg80211_send_deauth); 200 201 void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) 202 { 203 struct wireless_dev *wdev = dev->ieee80211_ptr; 204 205 wdev_lock(wdev); 206 __cfg80211_send_deauth(dev, buf, len); 207 wdev_unlock(wdev); 208 } 209 EXPORT_SYMBOL(cfg80211_send_deauth); 210 211 void __cfg80211_send_disassoc(struct net_device *dev, 212 const u8 *buf, size_t len) 213 { 214 struct wireless_dev *wdev = dev->ieee80211_ptr; 215 struct wiphy *wiphy = wdev->wiphy; 216 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 217 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; 218 const u8 *bssid = mgmt->bssid; 219 int i; 220 u16 reason_code; 221 bool from_ap; 222 bool done = false; 223 224 ASSERT_WDEV_LOCK(wdev); 225 226 nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); 227 228 if (wdev->sme_state != CFG80211_SME_CONNECTED) 229 return; 230 231 if (wdev->current_bss && 232 memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { 233 for (i = 0; i < MAX_AUTH_BSSES; i++) { 234 if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) 235 continue; 236 wdev->auth_bsses[i] = wdev->current_bss; 237 wdev->current_bss = NULL; 238 done = true; 239 cfg80211_sme_disassoc(dev, i); 240 break; 241 } 242 WARN_ON(!done); 243 } else 244 WARN_ON(1); 245 246 247 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); 248 249 from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; 250 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); 251 } 252 EXPORT_SYMBOL(__cfg80211_send_disassoc); 253 254 void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) 255 { 256 struct wireless_dev *wdev = dev->ieee80211_ptr; 257 258 wdev_lock(wdev); 259 __cfg80211_send_disassoc(dev, buf, len); 260 wdev_unlock(wdev); 261 } 262 EXPORT_SYMBOL(cfg80211_send_disassoc); 263 264 static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) 265 { 266 int i; 267 bool done = false; 268 269 ASSERT_WDEV_LOCK(wdev); 270 271 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { 272 if (wdev->authtry_bsses[i] && 273 memcmp(wdev->authtry_bsses[i]->pub.bssid, 274 addr, ETH_ALEN) == 0) { 275 cfg80211_unhold_bss(wdev->authtry_bsses[i]); 276 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); 277 wdev->authtry_bsses[i] = NULL; 278 done = true; 279 break; 280 } 281 } 282 283 WARN_ON(!done); 284 } 285 286 void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) 287 { 288 __cfg80211_auth_remove(dev->ieee80211_ptr, addr); 289 } 290 EXPORT_SYMBOL(__cfg80211_auth_canceled); 291 292 void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) 293 { 294 struct wireless_dev *wdev = dev->ieee80211_ptr; 295 struct wiphy *wiphy = wdev->wiphy; 296 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 297 298 wdev_lock(wdev); 299 300 nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); 301 if (wdev->sme_state == CFG80211_SME_CONNECTING) 302 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, 303 WLAN_STATUS_UNSPECIFIED_FAILURE, 304 false, NULL); 305 306 __cfg80211_auth_remove(wdev, addr); 307 308 wdev_unlock(wdev); 309 } 310 EXPORT_SYMBOL(cfg80211_send_auth_timeout); 311 312 void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) 313 { 314 struct wireless_dev *wdev = dev->ieee80211_ptr; 315 struct wiphy *wiphy = wdev->wiphy; 316 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 317 int i; 318 bool done = false; 319 320 wdev_lock(wdev); 321 322 nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); 323 if (wdev->sme_state == CFG80211_SME_CONNECTING) 324 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, 325 WLAN_STATUS_UNSPECIFIED_FAILURE, 326 false, NULL); 327 328 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { 329 if (wdev->auth_bsses[i] && 330 memcmp(wdev->auth_bsses[i]->pub.bssid, 331 addr, ETH_ALEN) == 0) { 332 cfg80211_unhold_bss(wdev->auth_bsses[i]); 333 cfg80211_put_bss(&wdev->auth_bsses[i]->pub); 334 wdev->auth_bsses[i] = NULL; 335 done = true; 336 break; 337 } 338 } 339 340 WARN_ON(!done); 341 342 wdev_unlock(wdev); 343 } 344 EXPORT_SYMBOL(cfg80211_send_assoc_timeout); 345 346 void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, 347 enum nl80211_key_type key_type, int key_id, 348 const u8 *tsc, gfp_t gfp) 349 { 350 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; 351 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 352 #ifdef CONFIG_CFG80211_WEXT 353 union iwreq_data wrqu; 354 char *buf = kmalloc(128, gfp); 355 356 if (buf) { 357 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(" 358 "keyid=%d %scast addr=%pM)", key_id, 359 key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni", 360 addr); 361 memset(&wrqu, 0, sizeof(wrqu)); 362 wrqu.data.length = strlen(buf); 363 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); 364 kfree(buf); 365 } 366 #endif 367 368 nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp); 369 } 370 EXPORT_SYMBOL(cfg80211_michael_mic_failure); 371 372 /* some MLME handling for userspace SME */ 373 int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 374 struct net_device *dev, 375 struct ieee80211_channel *chan, 376 enum nl80211_auth_type auth_type, 377 const u8 *bssid, 378 const u8 *ssid, int ssid_len, 379 const u8 *ie, int ie_len, 380 const u8 *key, int key_len, int key_idx) 381 { 382 struct wireless_dev *wdev = dev->ieee80211_ptr; 383 struct cfg80211_auth_request req; 384 struct cfg80211_internal_bss *bss; 385 int i, err, slot = -1, nfree = 0; 386 387 ASSERT_WDEV_LOCK(wdev); 388 389 if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) 390 if (!key || !key_len || key_idx < 0 || key_idx > 4) 391 return -EINVAL; 392 393 if (wdev->current_bss && 394 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) 395 return -EALREADY; 396 397 for (i = 0; i < MAX_AUTH_BSSES; i++) { 398 if (wdev->authtry_bsses[i] && 399 memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, 400 ETH_ALEN) == 0) 401 return -EALREADY; 402 if (wdev->auth_bsses[i] && 403 memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, 404 ETH_ALEN) == 0) 405 return -EALREADY; 406 } 407 408 memset(&req, 0, sizeof(req)); 409 410 req.ie = ie; 411 req.ie_len = ie_len; 412 req.auth_type = auth_type; 413 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 414 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 415 req.key = key; 416 req.key_len = key_len; 417 req.key_idx = key_idx; 418 if (!req.bss) 419 return -ENOENT; 420 421 bss = bss_from_pub(req.bss); 422 423 for (i = 0; i < MAX_AUTH_BSSES; i++) { 424 if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) { 425 slot = i; 426 nfree++; 427 } 428 } 429 430 /* we need one free slot for disassoc and one for this auth */ 431 if (nfree < 2) { 432 err = -ENOSPC; 433 goto out; 434 } 435 436 wdev->authtry_bsses[slot] = bss; 437 cfg80211_hold_bss(bss); 438 439 err = rdev->ops->auth(&rdev->wiphy, dev, &req); 440 if (err) { 441 wdev->authtry_bsses[slot] = NULL; 442 cfg80211_unhold_bss(bss); 443 } 444 445 out: 446 if (err) 447 cfg80211_put_bss(req.bss); 448 return err; 449 } 450 451 int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 452 struct net_device *dev, struct ieee80211_channel *chan, 453 enum nl80211_auth_type auth_type, const u8 *bssid, 454 const u8 *ssid, int ssid_len, 455 const u8 *ie, int ie_len, 456 const u8 *key, int key_len, int key_idx) 457 { 458 int err; 459 460 wdev_lock(dev->ieee80211_ptr); 461 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 462 ssid, ssid_len, ie, ie_len, 463 key, key_len, key_idx); 464 wdev_unlock(dev->ieee80211_ptr); 465 466 return err; 467 } 468 469 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 470 struct net_device *dev, 471 struct ieee80211_channel *chan, 472 const u8 *bssid, const u8 *prev_bssid, 473 const u8 *ssid, int ssid_len, 474 const u8 *ie, int ie_len, bool use_mfp, 475 struct cfg80211_crypto_settings *crypt) 476 { 477 struct wireless_dev *wdev = dev->ieee80211_ptr; 478 struct cfg80211_assoc_request req; 479 struct cfg80211_internal_bss *bss; 480 int i, err, slot = -1; 481 bool was_connected = false; 482 483 ASSERT_WDEV_LOCK(wdev); 484 485 memset(&req, 0, sizeof(req)); 486 487 if (wdev->current_bss && prev_bssid && 488 memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) { 489 /* 490 * Trying to reassociate: Allow this to proceed and let the old 491 * association to be dropped when the new one is completed. 492 */ 493 if (wdev->sme_state == CFG80211_SME_CONNECTED) { 494 was_connected = true; 495 wdev->sme_state = CFG80211_SME_CONNECTING; 496 } 497 } else if (wdev->current_bss) 498 return -EALREADY; 499 500 req.ie = ie; 501 req.ie_len = ie_len; 502 memcpy(&req.crypto, crypt, sizeof(req.crypto)); 503 req.use_mfp = use_mfp; 504 req.prev_bssid = prev_bssid; 505 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 506 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 507 if (!req.bss) { 508 if (was_connected) 509 wdev->sme_state = CFG80211_SME_CONNECTED; 510 return -ENOENT; 511 } 512 513 bss = bss_from_pub(req.bss); 514 515 for (i = 0; i < MAX_AUTH_BSSES; i++) { 516 if (bss == wdev->auth_bsses[i]) { 517 slot = i; 518 break; 519 } 520 } 521 522 if (slot < 0) { 523 err = -ENOTCONN; 524 goto out; 525 } 526 527 err = rdev->ops->assoc(&rdev->wiphy, dev, &req); 528 out: 529 if (err && was_connected) 530 wdev->sme_state = CFG80211_SME_CONNECTED; 531 /* still a reference in wdev->auth_bsses[slot] */ 532 cfg80211_put_bss(req.bss); 533 return err; 534 } 535 536 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 537 struct net_device *dev, 538 struct ieee80211_channel *chan, 539 const u8 *bssid, const u8 *prev_bssid, 540 const u8 *ssid, int ssid_len, 541 const u8 *ie, int ie_len, bool use_mfp, 542 struct cfg80211_crypto_settings *crypt) 543 { 544 struct wireless_dev *wdev = dev->ieee80211_ptr; 545 int err; 546 547 wdev_lock(wdev); 548 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, 549 ssid, ssid_len, ie, ie_len, use_mfp, crypt); 550 wdev_unlock(wdev); 551 552 return err; 553 } 554 555 int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 556 struct net_device *dev, const u8 *bssid, 557 const u8 *ie, int ie_len, u16 reason) 558 { 559 struct wireless_dev *wdev = dev->ieee80211_ptr; 560 struct cfg80211_deauth_request req; 561 int i; 562 563 ASSERT_WDEV_LOCK(wdev); 564 565 memset(&req, 0, sizeof(req)); 566 req.reason_code = reason; 567 req.ie = ie; 568 req.ie_len = ie_len; 569 if (wdev->current_bss && 570 memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { 571 req.bss = &wdev->current_bss->pub; 572 } else for (i = 0; i < MAX_AUTH_BSSES; i++) { 573 if (wdev->auth_bsses[i] && 574 memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) { 575 req.bss = &wdev->auth_bsses[i]->pub; 576 break; 577 } 578 if (wdev->authtry_bsses[i] && 579 memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) { 580 req.bss = &wdev->authtry_bsses[i]->pub; 581 break; 582 } 583 } 584 585 if (!req.bss) 586 return -ENOTCONN; 587 588 return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); 589 } 590 591 int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 592 struct net_device *dev, const u8 *bssid, 593 const u8 *ie, int ie_len, u16 reason) 594 { 595 struct wireless_dev *wdev = dev->ieee80211_ptr; 596 int err; 597 598 wdev_lock(wdev); 599 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); 600 wdev_unlock(wdev); 601 602 return err; 603 } 604 605 static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 606 struct net_device *dev, const u8 *bssid, 607 const u8 *ie, int ie_len, u16 reason) 608 { 609 struct wireless_dev *wdev = dev->ieee80211_ptr; 610 struct cfg80211_disassoc_request req; 611 612 ASSERT_WDEV_LOCK(wdev); 613 614 if (wdev->sme_state != CFG80211_SME_CONNECTED) 615 return -ENOTCONN; 616 617 if (WARN_ON(!wdev->current_bss)) 618 return -ENOTCONN; 619 620 memset(&req, 0, sizeof(req)); 621 req.reason_code = reason; 622 req.ie = ie; 623 req.ie_len = ie_len; 624 if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) 625 req.bss = &wdev->current_bss->pub; 626 else 627 return -ENOTCONN; 628 629 return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev); 630 } 631 632 int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 633 struct net_device *dev, const u8 *bssid, 634 const u8 *ie, int ie_len, u16 reason) 635 { 636 struct wireless_dev *wdev = dev->ieee80211_ptr; 637 int err; 638 639 wdev_lock(wdev); 640 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); 641 wdev_unlock(wdev); 642 643 return err; 644 } 645 646 void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, 647 struct net_device *dev) 648 { 649 struct wireless_dev *wdev = dev->ieee80211_ptr; 650 struct cfg80211_deauth_request req; 651 int i; 652 653 ASSERT_WDEV_LOCK(wdev); 654 655 if (!rdev->ops->deauth) 656 return; 657 658 memset(&req, 0, sizeof(req)); 659 req.reason_code = WLAN_REASON_DEAUTH_LEAVING; 660 req.ie = NULL; 661 req.ie_len = 0; 662 663 if (wdev->current_bss) { 664 req.bss = &wdev->current_bss->pub; 665 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); 666 if (wdev->current_bss) { 667 cfg80211_unhold_bss(wdev->current_bss); 668 cfg80211_put_bss(&wdev->current_bss->pub); 669 wdev->current_bss = NULL; 670 } 671 } 672 673 for (i = 0; i < MAX_AUTH_BSSES; i++) { 674 if (wdev->auth_bsses[i]) { 675 req.bss = &wdev->auth_bsses[i]->pub; 676 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); 677 if (wdev->auth_bsses[i]) { 678 cfg80211_unhold_bss(wdev->auth_bsses[i]); 679 cfg80211_put_bss(&wdev->auth_bsses[i]->pub); 680 wdev->auth_bsses[i] = NULL; 681 } 682 } 683 if (wdev->authtry_bsses[i]) { 684 req.bss = &wdev->authtry_bsses[i]->pub; 685 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); 686 if (wdev->authtry_bsses[i]) { 687 cfg80211_unhold_bss(wdev->authtry_bsses[i]); 688 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); 689 wdev->authtry_bsses[i] = NULL; 690 } 691 } 692 } 693 } 694 695 void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie, 696 struct ieee80211_channel *chan, 697 enum nl80211_channel_type channel_type, 698 unsigned int duration, gfp_t gfp) 699 { 700 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; 701 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 702 703 nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type, 704 duration, gfp); 705 } 706 EXPORT_SYMBOL(cfg80211_ready_on_channel); 707 708 void cfg80211_remain_on_channel_expired(struct net_device *dev, 709 u64 cookie, 710 struct ieee80211_channel *chan, 711 enum nl80211_channel_type channel_type, 712 gfp_t gfp) 713 { 714 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; 715 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 716 717 nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan, 718 channel_type, gfp); 719 } 720 EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); 721 722 void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, 723 struct station_info *sinfo, gfp_t gfp) 724 { 725 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; 726 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 727 728 nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); 729 } 730 EXPORT_SYMBOL(cfg80211_new_sta); 731 732 struct cfg80211_action_registration { 733 struct list_head list; 734 735 u32 nlpid; 736 737 int match_len; 738 739 u8 match[]; 740 }; 741 742 int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, 743 const u8 *match_data, int match_len) 744 { 745 struct cfg80211_action_registration *reg, *nreg; 746 int err = 0; 747 748 nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); 749 if (!nreg) 750 return -ENOMEM; 751 752 spin_lock_bh(&wdev->action_registrations_lock); 753 754 list_for_each_entry(reg, &wdev->action_registrations, list) { 755 int mlen = min(match_len, reg->match_len); 756 757 if (memcmp(reg->match, match_data, mlen) == 0) { 758 err = -EALREADY; 759 break; 760 } 761 } 762 763 if (err) { 764 kfree(nreg); 765 goto out; 766 } 767 768 memcpy(nreg->match, match_data, match_len); 769 nreg->match_len = match_len; 770 nreg->nlpid = snd_pid; 771 list_add(&nreg->list, &wdev->action_registrations); 772 773 out: 774 spin_unlock_bh(&wdev->action_registrations_lock); 775 return err; 776 } 777 778 void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) 779 { 780 struct cfg80211_action_registration *reg, *tmp; 781 782 spin_lock_bh(&wdev->action_registrations_lock); 783 784 list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { 785 if (reg->nlpid == nlpid) { 786 list_del(®->list); 787 kfree(reg); 788 } 789 } 790 791 spin_unlock_bh(&wdev->action_registrations_lock); 792 } 793 794 void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) 795 { 796 struct cfg80211_action_registration *reg, *tmp; 797 798 spin_lock_bh(&wdev->action_registrations_lock); 799 800 list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { 801 list_del(®->list); 802 kfree(reg); 803 } 804 805 spin_unlock_bh(&wdev->action_registrations_lock); 806 } 807 808 int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, 809 struct net_device *dev, 810 struct ieee80211_channel *chan, 811 enum nl80211_channel_type channel_type, 812 const u8 *buf, size_t len, u64 *cookie) 813 { 814 struct wireless_dev *wdev = dev->ieee80211_ptr; 815 const struct ieee80211_mgmt *mgmt; 816 817 if (rdev->ops->action == NULL) 818 return -EOPNOTSUPP; 819 if (len < 24 + 1) 820 return -EINVAL; 821 822 mgmt = (const struct ieee80211_mgmt *) buf; 823 if (!ieee80211_is_action(mgmt->frame_control)) 824 return -EINVAL; 825 if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { 826 /* Verify that we are associated with the destination AP */ 827 if (!wdev->current_bss || 828 memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, 829 ETH_ALEN) != 0 || 830 memcmp(wdev->current_bss->pub.bssid, mgmt->da, 831 ETH_ALEN) != 0) 832 return -ENOTCONN; 833 } 834 835 if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) 836 return -EINVAL; 837 838 /* Transmit the Action frame as requested by user space */ 839 return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, 840 buf, len, cookie); 841 } 842 843 bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, 844 size_t len, gfp_t gfp) 845 { 846 struct wireless_dev *wdev = dev->ieee80211_ptr; 847 struct wiphy *wiphy = wdev->wiphy; 848 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 849 struct cfg80211_action_registration *reg; 850 const u8 *action_data; 851 int action_data_len; 852 bool result = false; 853 854 /* frame length - min size excluding category */ 855 action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); 856 857 /* action data starts with category */ 858 action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; 859 860 spin_lock_bh(&wdev->action_registrations_lock); 861 862 list_for_each_entry(reg, &wdev->action_registrations, list) { 863 if (reg->match_len > action_data_len) 864 continue; 865 866 if (memcmp(reg->match, action_data, reg->match_len)) 867 continue; 868 869 /* found match! */ 870 871 /* Indicate the received Action frame to user space */ 872 if (nl80211_send_action(rdev, dev, reg->nlpid, freq, 873 buf, len, gfp)) 874 continue; 875 876 result = true; 877 break; 878 } 879 880 spin_unlock_bh(&wdev->action_registrations_lock); 881 882 return result; 883 } 884 EXPORT_SYMBOL(cfg80211_rx_action); 885 886 void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, 887 const u8 *buf, size_t len, bool ack, gfp_t gfp) 888 { 889 struct wireless_dev *wdev = dev->ieee80211_ptr; 890 struct wiphy *wiphy = wdev->wiphy; 891 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 892 893 /* Indicate TX status of the Action frame to user space */ 894 nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); 895 } 896 EXPORT_SYMBOL(cfg80211_action_tx_status); 897