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