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