linux/net/wireless/wext-compat.c
<<
>>
Prefs
   1/*
   2 * cfg80211 - wext compat code
   3 *
   4 * This is temporary code until all wireless functionality is migrated
   5 * into cfg80211, when that happens all the exports here go away and
   6 * we directly assign the wireless handlers of wireless interfaces.
   7 *
   8 * Copyright 2008-2009  Johannes Berg <johannes@sipsolutions.net>
   9 */
  10
  11#include <linux/wireless.h>
  12#include <linux/nl80211.h>
  13#include <linux/if_arp.h>
  14#include <linux/etherdevice.h>
  15#include <net/iw_handler.h>
  16#include <net/cfg80211.h>
  17#include "wext-compat.h"
  18#include "core.h"
  19
  20int cfg80211_wext_giwname(struct net_device *dev,
  21                          struct iw_request_info *info,
  22                          char *name, char *extra)
  23{
  24        struct wireless_dev *wdev = dev->ieee80211_ptr;
  25        struct ieee80211_supported_band *sband;
  26        bool is_ht = false, is_a = false, is_b = false, is_g = false;
  27
  28        if (!wdev)
  29                return -EOPNOTSUPP;
  30
  31        sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
  32        if (sband) {
  33                is_a = true;
  34                is_ht |= sband->ht_cap.ht_supported;
  35        }
  36
  37        sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
  38        if (sband) {
  39                int i;
  40                /* Check for mandatory rates */
  41                for (i = 0; i < sband->n_bitrates; i++) {
  42                        if (sband->bitrates[i].bitrate == 10)
  43                                is_b = true;
  44                        if (sband->bitrates[i].bitrate == 60)
  45                                is_g = true;
  46                }
  47                is_ht |= sband->ht_cap.ht_supported;
  48        }
  49
  50        strcpy(name, "IEEE 802.11");
  51        if (is_a)
  52                strcat(name, "a");
  53        if (is_b)
  54                strcat(name, "b");
  55        if (is_g)
  56                strcat(name, "g");
  57        if (is_ht)
  58                strcat(name, "n");
  59
  60        return 0;
  61}
  62EXPORT_SYMBOL_GPL(cfg80211_wext_giwname);
  63
  64int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
  65                          u32 *mode, char *extra)
  66{
  67        struct wireless_dev *wdev = dev->ieee80211_ptr;
  68        struct cfg80211_registered_device *rdev;
  69        struct vif_params vifparams;
  70        enum nl80211_iftype type;
  71        int ret;
  72
  73        rdev = wiphy_to_dev(wdev->wiphy);
  74
  75        switch (*mode) {
  76        case IW_MODE_INFRA:
  77                type = NL80211_IFTYPE_STATION;
  78                break;
  79        case IW_MODE_ADHOC:
  80                type = NL80211_IFTYPE_ADHOC;
  81                break;
  82        case IW_MODE_REPEAT:
  83                type = NL80211_IFTYPE_WDS;
  84                break;
  85        case IW_MODE_MONITOR:
  86                type = NL80211_IFTYPE_MONITOR;
  87                break;
  88        default:
  89                return -EINVAL;
  90        }
  91
  92        if (type == wdev->iftype)
  93                return 0;
  94
  95        memset(&vifparams, 0, sizeof(vifparams));
  96
  97        cfg80211_lock_rdev(rdev);
  98        ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
  99        cfg80211_unlock_rdev(rdev);
 100
 101        return ret;
 102}
 103EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
 104
 105int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
 106                          u32 *mode, char *extra)
 107{
 108        struct wireless_dev *wdev = dev->ieee80211_ptr;
 109
 110        if (!wdev)
 111                return -EOPNOTSUPP;
 112
 113        switch (wdev->iftype) {
 114        case NL80211_IFTYPE_AP:
 115                *mode = IW_MODE_MASTER;
 116                break;
 117        case NL80211_IFTYPE_STATION:
 118                *mode = IW_MODE_INFRA;
 119                break;
 120        case NL80211_IFTYPE_ADHOC:
 121                *mode = IW_MODE_ADHOC;
 122                break;
 123        case NL80211_IFTYPE_MONITOR:
 124                *mode = IW_MODE_MONITOR;
 125                break;
 126        case NL80211_IFTYPE_WDS:
 127                *mode = IW_MODE_REPEAT;
 128                break;
 129        case NL80211_IFTYPE_AP_VLAN:
 130                *mode = IW_MODE_SECOND;         /* FIXME */
 131                break;
 132        default:
 133                *mode = IW_MODE_AUTO;
 134                break;
 135        }
 136        return 0;
 137}
 138EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode);
 139
 140
 141int cfg80211_wext_giwrange(struct net_device *dev,
 142                           struct iw_request_info *info,
 143                           struct iw_point *data, char *extra)
 144{
 145        struct wireless_dev *wdev = dev->ieee80211_ptr;
 146        struct iw_range *range = (struct iw_range *) extra;
 147        enum ieee80211_band band;
 148        int i, c = 0;
 149
 150        if (!wdev)
 151                return -EOPNOTSUPP;
 152
 153        data->length = sizeof(struct iw_range);
 154        memset(range, 0, sizeof(struct iw_range));
 155
 156        range->we_version_compiled = WIRELESS_EXT;
 157        range->we_version_source = 21;
 158        range->retry_capa = IW_RETRY_LIMIT;
 159        range->retry_flags = IW_RETRY_LIMIT;
 160        range->min_retry = 0;
 161        range->max_retry = 255;
 162        range->min_rts = 0;
 163        range->max_rts = 2347;
 164        range->min_frag = 256;
 165        range->max_frag = 2346;
 166
 167        range->max_encoding_tokens = 4;
 168
 169        range->max_qual.updated = IW_QUAL_NOISE_INVALID;
 170
 171        switch (wdev->wiphy->signal_type) {
 172        case CFG80211_SIGNAL_TYPE_NONE:
 173                break;
 174        case CFG80211_SIGNAL_TYPE_MBM:
 175                range->max_qual.level = -110;
 176                range->max_qual.qual = 70;
 177                range->avg_qual.qual = 35;
 178                range->max_qual.updated |= IW_QUAL_DBM;
 179                range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
 180                range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
 181                break;
 182        case CFG80211_SIGNAL_TYPE_UNSPEC:
 183                range->max_qual.level = 100;
 184                range->max_qual.qual = 100;
 185                range->avg_qual.qual = 50;
 186                range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
 187                range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
 188                break;
 189        }
 190
 191        range->avg_qual.level = range->max_qual.level / 2;
 192        range->avg_qual.noise = range->max_qual.noise / 2;
 193        range->avg_qual.updated = range->max_qual.updated;
 194
 195        for (i = 0; i < wdev->wiphy->n_cipher_suites; i++) {
 196                switch (wdev->wiphy->cipher_suites[i]) {
 197                case WLAN_CIPHER_SUITE_TKIP:
 198                        range->enc_capa |= (IW_ENC_CAPA_CIPHER_TKIP |
 199                                            IW_ENC_CAPA_WPA);
 200                        break;
 201
 202                case WLAN_CIPHER_SUITE_CCMP:
 203                        range->enc_capa |= (IW_ENC_CAPA_CIPHER_CCMP |
 204                                            IW_ENC_CAPA_WPA2);
 205                        break;
 206
 207                case WLAN_CIPHER_SUITE_WEP40:
 208                        range->encoding_size[range->num_encoding_sizes++] =
 209                                WLAN_KEY_LEN_WEP40;
 210                        break;
 211
 212                case WLAN_CIPHER_SUITE_WEP104:
 213                        range->encoding_size[range->num_encoding_sizes++] =
 214                                WLAN_KEY_LEN_WEP104;
 215                        break;
 216                }
 217        }
 218
 219        for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
 220                struct ieee80211_supported_band *sband;
 221
 222                sband = wdev->wiphy->bands[band];
 223
 224                if (!sband)
 225                        continue;
 226
 227                for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
 228                        struct ieee80211_channel *chan = &sband->channels[i];
 229
 230                        if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
 231                                range->freq[c].i =
 232                                        ieee80211_frequency_to_channel(
 233                                                chan->center_freq);
 234                                range->freq[c].m = chan->center_freq;
 235                                range->freq[c].e = 6;
 236                                c++;
 237                        }
 238                }
 239        }
 240        range->num_channels = c;
 241        range->num_frequency = c;
 242
 243        IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
 244        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
 245        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
 246
 247        if (wdev->wiphy->max_scan_ssids > 0)
 248                range->scan_capa |= IW_SCAN_CAPA_ESSID;
 249
 250        return 0;
 251}
 252EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
 253
 254
 255/**
 256 * cfg80211_wext_freq - get wext frequency for non-"auto"
 257 * @wiphy: the wiphy
 258 * @freq: the wext freq encoding
 259 *
 260 * Returns a frequency, or a negative error code, or 0 for auto.
 261 */
 262int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
 263{
 264        /*
 265         * Parse frequency - return 0 for auto and
 266         * -EINVAL for impossible things.
 267         */
 268        if (freq->e == 0) {
 269                if (freq->m < 0)
 270                        return 0;
 271                return ieee80211_channel_to_frequency(freq->m);
 272        } else {
 273                int i, div = 1000000;
 274                for (i = 0; i < freq->e; i++)
 275                        div /= 10;
 276                if (div <= 0)
 277                        return -EINVAL;
 278                return freq->m / div;
 279        }
 280}
 281
 282int cfg80211_wext_siwrts(struct net_device *dev,
 283                         struct iw_request_info *info,
 284                         struct iw_param *rts, char *extra)
 285{
 286        struct wireless_dev *wdev = dev->ieee80211_ptr;
 287        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 288        u32 orts = wdev->wiphy->rts_threshold;
 289        int err;
 290
 291        if (rts->disabled || !rts->fixed)
 292                wdev->wiphy->rts_threshold = (u32) -1;
 293        else if (rts->value < 0)
 294                return -EINVAL;
 295        else
 296                wdev->wiphy->rts_threshold = rts->value;
 297
 298        err = rdev->ops->set_wiphy_params(wdev->wiphy,
 299                                          WIPHY_PARAM_RTS_THRESHOLD);
 300        if (err)
 301                wdev->wiphy->rts_threshold = orts;
 302
 303        return err;
 304}
 305EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts);
 306
 307int cfg80211_wext_giwrts(struct net_device *dev,
 308                         struct iw_request_info *info,
 309                         struct iw_param *rts, char *extra)
 310{
 311        struct wireless_dev *wdev = dev->ieee80211_ptr;
 312
 313        rts->value = wdev->wiphy->rts_threshold;
 314        rts->disabled = rts->value == (u32) -1;
 315        rts->fixed = 1;
 316
 317        return 0;
 318}
 319EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts);
 320
 321int cfg80211_wext_siwfrag(struct net_device *dev,
 322                          struct iw_request_info *info,
 323                          struct iw_param *frag, char *extra)
 324{
 325        struct wireless_dev *wdev = dev->ieee80211_ptr;
 326        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 327        u32 ofrag = wdev->wiphy->frag_threshold;
 328        int err;
 329
 330        if (frag->disabled || !frag->fixed)
 331                wdev->wiphy->frag_threshold = (u32) -1;
 332        else if (frag->value < 256)
 333                return -EINVAL;
 334        else {
 335                /* Fragment length must be even, so strip LSB. */
 336                wdev->wiphy->frag_threshold = frag->value & ~0x1;
 337        }
 338
 339        err = rdev->ops->set_wiphy_params(wdev->wiphy,
 340                                          WIPHY_PARAM_FRAG_THRESHOLD);
 341        if (err)
 342                wdev->wiphy->frag_threshold = ofrag;
 343
 344        return err;
 345}
 346EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag);
 347
 348int cfg80211_wext_giwfrag(struct net_device *dev,
 349                          struct iw_request_info *info,
 350                          struct iw_param *frag, char *extra)
 351{
 352        struct wireless_dev *wdev = dev->ieee80211_ptr;
 353
 354        frag->value = wdev->wiphy->frag_threshold;
 355        frag->disabled = frag->value == (u32) -1;
 356        frag->fixed = 1;
 357
 358        return 0;
 359}
 360EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag);
 361
 362int cfg80211_wext_siwretry(struct net_device *dev,
 363                           struct iw_request_info *info,
 364                           struct iw_param *retry, char *extra)
 365{
 366        struct wireless_dev *wdev = dev->ieee80211_ptr;
 367        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 368        u32 changed = 0;
 369        u8 olong = wdev->wiphy->retry_long;
 370        u8 oshort = wdev->wiphy->retry_short;
 371        int err;
 372
 373        if (retry->disabled ||
 374            (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
 375                return -EINVAL;
 376
 377        if (retry->flags & IW_RETRY_LONG) {
 378                wdev->wiphy->retry_long = retry->value;
 379                changed |= WIPHY_PARAM_RETRY_LONG;
 380        } else if (retry->flags & IW_RETRY_SHORT) {
 381                wdev->wiphy->retry_short = retry->value;
 382                changed |= WIPHY_PARAM_RETRY_SHORT;
 383        } else {
 384                wdev->wiphy->retry_short = retry->value;
 385                wdev->wiphy->retry_long = retry->value;
 386                changed |= WIPHY_PARAM_RETRY_LONG;
 387                changed |= WIPHY_PARAM_RETRY_SHORT;
 388        }
 389
 390        if (!changed)
 391                return 0;
 392
 393        err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
 394        if (err) {
 395                wdev->wiphy->retry_short = oshort;
 396                wdev->wiphy->retry_long = olong;
 397        }
 398
 399        return err;
 400}
 401EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry);
 402
 403int cfg80211_wext_giwretry(struct net_device *dev,
 404                           struct iw_request_info *info,
 405                           struct iw_param *retry, char *extra)
 406{
 407        struct wireless_dev *wdev = dev->ieee80211_ptr;
 408
 409        retry->disabled = 0;
 410
 411        if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
 412                /*
 413                 * First return short value, iwconfig will ask long value
 414                 * later if needed
 415                 */
 416                retry->flags |= IW_RETRY_LIMIT;
 417                retry->value = wdev->wiphy->retry_short;
 418                if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
 419                        retry->flags |= IW_RETRY_LONG;
 420
 421                return 0;
 422        }
 423
 424        if (retry->flags & IW_RETRY_LONG) {
 425                retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 426                retry->value = wdev->wiphy->retry_long;
 427        }
 428
 429        return 0;
 430}
 431EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
 432
 433static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
 434                                     struct net_device *dev, const u8 *addr,
 435                                     bool remove, bool tx_key, int idx,
 436                                     struct key_params *params)
 437{
 438        struct wireless_dev *wdev = dev->ieee80211_ptr;
 439        int err, i;
 440
 441        if (!wdev->wext.keys) {
 442                wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
 443                                              GFP_KERNEL);
 444                if (!wdev->wext.keys)
 445                        return -ENOMEM;
 446                for (i = 0; i < 6; i++)
 447                        wdev->wext.keys->params[i].key =
 448                                wdev->wext.keys->data[i];
 449        }
 450
 451        if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
 452            wdev->iftype != NL80211_IFTYPE_STATION)
 453                return -EOPNOTSUPP;
 454
 455        if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
 456                if (!wdev->current_bss)
 457                        return -ENOLINK;
 458
 459                if (!rdev->ops->set_default_mgmt_key)
 460                        return -EOPNOTSUPP;
 461
 462                if (idx < 4 || idx > 5)
 463                        return -EINVAL;
 464        } else if (idx < 0 || idx > 3)
 465                return -EINVAL;
 466
 467        if (remove) {
 468                err = 0;
 469                if (wdev->current_bss)
 470                        err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
 471                if (!err) {
 472                        if (!addr) {
 473                                wdev->wext.keys->params[idx].key_len = 0;
 474                                wdev->wext.keys->params[idx].cipher = 0;
 475                        }
 476                        if (idx == wdev->wext.default_key)
 477                                wdev->wext.default_key = -1;
 478                        else if (idx == wdev->wext.default_mgmt_key)
 479                                wdev->wext.default_mgmt_key = -1;
 480                }
 481                /*
 482                 * Applications using wireless extensions expect to be
 483                 * able to delete keys that don't exist, so allow that.
 484                 */
 485                if (err == -ENOENT)
 486                        return 0;
 487
 488                return err;
 489        }
 490
 491        if (addr)
 492                tx_key = false;
 493
 494        if (cfg80211_validate_key_settings(rdev, params, idx, addr))
 495                return -EINVAL;
 496
 497        err = 0;
 498        if (wdev->current_bss)
 499                err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
 500        if (err)
 501                return err;
 502
 503        if (!addr) {
 504                wdev->wext.keys->params[idx] = *params;
 505                memcpy(wdev->wext.keys->data[idx],
 506                        params->key, params->key_len);
 507                wdev->wext.keys->params[idx].key =
 508                        wdev->wext.keys->data[idx];
 509        }
 510
 511        if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 512             params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
 513            (tx_key || (!addr && wdev->wext.default_key == -1))) {
 514                if (wdev->current_bss)
 515                        err = rdev->ops->set_default_key(&rdev->wiphy,
 516                                                         dev, idx);
 517                if (!err)
 518                        wdev->wext.default_key = idx;
 519                return err;
 520        }
 521
 522        if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
 523            (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
 524                if (wdev->current_bss)
 525                        err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
 526                                                              dev, idx);
 527                if (!err)
 528                        wdev->wext.default_mgmt_key = idx;
 529                return err;
 530        }
 531
 532        return 0;
 533}
 534
 535static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
 536                                   struct net_device *dev, const u8 *addr,
 537                                   bool remove, bool tx_key, int idx,
 538                                   struct key_params *params)
 539{
 540        int err;
 541
 542        wdev_lock(dev->ieee80211_ptr);
 543        err = __cfg80211_set_encryption(rdev, dev, addr, remove,
 544                                        tx_key, idx, params);
 545        wdev_unlock(dev->ieee80211_ptr);
 546
 547        return err;
 548}
 549
 550int cfg80211_wext_siwencode(struct net_device *dev,
 551                            struct iw_request_info *info,
 552                            struct iw_point *erq, char *keybuf)
 553{
 554        struct wireless_dev *wdev = dev->ieee80211_ptr;
 555        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 556        int idx, err;
 557        bool remove = false;
 558        struct key_params params;
 559
 560        if (wdev->iftype != NL80211_IFTYPE_STATION &&
 561            wdev->iftype != NL80211_IFTYPE_ADHOC)
 562                return -EOPNOTSUPP;
 563
 564        /* no use -- only MFP (set_default_mgmt_key) is optional */
 565        if (!rdev->ops->del_key ||
 566            !rdev->ops->add_key ||
 567            !rdev->ops->set_default_key)
 568                return -EOPNOTSUPP;
 569
 570        idx = erq->flags & IW_ENCODE_INDEX;
 571        if (idx == 0) {
 572                idx = wdev->wext.default_key;
 573                if (idx < 0)
 574                        idx = 0;
 575        } else if (idx < 1 || idx > 4)
 576                return -EINVAL;
 577        else
 578                idx--;
 579
 580        if (erq->flags & IW_ENCODE_DISABLED)
 581                remove = true;
 582        else if (erq->length == 0) {
 583                /* No key data - just set the default TX key index */
 584                err = 0;
 585                wdev_lock(wdev);
 586                if (wdev->current_bss)
 587                        err = rdev->ops->set_default_key(&rdev->wiphy,
 588                                                         dev, idx);
 589                if (!err)
 590                        wdev->wext.default_key = idx;
 591                wdev_unlock(wdev);
 592                return err;
 593        }
 594
 595        memset(&params, 0, sizeof(params));
 596        params.key = keybuf;
 597        params.key_len = erq->length;
 598        if (erq->length == 5)
 599                params.cipher = WLAN_CIPHER_SUITE_WEP40;
 600        else if (erq->length == 13)
 601                params.cipher = WLAN_CIPHER_SUITE_WEP104;
 602        else if (!remove)
 603                return -EINVAL;
 604
 605        return cfg80211_set_encryption(rdev, dev, NULL, remove,
 606                                       wdev->wext.default_key == -1,
 607                                       idx, &params);
 608}
 609EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode);
 610
 611int cfg80211_wext_siwencodeext(struct net_device *dev,
 612                               struct iw_request_info *info,
 613                               struct iw_point *erq, char *extra)
 614{
 615        struct wireless_dev *wdev = dev->ieee80211_ptr;
 616        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 617        struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
 618        const u8 *addr;
 619        int idx;
 620        bool remove = false;
 621        struct key_params params;
 622        u32 cipher;
 623
 624        if (wdev->iftype != NL80211_IFTYPE_STATION &&
 625            wdev->iftype != NL80211_IFTYPE_ADHOC)
 626                return -EOPNOTSUPP;
 627
 628        /* no use -- only MFP (set_default_mgmt_key) is optional */
 629        if (!rdev->ops->del_key ||
 630            !rdev->ops->add_key ||
 631            !rdev->ops->set_default_key)
 632                return -EOPNOTSUPP;
 633
 634        switch (ext->alg) {
 635        case IW_ENCODE_ALG_NONE:
 636                remove = true;
 637                cipher = 0;
 638                break;
 639        case IW_ENCODE_ALG_WEP:
 640                if (ext->key_len == 5)
 641                        cipher = WLAN_CIPHER_SUITE_WEP40;
 642                else if (ext->key_len == 13)
 643                        cipher = WLAN_CIPHER_SUITE_WEP104;
 644                else
 645                        return -EINVAL;
 646                break;
 647        case IW_ENCODE_ALG_TKIP:
 648                cipher = WLAN_CIPHER_SUITE_TKIP;
 649                break;
 650        case IW_ENCODE_ALG_CCMP:
 651                cipher = WLAN_CIPHER_SUITE_CCMP;
 652                break;
 653        case IW_ENCODE_ALG_AES_CMAC:
 654                cipher = WLAN_CIPHER_SUITE_AES_CMAC;
 655                break;
 656        default:
 657                return -EOPNOTSUPP;
 658        }
 659
 660        if (erq->flags & IW_ENCODE_DISABLED)
 661                remove = true;
 662
 663        idx = erq->flags & IW_ENCODE_INDEX;
 664        if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
 665                if (idx < 4 || idx > 5) {
 666                        idx = wdev->wext.default_mgmt_key;
 667                        if (idx < 0)
 668                                return -EINVAL;
 669                } else
 670                        idx--;
 671        } else {
 672                if (idx < 1 || idx > 4) {
 673                        idx = wdev->wext.default_key;
 674                        if (idx < 0)
 675                                return -EINVAL;
 676                } else
 677                        idx--;
 678        }
 679
 680        addr = ext->addr.sa_data;
 681        if (is_broadcast_ether_addr(addr))
 682                addr = NULL;
 683
 684        memset(&params, 0, sizeof(params));
 685        params.key = ext->key;
 686        params.key_len = ext->key_len;
 687        params.cipher = cipher;
 688
 689        if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
 690                params.seq = ext->rx_seq;
 691                params.seq_len = 6;
 692        }
 693
 694        return cfg80211_set_encryption(
 695                        rdev, dev, addr, remove,
 696                        ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
 697                        idx, &params);
 698}
 699EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
 700
 701int cfg80211_wext_giwencode(struct net_device *dev,
 702                            struct iw_request_info *info,
 703                            struct iw_point *erq, char *keybuf)
 704{
 705        struct wireless_dev *wdev = dev->ieee80211_ptr;
 706        int idx;
 707
 708        if (wdev->iftype != NL80211_IFTYPE_STATION &&
 709            wdev->iftype != NL80211_IFTYPE_ADHOC)
 710                return -EOPNOTSUPP;
 711
 712        idx = erq->flags & IW_ENCODE_INDEX;
 713        if (idx == 0) {
 714                idx = wdev->wext.default_key;
 715                if (idx < 0)
 716                        idx = 0;
 717        } else if (idx < 1 || idx > 4)
 718                return -EINVAL;
 719        else
 720                idx--;
 721
 722        erq->flags = idx + 1;
 723
 724        if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
 725                erq->flags |= IW_ENCODE_DISABLED;
 726                erq->length = 0;
 727                return 0;
 728        }
 729
 730        erq->length = min_t(size_t, erq->length,
 731                            wdev->wext.keys->params[idx].key_len);
 732        memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
 733        erq->flags |= IW_ENCODE_ENABLED;
 734
 735        return 0;
 736}
 737EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
 738
 739int cfg80211_wext_siwfreq(struct net_device *dev,
 740                          struct iw_request_info *info,
 741                          struct iw_freq *wextfreq, char *extra)
 742{
 743        struct wireless_dev *wdev = dev->ieee80211_ptr;
 744        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 745        int freq, err;
 746
 747        switch (wdev->iftype) {
 748        case NL80211_IFTYPE_STATION:
 749                return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
 750        case NL80211_IFTYPE_ADHOC:
 751                return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
 752        default:
 753                freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
 754                if (freq < 0)
 755                        return freq;
 756                if (freq == 0)
 757                        return -EINVAL;
 758                mutex_lock(&rdev->devlist_mtx);
 759                err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
 760                mutex_unlock(&rdev->devlist_mtx);
 761                return err;
 762        }
 763}
 764EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
 765
 766int cfg80211_wext_giwfreq(struct net_device *dev,
 767                          struct iw_request_info *info,
 768                          struct iw_freq *freq, char *extra)
 769{
 770        struct wireless_dev *wdev = dev->ieee80211_ptr;
 771        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 772
 773        switch (wdev->iftype) {
 774        case NL80211_IFTYPE_STATION:
 775                return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
 776        case NL80211_IFTYPE_ADHOC:
 777                return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
 778        default:
 779                if (!rdev->channel)
 780                        return -EINVAL;
 781                freq->m = rdev->channel->center_freq;
 782                freq->e = 6;
 783                return 0;
 784        }
 785}
 786EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq);
 787
 788int cfg80211_wext_siwtxpower(struct net_device *dev,
 789                             struct iw_request_info *info,
 790                             union iwreq_data *data, char *extra)
 791{
 792        struct wireless_dev *wdev = dev->ieee80211_ptr;
 793        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 794        enum tx_power_setting type;
 795        int dbm = 0;
 796
 797        if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
 798                return -EINVAL;
 799        if (data->txpower.flags & IW_TXPOW_RANGE)
 800                return -EINVAL;
 801
 802        if (!rdev->ops->set_tx_power)
 803                return -EOPNOTSUPP;
 804
 805        /* only change when not disabling */
 806        if (!data->txpower.disabled) {
 807                rfkill_set_sw_state(rdev->rfkill, false);
 808
 809                if (data->txpower.fixed) {
 810                        /*
 811                         * wext doesn't support negative values, see
 812                         * below where it's for automatic
 813                         */
 814                        if (data->txpower.value < 0)
 815                                return -EINVAL;
 816                        dbm = data->txpower.value;
 817                        type = TX_POWER_FIXED;
 818                        /* TODO: do regulatory check! */
 819                } else {
 820                        /*
 821                         * Automatic power level setting, max being the value
 822                         * passed in from userland.
 823                         */
 824                        if (data->txpower.value < 0) {
 825                                type = TX_POWER_AUTOMATIC;
 826                        } else {
 827                                dbm = data->txpower.value;
 828                                type = TX_POWER_LIMITED;
 829                        }
 830                }
 831        } else {
 832                rfkill_set_sw_state(rdev->rfkill, true);
 833                schedule_work(&rdev->rfkill_sync);
 834                return 0;
 835        }
 836
 837        return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);
 838}
 839EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
 840
 841int cfg80211_wext_giwtxpower(struct net_device *dev,
 842                             struct iw_request_info *info,
 843                             union iwreq_data *data, char *extra)
 844{
 845        struct wireless_dev *wdev = dev->ieee80211_ptr;
 846        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 847        int err, val;
 848
 849        if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
 850                return -EINVAL;
 851        if (data->txpower.flags & IW_TXPOW_RANGE)
 852                return -EINVAL;
 853
 854        if (!rdev->ops->get_tx_power)
 855                return -EOPNOTSUPP;
 856
 857        err = rdev->ops->get_tx_power(wdev->wiphy, &val);
 858        if (err)
 859                return err;
 860
 861        /* well... oh well */
 862        data->txpower.fixed = 1;
 863        data->txpower.disabled = rfkill_blocked(rdev->rfkill);
 864        data->txpower.value = val;
 865        data->txpower.flags = IW_TXPOW_DBM;
 866
 867        return 0;
 868}
 869EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
 870
 871static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
 872                                 s32 auth_alg)
 873{
 874        int nr_alg = 0;
 875
 876        if (!auth_alg)
 877                return -EINVAL;
 878
 879        if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
 880                         IW_AUTH_ALG_SHARED_KEY |
 881                         IW_AUTH_ALG_LEAP))
 882                return -EINVAL;
 883
 884        if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
 885                nr_alg++;
 886                wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
 887        }
 888
 889        if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
 890                nr_alg++;
 891                wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
 892        }
 893
 894        if (auth_alg & IW_AUTH_ALG_LEAP) {
 895                nr_alg++;
 896                wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
 897        }
 898
 899        if (nr_alg > 1)
 900                wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
 901
 902        return 0;
 903}
 904
 905static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
 906{
 907        wdev->wext.connect.crypto.wpa_versions = 0;
 908
 909        if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
 910                             IW_AUTH_WPA_VERSION_WPA2|
 911                             IW_AUTH_WPA_VERSION_DISABLED))
 912                return -EINVAL;
 913
 914        if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
 915            (wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
 916                             IW_AUTH_WPA_VERSION_WPA2)))
 917                return -EINVAL;
 918
 919        if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
 920                wdev->wext.connect.crypto.wpa_versions &=
 921                        ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
 922
 923        if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
 924                wdev->wext.connect.crypto.wpa_versions |=
 925                        NL80211_WPA_VERSION_1;
 926
 927        if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
 928                wdev->wext.connect.crypto.wpa_versions |=
 929                        NL80211_WPA_VERSION_2;
 930
 931        return 0;
 932}
 933
 934static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
 935{
 936        wdev->wext.connect.crypto.cipher_group = 0;
 937
 938        if (cipher & IW_AUTH_CIPHER_WEP40)
 939                wdev->wext.connect.crypto.cipher_group =
 940                        WLAN_CIPHER_SUITE_WEP40;
 941        else if (cipher & IW_AUTH_CIPHER_WEP104)
 942                wdev->wext.connect.crypto.cipher_group =
 943                        WLAN_CIPHER_SUITE_WEP104;
 944        else if (cipher & IW_AUTH_CIPHER_TKIP)
 945                wdev->wext.connect.crypto.cipher_group =
 946                        WLAN_CIPHER_SUITE_TKIP;
 947        else if (cipher & IW_AUTH_CIPHER_CCMP)
 948                wdev->wext.connect.crypto.cipher_group =
 949                        WLAN_CIPHER_SUITE_CCMP;
 950        else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
 951                wdev->wext.connect.crypto.cipher_group =
 952                        WLAN_CIPHER_SUITE_AES_CMAC;
 953        else
 954                return -EINVAL;
 955
 956        return 0;
 957}
 958
 959static int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
 960{
 961        int nr_ciphers = 0;
 962        u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
 963
 964        if (cipher & IW_AUTH_CIPHER_WEP40) {
 965                ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
 966                nr_ciphers++;
 967        }
 968
 969        if (cipher & IW_AUTH_CIPHER_WEP104) {
 970                ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
 971                nr_ciphers++;
 972        }
 973
 974        if (cipher & IW_AUTH_CIPHER_TKIP) {
 975                ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
 976                nr_ciphers++;
 977        }
 978
 979        if (cipher & IW_AUTH_CIPHER_CCMP) {
 980                ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
 981                nr_ciphers++;
 982        }
 983
 984        if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
 985                ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
 986                nr_ciphers++;
 987        }
 988
 989        BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
 990
 991        wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
 992
 993        return 0;
 994}
 995
 996
 997static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
 998{
 999        int nr_akm_suites = 0;
1000
1001        if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
1002                        IW_AUTH_KEY_MGMT_PSK))
1003                return -EINVAL;
1004
1005        if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
1006                wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1007                        WLAN_AKM_SUITE_8021X;
1008                nr_akm_suites++;
1009        }
1010
1011        if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
1012                wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
1013                        WLAN_AKM_SUITE_PSK;
1014                nr_akm_suites++;
1015        }
1016
1017        wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
1018
1019        return 0;
1020}
1021
1022int cfg80211_wext_siwauth(struct net_device *dev,
1023                          struct iw_request_info *info,
1024                          struct iw_param *data, char *extra)
1025{
1026        struct wireless_dev *wdev = dev->ieee80211_ptr;
1027
1028        if (wdev->iftype != NL80211_IFTYPE_STATION)
1029                return -EOPNOTSUPP;
1030
1031        switch (data->flags & IW_AUTH_INDEX) {
1032        case IW_AUTH_PRIVACY_INVOKED:
1033                wdev->wext.connect.privacy = data->value;
1034                return 0;
1035        case IW_AUTH_WPA_VERSION:
1036                return cfg80211_set_wpa_version(wdev, data->value);
1037        case IW_AUTH_CIPHER_GROUP:
1038                return cfg80211_set_cipher_group(wdev, data->value);
1039        case IW_AUTH_KEY_MGMT:
1040                return cfg80211_set_key_mgt(wdev, data->value);
1041        case IW_AUTH_CIPHER_PAIRWISE:
1042                return cfg80211_set_cipher_pairwise(wdev, data->value);
1043        case IW_AUTH_80211_AUTH_ALG:
1044                return cfg80211_set_auth_alg(wdev, data->value);
1045        case IW_AUTH_WPA_ENABLED:
1046        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1047        case IW_AUTH_DROP_UNENCRYPTED:
1048        case IW_AUTH_MFP:
1049                return 0;
1050        default:
1051                return -EOPNOTSUPP;
1052        }
1053}
1054EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
1055
1056int cfg80211_wext_giwauth(struct net_device *dev,
1057                          struct iw_request_info *info,
1058                          struct iw_param *data, char *extra)
1059{
1060        /* XXX: what do we need? */
1061
1062        return -EOPNOTSUPP;
1063}
1064EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
1065
1066int cfg80211_wext_siwpower(struct net_device *dev,
1067                           struct iw_request_info *info,
1068                           struct iw_param *wrq, char *extra)
1069{
1070        struct wireless_dev *wdev = dev->ieee80211_ptr;
1071        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1072        bool ps = wdev->wext.ps;
1073        int timeout = wdev->wext.ps_timeout;
1074        int err;
1075
1076        if (wdev->iftype != NL80211_IFTYPE_STATION)
1077                return -EINVAL;
1078
1079        if (!rdev->ops->set_power_mgmt)
1080                return -EOPNOTSUPP;
1081
1082        if (wrq->disabled) {
1083                ps = false;
1084        } else {
1085                switch (wrq->flags & IW_POWER_MODE) {
1086                case IW_POWER_ON:       /* If not specified */
1087                case IW_POWER_MODE:     /* If set all mask */
1088                case IW_POWER_ALL_R:    /* If explicitely state all */
1089                        ps = true;
1090                        break;
1091                default:                /* Otherwise we ignore */
1092                        return -EINVAL;
1093                }
1094
1095                if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
1096                        return -EINVAL;
1097
1098                if (wrq->flags & IW_POWER_TIMEOUT)
1099                        timeout = wrq->value / 1000;
1100        }
1101
1102        err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
1103        if (err)
1104                return err;
1105
1106        wdev->wext.ps = ps;
1107        wdev->wext.ps_timeout = timeout;
1108
1109        return 0;
1110
1111}
1112EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
1113
1114int cfg80211_wext_giwpower(struct net_device *dev,
1115                           struct iw_request_info *info,
1116                           struct iw_param *wrq, char *extra)
1117{
1118        struct wireless_dev *wdev = dev->ieee80211_ptr;
1119
1120        wrq->disabled = !wdev->wext.ps;
1121
1122        return 0;
1123}
1124EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
1125
1126static int cfg80211_wds_wext_siwap(struct net_device *dev,
1127                                   struct iw_request_info *info,
1128                                   struct sockaddr *addr, char *extra)
1129{
1130        struct wireless_dev *wdev = dev->ieee80211_ptr;
1131        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1132        int err;
1133
1134        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1135                return -EINVAL;
1136
1137        if (addr->sa_family != ARPHRD_ETHER)
1138                return -EINVAL;
1139
1140        if (netif_running(dev))
1141                return -EBUSY;
1142
1143        if (!rdev->ops->set_wds_peer)
1144                return -EOPNOTSUPP;
1145
1146        err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
1147        if (err)
1148                return err;
1149
1150        memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
1151
1152        return 0;
1153}
1154
1155static int cfg80211_wds_wext_giwap(struct net_device *dev,
1156                                   struct iw_request_info *info,
1157                                   struct sockaddr *addr, char *extra)
1158{
1159        struct wireless_dev *wdev = dev->ieee80211_ptr;
1160
1161        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
1162                return -EINVAL;
1163
1164        addr->sa_family = ARPHRD_ETHER;
1165        memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
1166
1167        return 0;
1168}
1169
1170int cfg80211_wext_siwrate(struct net_device *dev,
1171                          struct iw_request_info *info,
1172                          struct iw_param *rate, char *extra)
1173{
1174        struct wireless_dev *wdev = dev->ieee80211_ptr;
1175        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1176        struct cfg80211_bitrate_mask mask;
1177
1178        if (!rdev->ops->set_bitrate_mask)
1179                return -EOPNOTSUPP;
1180
1181        mask.fixed = 0;
1182        mask.maxrate = 0;
1183
1184        if (rate->value < 0) {
1185                /* nothing */
1186        } else if (rate->fixed) {
1187                mask.fixed = rate->value / 1000; /* kbps */
1188        } else {
1189                mask.maxrate = rate->value / 1000; /* kbps */
1190        }
1191
1192        return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1193}
1194EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
1195
1196int cfg80211_wext_giwrate(struct net_device *dev,
1197                          struct iw_request_info *info,
1198                          struct iw_param *rate, char *extra)
1199{
1200        struct wireless_dev *wdev = dev->ieee80211_ptr;
1201        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1202        /* we are under RTNL - globally locked - so can use a static struct */
1203        static struct station_info sinfo;
1204        u8 addr[ETH_ALEN];
1205        int err;
1206
1207        if (wdev->iftype != NL80211_IFTYPE_STATION)
1208                return -EOPNOTSUPP;
1209
1210        if (!rdev->ops->get_station)
1211                return -EOPNOTSUPP;
1212
1213        err = 0;
1214        wdev_lock(wdev);
1215        if (wdev->current_bss)
1216                memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN);
1217        else
1218                err = -EOPNOTSUPP;
1219        wdev_unlock(wdev);
1220        if (err)
1221                return err;
1222
1223        err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
1224        if (err)
1225                return err;
1226
1227        if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
1228                return -EOPNOTSUPP;
1229
1230        rate->value = 0;
1231
1232        if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
1233                rate->value = 100000 * sinfo.txrate.legacy;
1234
1235        return 0;
1236}
1237EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
1238
1239/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
1240struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
1241{
1242        struct wireless_dev *wdev = dev->ieee80211_ptr;
1243        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1244        /* we are under RTNL - globally locked - so can use static structs */
1245        static struct iw_statistics wstats;
1246        static struct station_info sinfo;
1247        u8 bssid[ETH_ALEN];
1248
1249        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
1250                return NULL;
1251
1252        if (!rdev->ops->get_station)
1253                return NULL;
1254
1255        /* Grab BSSID of current BSS, if any */
1256        wdev_lock(wdev);
1257        if (!wdev->current_bss) {
1258                wdev_unlock(wdev);
1259                return NULL;
1260        }
1261        memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
1262        wdev_unlock(wdev);
1263
1264        if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
1265                return NULL;
1266
1267        memset(&wstats, 0, sizeof(wstats));
1268
1269        switch (rdev->wiphy.signal_type) {
1270        case CFG80211_SIGNAL_TYPE_MBM:
1271                if (sinfo.filled & STATION_INFO_SIGNAL) {
1272                        int sig = sinfo.signal;
1273                        wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1274                        wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1275                        wstats.qual.updated |= IW_QUAL_DBM;
1276                        wstats.qual.level = sig;
1277                        if (sig < -110)
1278                                sig = -110;
1279                        else if (sig > -40)
1280                                sig = -40;
1281                        wstats.qual.qual = sig + 110;
1282                        break;
1283                }
1284        case CFG80211_SIGNAL_TYPE_UNSPEC:
1285                if (sinfo.filled & STATION_INFO_SIGNAL) {
1286                        wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1287                        wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1288                        wstats.qual.level = sinfo.signal;
1289                        wstats.qual.qual = sinfo.signal;
1290                        break;
1291                }
1292        default:
1293                wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
1294                wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
1295        }
1296
1297        wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1298
1299        return &wstats;
1300}
1301EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);
1302
1303int cfg80211_wext_siwap(struct net_device *dev,
1304                        struct iw_request_info *info,
1305                        struct sockaddr *ap_addr, char *extra)
1306{
1307        struct wireless_dev *wdev = dev->ieee80211_ptr;
1308
1309        switch (wdev->iftype) {
1310        case NL80211_IFTYPE_ADHOC:
1311                return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
1312        case NL80211_IFTYPE_STATION:
1313                return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
1314        case NL80211_IFTYPE_WDS:
1315                return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
1316        default:
1317                return -EOPNOTSUPP;
1318        }
1319}
1320EXPORT_SYMBOL_GPL(cfg80211_wext_siwap);
1321
1322int cfg80211_wext_giwap(struct net_device *dev,
1323                        struct iw_request_info *info,
1324                        struct sockaddr *ap_addr, char *extra)
1325{
1326        struct wireless_dev *wdev = dev->ieee80211_ptr;
1327
1328        switch (wdev->iftype) {
1329        case NL80211_IFTYPE_ADHOC:
1330                return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
1331        case NL80211_IFTYPE_STATION:
1332                return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
1333        case NL80211_IFTYPE_WDS:
1334                return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
1335        default:
1336                return -EOPNOTSUPP;
1337        }
1338}
1339EXPORT_SYMBOL_GPL(cfg80211_wext_giwap);
1340
1341int cfg80211_wext_siwessid(struct net_device *dev,
1342                           struct iw_request_info *info,
1343                           struct iw_point *data, char *ssid)
1344{
1345        struct wireless_dev *wdev = dev->ieee80211_ptr;
1346
1347        switch (wdev->iftype) {
1348        case NL80211_IFTYPE_ADHOC:
1349                return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
1350        case NL80211_IFTYPE_STATION:
1351                return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
1352        default:
1353                return -EOPNOTSUPP;
1354        }
1355}
1356EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid);
1357
1358int cfg80211_wext_giwessid(struct net_device *dev,
1359                           struct iw_request_info *info,
1360                           struct iw_point *data, char *ssid)
1361{
1362        struct wireless_dev *wdev = dev->ieee80211_ptr;
1363
1364        switch (wdev->iftype) {
1365        case NL80211_IFTYPE_ADHOC:
1366                return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
1367        case NL80211_IFTYPE_STATION:
1368                return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
1369        default:
1370                return -EOPNOTSUPP;
1371        }
1372}
1373EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
1374
1375static const iw_handler cfg80211_handlers[] = {
1376        [IW_IOCTL_IDX(SIOCGIWNAME)]     = (iw_handler) cfg80211_wext_giwname,
1377        [IW_IOCTL_IDX(SIOCSIWFREQ)]     = (iw_handler) cfg80211_wext_siwfreq,
1378        [IW_IOCTL_IDX(SIOCGIWFREQ)]     = (iw_handler) cfg80211_wext_giwfreq,
1379        [IW_IOCTL_IDX(SIOCSIWMODE)]     = (iw_handler) cfg80211_wext_siwmode,
1380        [IW_IOCTL_IDX(SIOCGIWMODE)]     = (iw_handler) cfg80211_wext_giwmode,
1381        [IW_IOCTL_IDX(SIOCGIWRANGE)]    = (iw_handler) cfg80211_wext_giwrange,
1382        [IW_IOCTL_IDX(SIOCSIWAP)]       = (iw_handler) cfg80211_wext_siwap,
1383        [IW_IOCTL_IDX(SIOCGIWAP)]       = (iw_handler) cfg80211_wext_giwap,
1384        [IW_IOCTL_IDX(SIOCSIWMLME)]     = (iw_handler) cfg80211_wext_siwmlme,
1385        [IW_IOCTL_IDX(SIOCSIWSCAN)]     = (iw_handler) cfg80211_wext_siwscan,
1386        [IW_IOCTL_IDX(SIOCGIWSCAN)]     = (iw_handler) cfg80211_wext_giwscan,
1387        [IW_IOCTL_IDX(SIOCSIWESSID)]    = (iw_handler) cfg80211_wext_siwessid,
1388        [IW_IOCTL_IDX(SIOCGIWESSID)]    = (iw_handler) cfg80211_wext_giwessid,
1389        [IW_IOCTL_IDX(SIOCSIWRATE)]     = (iw_handler) cfg80211_wext_siwrate,
1390        [IW_IOCTL_IDX(SIOCGIWRATE)]     = (iw_handler) cfg80211_wext_giwrate,
1391        [IW_IOCTL_IDX(SIOCSIWRTS)]      = (iw_handler) cfg80211_wext_siwrts,
1392        [IW_IOCTL_IDX(SIOCGIWRTS)]      = (iw_handler) cfg80211_wext_giwrts,
1393        [IW_IOCTL_IDX(SIOCSIWFRAG)]     = (iw_handler) cfg80211_wext_siwfrag,
1394        [IW_IOCTL_IDX(SIOCGIWFRAG)]     = (iw_handler) cfg80211_wext_giwfrag,
1395        [IW_IOCTL_IDX(SIOCSIWTXPOW)]    = (iw_handler) cfg80211_wext_siwtxpower,
1396        [IW_IOCTL_IDX(SIOCGIWTXPOW)]    = (iw_handler) cfg80211_wext_giwtxpower,
1397        [IW_IOCTL_IDX(SIOCSIWRETRY)]    = (iw_handler) cfg80211_wext_siwretry,
1398        [IW_IOCTL_IDX(SIOCGIWRETRY)]    = (iw_handler) cfg80211_wext_giwretry,
1399        [IW_IOCTL_IDX(SIOCSIWENCODE)]   = (iw_handler) cfg80211_wext_siwencode,
1400        [IW_IOCTL_IDX(SIOCGIWENCODE)]   = (iw_handler) cfg80211_wext_giwencode,
1401        [IW_IOCTL_IDX(SIOCSIWPOWER)]    = (iw_handler) cfg80211_wext_siwpower,
1402        [IW_IOCTL_IDX(SIOCGIWPOWER)]    = (iw_handler) cfg80211_wext_giwpower,
1403        [IW_IOCTL_IDX(SIOCSIWGENIE)]    = (iw_handler) cfg80211_wext_siwgenie,
1404        [IW_IOCTL_IDX(SIOCSIWAUTH)]     = (iw_handler) cfg80211_wext_siwauth,
1405        [IW_IOCTL_IDX(SIOCGIWAUTH)]     = (iw_handler) cfg80211_wext_giwauth,
1406        [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
1407};
1408
1409const struct iw_handler_def cfg80211_wext_handler = {
1410        .num_standard           = ARRAY_SIZE(cfg80211_handlers),
1411        .standard               = cfg80211_handlers,
1412        .get_wireless_stats = cfg80211_wireless_stats,
1413};
1414