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