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