1 /* 2 * cfg80211 scan result handling 3 * 4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 5 */ 6 #include <linux/kernel.h> 7 #include <linux/module.h> 8 #include <linux/netdevice.h> 9 #include <linux/wireless.h> 10 #include <linux/nl80211.h> 11 #include <linux/etherdevice.h> 12 #include <net/arp.h> 13 #include <net/cfg80211.h> 14 #include <net/iw_handler.h> 15 #include "core.h" 16 #include "nl80211.h" 17 #include "wext-compat.h" 18 19 #define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) 20 21 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) 22 { 23 struct cfg80211_scan_request *request; 24 struct net_device *dev; 25 #ifdef CONFIG_CFG80211_WEXT 26 union iwreq_data wrqu; 27 #endif 28 29 ASSERT_RDEV_LOCK(rdev); 30 31 request = rdev->scan_req; 32 33 if (!request) 34 return; 35 36 dev = request->dev; 37 38 /* 39 * This must be before sending the other events! 40 * Otherwise, wpa_supplicant gets completely confused with 41 * wext events. 42 */ 43 cfg80211_sme_scan_done(dev); 44 45 if (request->aborted) 46 nl80211_send_scan_aborted(rdev, dev); 47 else 48 nl80211_send_scan_done(rdev, dev); 49 50 #ifdef CONFIG_CFG80211_WEXT 51 if (!request->aborted) { 52 memset(&wrqu, 0, sizeof(wrqu)); 53 54 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); 55 } 56 #endif 57 58 dev_put(dev); 59 60 rdev->scan_req = NULL; 61 62 /* 63 * OK. If this is invoked with "leak" then we can't 64 * free this ... but we've cleaned it up anyway. The 65 * driver failed to call the scan_done callback, so 66 * all bets are off, it might still be trying to use 67 * the scan request or not ... if it accesses the dev 68 * in there (it shouldn't anyway) then it may crash. 69 */ 70 if (!leak) 71 kfree(request); 72 } 73 74 void __cfg80211_scan_done(struct work_struct *wk) 75 { 76 struct cfg80211_registered_device *rdev; 77 78 rdev = container_of(wk, struct cfg80211_registered_device, 79 scan_done_wk); 80 81 cfg80211_lock_rdev(rdev); 82 ___cfg80211_scan_done(rdev, false); 83 cfg80211_unlock_rdev(rdev); 84 } 85 86 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 87 { 88 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 89 90 request->aborted = aborted; 91 queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); 92 } 93 EXPORT_SYMBOL(cfg80211_scan_done); 94 95 static void bss_release(struct kref *ref) 96 { 97 struct cfg80211_internal_bss *bss; 98 99 bss = container_of(ref, struct cfg80211_internal_bss, ref); 100 if (bss->pub.free_priv) 101 bss->pub.free_priv(&bss->pub); 102 103 if (bss->beacon_ies_allocated) 104 kfree(bss->pub.beacon_ies); 105 if (bss->proberesp_ies_allocated) 106 kfree(bss->pub.proberesp_ies); 107 108 BUG_ON(atomic_read(&bss->hold)); 109 110 kfree(bss); 111 } 112 113 /* must hold dev->bss_lock! */ 114 void cfg80211_bss_age(struct cfg80211_registered_device *dev, 115 unsigned long age_secs) 116 { 117 struct cfg80211_internal_bss *bss; 118 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); 119 120 list_for_each_entry(bss, &dev->bss_list, list) { 121 bss->ts -= age_jiffies; 122 } 123 } 124 125 /* must hold dev->bss_lock! */ 126 void cfg80211_bss_expire(struct cfg80211_registered_device *dev) 127 { 128 struct cfg80211_internal_bss *bss, *tmp; 129 bool expired = false; 130 131 list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) { 132 if (atomic_read(&bss->hold)) 133 continue; 134 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) 135 continue; 136 list_del(&bss->list); 137 rb_erase(&bss->rbn, &dev->bss_tree); 138 kref_put(&bss->ref, bss_release); 139 expired = true; 140 } 141 142 if (expired) 143 dev->bss_generation++; 144 } 145 146 const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) 147 { 148 while (len > 2 && ies[0] != eid) { 149 len -= ies[1] + 2; 150 ies += ies[1] + 2; 151 } 152 if (len < 2) 153 return NULL; 154 if (len < 2 + ies[1]) 155 return NULL; 156 return ies; 157 } 158 EXPORT_SYMBOL(cfg80211_find_ie); 159 160 static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) 161 { 162 const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); 163 const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); 164 int r; 165 166 if (!ie1 && !ie2) 167 return 0; 168 if (!ie1 || !ie2) 169 return -1; 170 171 r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1])); 172 if (r == 0 && ie1[1] != ie2[1]) 173 return ie2[1] - ie1[1]; 174 return r; 175 } 176 177 static bool is_bss(struct cfg80211_bss *a, 178 const u8 *bssid, 179 const u8 *ssid, size_t ssid_len) 180 { 181 const u8 *ssidie; 182 183 if (bssid && compare_ether_addr(a->bssid, bssid)) 184 return false; 185 186 if (!ssid) 187 return true; 188 189 ssidie = cfg80211_find_ie(WLAN_EID_SSID, 190 a->information_elements, 191 a->len_information_elements); 192 if (!ssidie) 193 return false; 194 if (ssidie[1] != ssid_len) 195 return false; 196 return memcmp(ssidie + 2, ssid, ssid_len) == 0; 197 } 198 199 static bool is_mesh(struct cfg80211_bss *a, 200 const u8 *meshid, size_t meshidlen, 201 const u8 *meshcfg) 202 { 203 const u8 *ie; 204 205 if (!is_zero_ether_addr(a->bssid)) 206 return false; 207 208 ie = cfg80211_find_ie(WLAN_EID_MESH_ID, 209 a->information_elements, 210 a->len_information_elements); 211 if (!ie) 212 return false; 213 if (ie[1] != meshidlen) 214 return false; 215 if (memcmp(ie + 2, meshid, meshidlen)) 216 return false; 217 218 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, 219 a->information_elements, 220 a->len_information_elements); 221 if (!ie) 222 return false; 223 if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) 224 return false; 225 226 /* 227 * Ignore mesh capability (last two bytes of the IE) when 228 * comparing since that may differ between stations taking 229 * part in the same mesh. 230 */ 231 return memcmp(ie + 2, meshcfg, 232 sizeof(struct ieee80211_meshconf_ie) - 2) == 0; 233 } 234 235 static int cmp_bss(struct cfg80211_bss *a, 236 struct cfg80211_bss *b) 237 { 238 int r; 239 240 if (a->channel != b->channel) 241 return b->channel->center_freq - a->channel->center_freq; 242 243 r = memcmp(a->bssid, b->bssid, ETH_ALEN); 244 if (r) 245 return r; 246 247 if (is_zero_ether_addr(a->bssid)) { 248 r = cmp_ies(WLAN_EID_MESH_ID, 249 a->information_elements, 250 a->len_information_elements, 251 b->information_elements, 252 b->len_information_elements); 253 if (r) 254 return r; 255 return cmp_ies(WLAN_EID_MESH_CONFIG, 256 a->information_elements, 257 a->len_information_elements, 258 b->information_elements, 259 b->len_information_elements); 260 } 261 262 return cmp_ies(WLAN_EID_SSID, 263 a->information_elements, 264 a->len_information_elements, 265 b->information_elements, 266 b->len_information_elements); 267 } 268 269 struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, 270 struct ieee80211_channel *channel, 271 const u8 *bssid, 272 const u8 *ssid, size_t ssid_len, 273 u16 capa_mask, u16 capa_val) 274 { 275 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); 276 struct cfg80211_internal_bss *bss, *res = NULL; 277 278 spin_lock_bh(&dev->bss_lock); 279 280 list_for_each_entry(bss, &dev->bss_list, list) { 281 if ((bss->pub.capability & capa_mask) != capa_val) 282 continue; 283 if (channel && bss->pub.channel != channel) 284 continue; 285 if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { 286 res = bss; 287 kref_get(&res->ref); 288 break; 289 } 290 } 291 292 spin_unlock_bh(&dev->bss_lock); 293 if (!res) 294 return NULL; 295 return &res->pub; 296 } 297 EXPORT_SYMBOL(cfg80211_get_bss); 298 299 struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, 300 struct ieee80211_channel *channel, 301 const u8 *meshid, size_t meshidlen, 302 const u8 *meshcfg) 303 { 304 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); 305 struct cfg80211_internal_bss *bss, *res = NULL; 306 307 spin_lock_bh(&dev->bss_lock); 308 309 list_for_each_entry(bss, &dev->bss_list, list) { 310 if (channel && bss->pub.channel != channel) 311 continue; 312 if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) { 313 res = bss; 314 kref_get(&res->ref); 315 break; 316 } 317 } 318 319 spin_unlock_bh(&dev->bss_lock); 320 if (!res) 321 return NULL; 322 return &res->pub; 323 } 324 EXPORT_SYMBOL(cfg80211_get_mesh); 325 326 327 static void rb_insert_bss(struct cfg80211_registered_device *dev, 328 struct cfg80211_internal_bss *bss) 329 { 330 struct rb_node **p = &dev->bss_tree.rb_node; 331 struct rb_node *parent = NULL; 332 struct cfg80211_internal_bss *tbss; 333 int cmp; 334 335 while (*p) { 336 parent = *p; 337 tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn); 338 339 cmp = cmp_bss(&bss->pub, &tbss->pub); 340 341 if (WARN_ON(!cmp)) { 342 /* will sort of leak this BSS */ 343 return; 344 } 345 346 if (cmp < 0) 347 p = &(*p)->rb_left; 348 else 349 p = &(*p)->rb_right; 350 } 351 352 rb_link_node(&bss->rbn, parent, p); 353 rb_insert_color(&bss->rbn, &dev->bss_tree); 354 } 355 356 static struct cfg80211_internal_bss * 357 rb_find_bss(struct cfg80211_registered_device *dev, 358 struct cfg80211_internal_bss *res) 359 { 360 struct rb_node *n = dev->bss_tree.rb_node; 361 struct cfg80211_internal_bss *bss; 362 int r; 363 364 while (n) { 365 bss = rb_entry(n, struct cfg80211_internal_bss, rbn); 366 r = cmp_bss(&res->pub, &bss->pub); 367 368 if (r == 0) 369 return bss; 370 else if (r < 0) 371 n = n->rb_left; 372 else 373 n = n->rb_right; 374 } 375 376 return NULL; 377 } 378 379 static struct cfg80211_internal_bss * 380 cfg80211_bss_update(struct cfg80211_registered_device *dev, 381 struct cfg80211_internal_bss *res) 382 { 383 struct cfg80211_internal_bss *found = NULL; 384 const u8 *meshid, *meshcfg; 385 386 /* 387 * The reference to "res" is donated to this function. 388 */ 389 390 if (WARN_ON(!res->pub.channel)) { 391 kref_put(&res->ref, bss_release); 392 return NULL; 393 } 394 395 res->ts = jiffies; 396 397 if (is_zero_ether_addr(res->pub.bssid)) { 398 /* must be mesh, verify */ 399 meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, 400 res->pub.information_elements, 401 res->pub.len_information_elements); 402 meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, 403 res->pub.information_elements, 404 res->pub.len_information_elements); 405 if (!meshid || !meshcfg || 406 meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { 407 /* bogus mesh */ 408 kref_put(&res->ref, bss_release); 409 return NULL; 410 } 411 } 412 413 spin_lock_bh(&dev->bss_lock); 414 415 found = rb_find_bss(dev, res); 416 417 if (found) { 418 found->pub.beacon_interval = res->pub.beacon_interval; 419 found->pub.tsf = res->pub.tsf; 420 found->pub.signal = res->pub.signal; 421 found->pub.capability = res->pub.capability; 422 found->ts = res->ts; 423 424 /* Update IEs */ 425 if (res->pub.proberesp_ies) { 426 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 427 size_t ielen = res->pub.len_proberesp_ies; 428 429 if (found->pub.proberesp_ies && 430 !found->proberesp_ies_allocated && 431 ksize(found) >= used + ielen) { 432 memcpy(found->pub.proberesp_ies, 433 res->pub.proberesp_ies, ielen); 434 found->pub.len_proberesp_ies = ielen; 435 } else { 436 u8 *ies = found->pub.proberesp_ies; 437 438 if (found->proberesp_ies_allocated) 439 ies = krealloc(ies, ielen, GFP_ATOMIC); 440 else 441 ies = kmalloc(ielen, GFP_ATOMIC); 442 443 if (ies) { 444 memcpy(ies, res->pub.proberesp_ies, 445 ielen); 446 found->proberesp_ies_allocated = true; 447 found->pub.proberesp_ies = ies; 448 found->pub.len_proberesp_ies = ielen; 449 } 450 } 451 452 /* Override possible earlier Beacon frame IEs */ 453 found->pub.information_elements = 454 found->pub.proberesp_ies; 455 found->pub.len_information_elements = 456 found->pub.len_proberesp_ies; 457 } 458 if (res->pub.beacon_ies) { 459 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 460 size_t ielen = res->pub.len_beacon_ies; 461 462 if (found->pub.beacon_ies && 463 !found->beacon_ies_allocated && 464 ksize(found) >= used + ielen) { 465 memcpy(found->pub.beacon_ies, 466 res->pub.beacon_ies, ielen); 467 found->pub.len_beacon_ies = ielen; 468 } else { 469 u8 *ies = found->pub.beacon_ies; 470 471 if (found->beacon_ies_allocated) 472 ies = krealloc(ies, ielen, GFP_ATOMIC); 473 else 474 ies = kmalloc(ielen, GFP_ATOMIC); 475 476 if (ies) { 477 memcpy(ies, res->pub.beacon_ies, 478 ielen); 479 found->beacon_ies_allocated = true; 480 found->pub.beacon_ies = ies; 481 found->pub.len_beacon_ies = ielen; 482 } 483 } 484 } 485 486 kref_put(&res->ref, bss_release); 487 } else { 488 /* this "consumes" the reference */ 489 list_add_tail(&res->list, &dev->bss_list); 490 rb_insert_bss(dev, res); 491 found = res; 492 } 493 494 dev->bss_generation++; 495 spin_unlock_bh(&dev->bss_lock); 496 497 kref_get(&found->ref); 498 return found; 499 } 500 501 struct cfg80211_bss* 502 cfg80211_inform_bss(struct wiphy *wiphy, 503 struct ieee80211_channel *channel, 504 const u8 *bssid, 505 u64 timestamp, u16 capability, u16 beacon_interval, 506 const u8 *ie, size_t ielen, 507 s32 signal, gfp_t gfp) 508 { 509 struct cfg80211_internal_bss *res; 510 size_t privsz; 511 512 if (WARN_ON(!wiphy)) 513 return NULL; 514 515 privsz = wiphy->bss_priv_size; 516 517 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && 518 (signal < 0 || signal > 100))) 519 return NULL; 520 521 res = kzalloc(sizeof(*res) + privsz + ielen, gfp); 522 if (!res) 523 return NULL; 524 525 memcpy(res->pub.bssid, bssid, ETH_ALEN); 526 res->pub.channel = channel; 527 res->pub.signal = signal; 528 res->pub.tsf = timestamp; 529 res->pub.beacon_interval = beacon_interval; 530 res->pub.capability = capability; 531 /* 532 * Since we do not know here whether the IEs are from a Beacon or Probe 533 * Response frame, we need to pick one of the options and only use it 534 * with the driver that does not provide the full Beacon/Probe Response 535 * frame. Use Beacon frame pointer to avoid indicating that this should 536 * override the information_elements pointer should we have received an 537 * earlier indication of Probe Response data. 538 * 539 * The initial buffer for the IEs is allocated with the BSS entry and 540 * is located after the private area. 541 */ 542 res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz; 543 memcpy(res->pub.beacon_ies, ie, ielen); 544 res->pub.len_beacon_ies = ielen; 545 res->pub.information_elements = res->pub.beacon_ies; 546 res->pub.len_information_elements = res->pub.len_beacon_ies; 547 548 kref_init(&res->ref); 549 550 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); 551 if (!res) 552 return NULL; 553 554 if (res->pub.capability & WLAN_CAPABILITY_ESS) 555 regulatory_hint_found_beacon(wiphy, channel, gfp); 556 557 /* cfg80211_bss_update gives us a referenced result */ 558 return &res->pub; 559 } 560 EXPORT_SYMBOL(cfg80211_inform_bss); 561 562 struct cfg80211_bss * 563 cfg80211_inform_bss_frame(struct wiphy *wiphy, 564 struct ieee80211_channel *channel, 565 struct ieee80211_mgmt *mgmt, size_t len, 566 s32 signal, gfp_t gfp) 567 { 568 struct cfg80211_internal_bss *res; 569 size_t ielen = len - offsetof(struct ieee80211_mgmt, 570 u.probe_resp.variable); 571 size_t privsz = wiphy->bss_priv_size; 572 573 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && 574 (signal < 0 || signal > 100))) 575 return NULL; 576 577 if (WARN_ON(!mgmt || !wiphy || 578 len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) 579 return NULL; 580 581 res = kzalloc(sizeof(*res) + privsz + ielen, gfp); 582 if (!res) 583 return NULL; 584 585 memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN); 586 res->pub.channel = channel; 587 res->pub.signal = signal; 588 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); 589 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 590 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 591 /* 592 * The initial buffer for the IEs is allocated with the BSS entry and 593 * is located after the private area. 594 */ 595 if (ieee80211_is_probe_resp(mgmt->frame_control)) { 596 res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz; 597 memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable, 598 ielen); 599 res->pub.len_proberesp_ies = ielen; 600 res->pub.information_elements = res->pub.proberesp_ies; 601 res->pub.len_information_elements = res->pub.len_proberesp_ies; 602 } else { 603 res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz; 604 memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen); 605 res->pub.len_beacon_ies = ielen; 606 res->pub.information_elements = res->pub.beacon_ies; 607 res->pub.len_information_elements = res->pub.len_beacon_ies; 608 } 609 610 kref_init(&res->ref); 611 612 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); 613 if (!res) 614 return NULL; 615 616 if (res->pub.capability & WLAN_CAPABILITY_ESS) 617 regulatory_hint_found_beacon(wiphy, channel, gfp); 618 619 /* cfg80211_bss_update gives us a referenced result */ 620 return &res->pub; 621 } 622 EXPORT_SYMBOL(cfg80211_inform_bss_frame); 623 624 void cfg80211_put_bss(struct cfg80211_bss *pub) 625 { 626 struct cfg80211_internal_bss *bss; 627 628 if (!pub) 629 return; 630 631 bss = container_of(pub, struct cfg80211_internal_bss, pub); 632 kref_put(&bss->ref, bss_release); 633 } 634 EXPORT_SYMBOL(cfg80211_put_bss); 635 636 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) 637 { 638 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); 639 struct cfg80211_internal_bss *bss; 640 641 if (WARN_ON(!pub)) 642 return; 643 644 bss = container_of(pub, struct cfg80211_internal_bss, pub); 645 646 spin_lock_bh(&dev->bss_lock); 647 648 list_del(&bss->list); 649 dev->bss_generation++; 650 rb_erase(&bss->rbn, &dev->bss_tree); 651 652 spin_unlock_bh(&dev->bss_lock); 653 654 kref_put(&bss->ref, bss_release); 655 } 656 EXPORT_SYMBOL(cfg80211_unlink_bss); 657 658 #ifdef CONFIG_CFG80211_WEXT 659 int cfg80211_wext_siwscan(struct net_device *dev, 660 struct iw_request_info *info, 661 union iwreq_data *wrqu, char *extra) 662 { 663 struct cfg80211_registered_device *rdev; 664 struct wiphy *wiphy; 665 struct iw_scan_req *wreq = NULL; 666 struct cfg80211_scan_request *creq = NULL; 667 int i, err, n_channels = 0; 668 enum ieee80211_band band; 669 670 if (!netif_running(dev)) 671 return -ENETDOWN; 672 673 if (wrqu->data.length == sizeof(struct iw_scan_req)) 674 wreq = (struct iw_scan_req *)extra; 675 676 rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex); 677 678 if (IS_ERR(rdev)) 679 return PTR_ERR(rdev); 680 681 if (rdev->scan_req) { 682 err = -EBUSY; 683 goto out; 684 } 685 686 wiphy = &rdev->wiphy; 687 688 /* Determine number of channels, needed to allocate creq */ 689 if (wreq && wreq->num_channels) 690 n_channels = wreq->num_channels; 691 else { 692 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 693 if (wiphy->bands[band]) 694 n_channels += wiphy->bands[band]->n_channels; 695 } 696 697 creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + 698 n_channels * sizeof(void *), 699 GFP_ATOMIC); 700 if (!creq) { 701 err = -ENOMEM; 702 goto out; 703 } 704 705 creq->wiphy = wiphy; 706 creq->dev = dev; 707 /* SSIDs come after channels */ 708 creq->ssids = (void *)&creq->channels[n_channels]; 709 creq->n_channels = n_channels; 710 creq->n_ssids = 1; 711 712 /* translate "Scan on frequencies" request */ 713 i = 0; 714 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 715 int j; 716 717 if (!wiphy->bands[band]) 718 continue; 719 720 for (j = 0; j < wiphy->bands[band]->n_channels; j++) { 721 /* ignore disabled channels */ 722 if (wiphy->bands[band]->channels[j].flags & 723 IEEE80211_CHAN_DISABLED) 724 continue; 725 726 /* If we have a wireless request structure and the 727 * wireless request specifies frequencies, then search 728 * for the matching hardware channel. 729 */ 730 if (wreq && wreq->num_channels) { 731 int k; 732 int wiphy_freq = wiphy->bands[band]->channels[j].center_freq; 733 for (k = 0; k < wreq->num_channels; k++) { 734 int wext_freq = cfg80211_wext_freq(wiphy, &wreq->channel_list[k]); 735 if (wext_freq == wiphy_freq) 736 goto wext_freq_found; 737 } 738 goto wext_freq_not_found; 739 } 740 741 wext_freq_found: 742 creq->channels[i] = &wiphy->bands[band]->channels[j]; 743 i++; 744 wext_freq_not_found: ; 745 } 746 } 747 /* No channels found? */ 748 if (!i) { 749 err = -EINVAL; 750 goto out; 751 } 752 753 /* Set real number of channels specified in creq->channels[] */ 754 creq->n_channels = i; 755 756 /* translate "Scan for SSID" request */ 757 if (wreq) { 758 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 759 if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { 760 err = -EINVAL; 761 goto out; 762 } 763 memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); 764 creq->ssids[0].ssid_len = wreq->essid_len; 765 } 766 if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) 767 creq->n_ssids = 0; 768 } 769 770 rdev->scan_req = creq; 771 err = rdev->ops->scan(wiphy, dev, creq); 772 if (err) { 773 rdev->scan_req = NULL; 774 /* creq will be freed below */ 775 } else { 776 nl80211_send_scan_start(rdev, dev); 777 /* creq now owned by driver */ 778 creq = NULL; 779 dev_hold(dev); 780 } 781 out: 782 kfree(creq); 783 cfg80211_unlock_rdev(rdev); 784 return err; 785 } 786 EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); 787 788 static void ieee80211_scan_add_ies(struct iw_request_info *info, 789 struct cfg80211_bss *bss, 790 char **current_ev, char *end_buf) 791 { 792 u8 *pos, *end, *next; 793 struct iw_event iwe; 794 795 if (!bss->information_elements || 796 !bss->len_information_elements) 797 return; 798 799 /* 800 * If needed, fragment the IEs buffer (at IE boundaries) into short 801 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. 802 */ 803 pos = bss->information_elements; 804 end = pos + bss->len_information_elements; 805 806 while (end - pos > IW_GENERIC_IE_MAX) { 807 next = pos + 2 + pos[1]; 808 while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) 809 next = next + 2 + next[1]; 810 811 memset(&iwe, 0, sizeof(iwe)); 812 iwe.cmd = IWEVGENIE; 813 iwe.u.data.length = next - pos; 814 *current_ev = iwe_stream_add_point(info, *current_ev, 815 end_buf, &iwe, pos); 816 817 pos = next; 818 } 819 820 if (end > pos) { 821 memset(&iwe, 0, sizeof(iwe)); 822 iwe.cmd = IWEVGENIE; 823 iwe.u.data.length = end - pos; 824 *current_ev = iwe_stream_add_point(info, *current_ev, 825 end_buf, &iwe, pos); 826 } 827 } 828 829 static inline unsigned int elapsed_jiffies_msecs(unsigned long start) 830 { 831 unsigned long end = jiffies; 832 833 if (end >= start) 834 return jiffies_to_msecs(end - start); 835 836 return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1); 837 } 838 839 static char * 840 ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, 841 struct cfg80211_internal_bss *bss, char *current_ev, 842 char *end_buf) 843 { 844 struct iw_event iwe; 845 u8 *buf, *cfg, *p; 846 u8 *ie = bss->pub.information_elements; 847 int rem = bss->pub.len_information_elements, i, sig; 848 bool ismesh = false; 849 850 memset(&iwe, 0, sizeof(iwe)); 851 iwe.cmd = SIOCGIWAP; 852 iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 853 memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN); 854 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 855 IW_EV_ADDR_LEN); 856 857 memset(&iwe, 0, sizeof(iwe)); 858 iwe.cmd = SIOCGIWFREQ; 859 iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq); 860 iwe.u.freq.e = 0; 861 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 862 IW_EV_FREQ_LEN); 863 864 memset(&iwe, 0, sizeof(iwe)); 865 iwe.cmd = SIOCGIWFREQ; 866 iwe.u.freq.m = bss->pub.channel->center_freq; 867 iwe.u.freq.e = 6; 868 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 869 IW_EV_FREQ_LEN); 870 871 if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) { 872 memset(&iwe, 0, sizeof(iwe)); 873 iwe.cmd = IWEVQUAL; 874 iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED | 875 IW_QUAL_NOISE_INVALID | 876 IW_QUAL_QUAL_UPDATED; 877 switch (wiphy->signal_type) { 878 case CFG80211_SIGNAL_TYPE_MBM: 879 sig = bss->pub.signal / 100; 880 iwe.u.qual.level = sig; 881 iwe.u.qual.updated |= IW_QUAL_DBM; 882 if (sig < -110) /* rather bad */ 883 sig = -110; 884 else if (sig > -40) /* perfect */ 885 sig = -40; 886 /* will give a range of 0 .. 70 */ 887 iwe.u.qual.qual = sig + 110; 888 break; 889 case CFG80211_SIGNAL_TYPE_UNSPEC: 890 iwe.u.qual.level = bss->pub.signal; 891 /* will give range 0 .. 100 */ 892 iwe.u.qual.qual = bss->pub.signal; 893 break; 894 default: 895 /* not reached */ 896 break; 897 } 898 current_ev = iwe_stream_add_event(info, current_ev, end_buf, 899 &iwe, IW_EV_QUAL_LEN); 900 } 901 902 memset(&iwe, 0, sizeof(iwe)); 903 iwe.cmd = SIOCGIWENCODE; 904 if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY) 905 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 906 else 907 iwe.u.data.flags = IW_ENCODE_DISABLED; 908 iwe.u.data.length = 0; 909 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 910 &iwe, ""); 911 912 while (rem >= 2) { 913 /* invalid data */ 914 if (ie[1] > rem - 2) 915 break; 916 917 switch (ie[0]) { 918 case WLAN_EID_SSID: 919 memset(&iwe, 0, sizeof(iwe)); 920 iwe.cmd = SIOCGIWESSID; 921 iwe.u.data.length = ie[1]; 922 iwe.u.data.flags = 1; 923 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 924 &iwe, ie + 2); 925 break; 926 case WLAN_EID_MESH_ID: 927 memset(&iwe, 0, sizeof(iwe)); 928 iwe.cmd = SIOCGIWESSID; 929 iwe.u.data.length = ie[1]; 930 iwe.u.data.flags = 1; 931 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 932 &iwe, ie + 2); 933 break; 934 case WLAN_EID_MESH_CONFIG: 935 ismesh = true; 936 if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) 937 break; 938 buf = kmalloc(50, GFP_ATOMIC); 939 if (!buf) 940 break; 941 cfg = ie + 2; 942 memset(&iwe, 0, sizeof(iwe)); 943 iwe.cmd = IWEVCUSTOM; 944 sprintf(buf, "Mesh Network Path Selection Protocol ID: " 945 "0x%02X", cfg[0]); 946 iwe.u.data.length = strlen(buf); 947 current_ev = iwe_stream_add_point(info, current_ev, 948 end_buf, 949 &iwe, buf); 950 sprintf(buf, "Path Selection Metric ID: 0x%02X", 951 cfg[1]); 952 iwe.u.data.length = strlen(buf); 953 current_ev = iwe_stream_add_point(info, current_ev, 954 end_buf, 955 &iwe, buf); 956 sprintf(buf, "Congestion Control Mode ID: 0x%02X", 957 cfg[2]); 958 iwe.u.data.length = strlen(buf); 959 current_ev = iwe_stream_add_point(info, current_ev, 960 end_buf, 961 &iwe, buf); 962 sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]); 963 iwe.u.data.length = strlen(buf); 964 current_ev = iwe_stream_add_point(info, current_ev, 965 end_buf, 966 &iwe, buf); 967 sprintf(buf, "Authentication ID: 0x%02X", cfg[4]); 968 iwe.u.data.length = strlen(buf); 969 current_ev = iwe_stream_add_point(info, current_ev, 970 end_buf, 971 &iwe, buf); 972 sprintf(buf, "Formation Info: 0x%02X", cfg[5]); 973 iwe.u.data.length = strlen(buf); 974 current_ev = iwe_stream_add_point(info, current_ev, 975 end_buf, 976 &iwe, buf); 977 sprintf(buf, "Capabilities: 0x%02X", cfg[6]); 978 iwe.u.data.length = strlen(buf); 979 current_ev = iwe_stream_add_point(info, current_ev, 980 end_buf, 981 &iwe, buf); 982 kfree(buf); 983 break; 984 case WLAN_EID_SUPP_RATES: 985 case WLAN_EID_EXT_SUPP_RATES: 986 /* display all supported rates in readable format */ 987 p = current_ev + iwe_stream_lcp_len(info); 988 989 memset(&iwe, 0, sizeof(iwe)); 990 iwe.cmd = SIOCGIWRATE; 991 /* Those two flags are ignored... */ 992 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 993 994 for (i = 0; i < ie[1]; i++) { 995 iwe.u.bitrate.value = 996 ((ie[i + 2] & 0x7f) * 500000); 997 p = iwe_stream_add_value(info, current_ev, p, 998 end_buf, &iwe, IW_EV_PARAM_LEN); 999 } 1000 current_ev = p; 1001 break; 1002 } 1003 rem -= ie[1] + 2; 1004 ie += ie[1] + 2; 1005 } 1006 1007 if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) || 1008 ismesh) { 1009 memset(&iwe, 0, sizeof(iwe)); 1010 iwe.cmd = SIOCGIWMODE; 1011 if (ismesh) 1012 iwe.u.mode = IW_MODE_MESH; 1013 else if (bss->pub.capability & WLAN_CAPABILITY_ESS) 1014 iwe.u.mode = IW_MODE_MASTER; 1015 else 1016 iwe.u.mode = IW_MODE_ADHOC; 1017 current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1018 &iwe, IW_EV_UINT_LEN); 1019 } 1020 1021 buf = kmalloc(30, GFP_ATOMIC); 1022 if (buf) { 1023 memset(&iwe, 0, sizeof(iwe)); 1024 iwe.cmd = IWEVCUSTOM; 1025 sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf)); 1026 iwe.u.data.length = strlen(buf); 1027 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1028 &iwe, buf); 1029 memset(&iwe, 0, sizeof(iwe)); 1030 iwe.cmd = IWEVCUSTOM; 1031 sprintf(buf, " Last beacon: %ums ago", 1032 elapsed_jiffies_msecs(bss->ts)); 1033 iwe.u.data.length = strlen(buf); 1034 current_ev = iwe_stream_add_point(info, current_ev, 1035 end_buf, &iwe, buf); 1036 kfree(buf); 1037 } 1038 1039 ieee80211_scan_add_ies(info, &bss->pub, ¤t_ev, end_buf); 1040 1041 return current_ev; 1042 } 1043 1044 1045 static int ieee80211_scan_results(struct cfg80211_registered_device *dev, 1046 struct iw_request_info *info, 1047 char *buf, size_t len) 1048 { 1049 char *current_ev = buf; 1050 char *end_buf = buf + len; 1051 struct cfg80211_internal_bss *bss; 1052 1053 spin_lock_bh(&dev->bss_lock); 1054 cfg80211_bss_expire(dev); 1055 1056 list_for_each_entry(bss, &dev->bss_list, list) { 1057 if (buf + len - current_ev <= IW_EV_ADDR_LEN) { 1058 spin_unlock_bh(&dev->bss_lock); 1059 return -E2BIG; 1060 } 1061 current_ev = ieee80211_bss(&dev->wiphy, info, bss, 1062 current_ev, end_buf); 1063 } 1064 spin_unlock_bh(&dev->bss_lock); 1065 return current_ev - buf; 1066 } 1067 1068 1069 int cfg80211_wext_giwscan(struct net_device *dev, 1070 struct iw_request_info *info, 1071 struct iw_point *data, char *extra) 1072 { 1073 struct cfg80211_registered_device *rdev; 1074 int res; 1075 1076 if (!netif_running(dev)) 1077 return -ENETDOWN; 1078 1079 rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex); 1080 1081 if (IS_ERR(rdev)) 1082 return PTR_ERR(rdev); 1083 1084 if (rdev->scan_req) { 1085 res = -EAGAIN; 1086 goto out; 1087 } 1088 1089 res = ieee80211_scan_results(rdev, info, extra, data->length); 1090 data->length = 0; 1091 if (res >= 0) { 1092 data->length = res; 1093 res = 0; 1094 } 1095 1096 out: 1097 cfg80211_unlock_rdev(rdev); 1098 return res; 1099 } 1100 EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); 1101 #endif 1102