linux/net/mac80211/wext.c
<<
>>
Prefs
   1/*
   2 * Copyright 2002-2005, Instant802 Networks, Inc.
   3 * Copyright 2005-2006, Devicescape Software, Inc.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/init.h>
  12#include <linux/netdevice.h>
  13#include <linux/types.h>
  14#include <linux/slab.h>
  15#include <linux/skbuff.h>
  16#include <linux/etherdevice.h>
  17#include <linux/if_arp.h>
  18#include <linux/wireless.h>
  19#include <net/iw_handler.h>
  20#include <asm/uaccess.h>
  21
  22#include <net/mac80211.h>
  23#include "ieee80211_i.h"
  24#include "led.h"
  25#include "rate.h"
  26#include "wpa.h"
  27#include "aes_ccm.h"
  28
  29
  30static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr,
  31                                    int idx, int alg, int remove,
  32                                    int set_tx_key, const u8 *_key,
  33                                    size_t key_len)
  34{
  35        struct ieee80211_local *local = sdata->local;
  36        struct sta_info *sta;
  37        struct ieee80211_key *key;
  38        int err;
  39
  40        if (alg == ALG_AES_CMAC) {
  41                if (idx < NUM_DEFAULT_KEYS ||
  42                    idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
  43                        printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
  44                               "(BIP)\n", sdata->dev->name, idx);
  45                        return -EINVAL;
  46                }
  47        } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
  48                printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
  49                       sdata->dev->name, idx);
  50                return -EINVAL;
  51        }
  52
  53        if (remove) {
  54                rcu_read_lock();
  55
  56                err = 0;
  57
  58                if (is_broadcast_ether_addr(sta_addr)) {
  59                        key = sdata->keys[idx];
  60                } else {
  61                        sta = sta_info_get(local, sta_addr);
  62                        if (!sta) {
  63                                err = -ENOENT;
  64                                goto out_unlock;
  65                        }
  66                        key = sta->key;
  67                }
  68
  69                ieee80211_key_free(key);
  70        } else {
  71                key = ieee80211_key_alloc(alg, idx, key_len, _key);
  72                if (!key)
  73                        return -ENOMEM;
  74
  75                sta = NULL;
  76                err = 0;
  77
  78                rcu_read_lock();
  79
  80                if (!is_broadcast_ether_addr(sta_addr)) {
  81                        set_tx_key = 0;
  82                        /*
  83                         * According to the standard, the key index of a
  84                         * pairwise key must be zero. However, some AP are
  85                         * broken when it comes to WEP key indices, so we
  86                         * work around this.
  87                         */
  88                        if (idx != 0 && alg != ALG_WEP) {
  89                                ieee80211_key_free(key);
  90                                err = -EINVAL;
  91                                goto out_unlock;
  92                        }
  93
  94                        sta = sta_info_get(local, sta_addr);
  95                        if (!sta) {
  96                                ieee80211_key_free(key);
  97                                err = -ENOENT;
  98                                goto out_unlock;
  99                        }
 100                }
 101
 102                if (alg == ALG_WEP &&
 103                        key_len != LEN_WEP40 && key_len != LEN_WEP104) {
 104                        ieee80211_key_free(key);
 105                        err = -EINVAL;
 106                        goto out_unlock;
 107                }
 108
 109                ieee80211_key_link(key, sdata, sta);
 110
 111                if (set_tx_key || (!sta && !sdata->default_key && key))
 112                        ieee80211_set_default_key(sdata, idx);
 113                if (alg == ALG_AES_CMAC &&
 114                    (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
 115                        ieee80211_set_default_mgmt_key(sdata, idx);
 116        }
 117
 118 out_unlock:
 119        rcu_read_unlock();
 120
 121        return err;
 122}
 123
 124static int ieee80211_ioctl_siwgenie(struct net_device *dev,
 125                                    struct iw_request_info *info,
 126                                    struct iw_point *data, char *extra)
 127{
 128        struct ieee80211_sub_if_data *sdata;
 129
 130        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 131
 132        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 133                int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
 134                if (ret)
 135                        return ret;
 136                sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
 137                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
 138                ieee80211_sta_req_auth(sdata);
 139                return 0;
 140        }
 141
 142        return -EOPNOTSUPP;
 143}
 144
 145static int ieee80211_ioctl_siwfreq(struct net_device *dev,
 146                                   struct iw_request_info *info,
 147                                   struct iw_freq *freq, char *extra)
 148{
 149        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 150
 151        if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 152                sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_CHANNEL_SEL;
 153        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
 154                sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
 155
 156        /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
 157        if (freq->e == 0) {
 158                if (freq->m < 0) {
 159                        if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 160                                sdata->u.ibss.flags |=
 161                                        IEEE80211_IBSS_AUTO_CHANNEL_SEL;
 162                        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
 163                                sdata->u.mgd.flags |=
 164                                        IEEE80211_STA_AUTO_CHANNEL_SEL;
 165                        return 0;
 166                } else
 167                        return ieee80211_set_freq(sdata,
 168                                ieee80211_channel_to_frequency(freq->m));
 169        } else {
 170                int i, div = 1000000;
 171                for (i = 0; i < freq->e; i++)
 172                        div /= 10;
 173                if (div > 0)
 174                        return ieee80211_set_freq(sdata, freq->m / div);
 175                else
 176                        return -EINVAL;
 177        }
 178}
 179
 180
 181static int ieee80211_ioctl_giwfreq(struct net_device *dev,
 182                                   struct iw_request_info *info,
 183                                   struct iw_freq *freq, char *extra)
 184{
 185        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 186
 187        freq->m = local->hw.conf.channel->center_freq;
 188        freq->e = 6;
 189
 190        return 0;
 191}
 192
 193
 194static int ieee80211_ioctl_siwessid(struct net_device *dev,
 195                                    struct iw_request_info *info,
 196                                    struct iw_point *data, char *ssid)
 197{
 198        struct ieee80211_sub_if_data *sdata;
 199        size_t len = data->length;
 200        int ret;
 201
 202        /* iwconfig uses nul termination in SSID.. */
 203        if (len > 0 && ssid[len - 1] == '\0')
 204                len--;
 205
 206        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 207        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 208                if (data->flags)
 209                        sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
 210                else
 211                        sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
 212
 213                ret = ieee80211_sta_set_ssid(sdata, ssid, len);
 214                if (ret)
 215                        return ret;
 216
 217                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
 218                ieee80211_sta_req_auth(sdata);
 219                return 0;
 220        } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 221                return ieee80211_ibss_set_ssid(sdata, ssid, len);
 222
 223        return -EOPNOTSUPP;
 224}
 225
 226
 227static int ieee80211_ioctl_giwessid(struct net_device *dev,
 228                                    struct iw_request_info *info,
 229                                    struct iw_point *data, char *ssid)
 230{
 231        size_t len;
 232
 233        struct ieee80211_sub_if_data *sdata;
 234        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 235        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 236                int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
 237                if (res == 0) {
 238                        data->length = len;
 239                        data->flags = 1;
 240                } else
 241                        data->flags = 0;
 242                return res;
 243        } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 244                int res = ieee80211_ibss_get_ssid(sdata, ssid, &len);
 245                if (res == 0) {
 246                        data->length = len;
 247                        data->flags = 1;
 248                } else
 249                        data->flags = 0;
 250                return res;
 251        }
 252
 253        return -EOPNOTSUPP;
 254}
 255
 256
 257static int ieee80211_ioctl_siwap(struct net_device *dev,
 258                                 struct iw_request_info *info,
 259                                 struct sockaddr *ap_addr, char *extra)
 260{
 261        struct ieee80211_sub_if_data *sdata;
 262
 263        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 264        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 265                int ret;
 266
 267                if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
 268                        sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
 269                                IEEE80211_STA_AUTO_CHANNEL_SEL;
 270                else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
 271                        sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
 272                else
 273                        sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
 274                ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
 275                if (ret)
 276                        return ret;
 277                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
 278                ieee80211_sta_req_auth(sdata);
 279                return 0;
 280        } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 281                if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
 282                        sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL |
 283                                               IEEE80211_IBSS_AUTO_CHANNEL_SEL;
 284                else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
 285                        sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL;
 286                else
 287                        sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_BSSID_SEL;
 288
 289                return ieee80211_ibss_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
 290        } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
 291                /*
 292                 * If it is necessary to update the WDS peer address
 293                 * while the interface is running, then we need to do
 294                 * more work here, namely if it is running we need to
 295                 * add a new and remove the old STA entry, this is
 296                 * normally handled by _open() and _stop().
 297                 */
 298                if (netif_running(dev))
 299                        return -EBUSY;
 300
 301                memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
 302                       ETH_ALEN);
 303
 304                return 0;
 305        }
 306
 307        return -EOPNOTSUPP;
 308}
 309
 310
 311static int ieee80211_ioctl_giwap(struct net_device *dev,
 312                                 struct iw_request_info *info,
 313                                 struct sockaddr *ap_addr, char *extra)
 314{
 315        struct ieee80211_sub_if_data *sdata;
 316
 317        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 318        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 319                if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) {
 320                        ap_addr->sa_family = ARPHRD_ETHER;
 321                        memcpy(&ap_addr->sa_data, sdata->u.mgd.bssid, ETH_ALEN);
 322                } else
 323                        memset(&ap_addr->sa_data, 0, ETH_ALEN);
 324                return 0;
 325        } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 326                if (sdata->u.ibss.state == IEEE80211_IBSS_MLME_JOINED) {
 327                        ap_addr->sa_family = ARPHRD_ETHER;
 328                        memcpy(&ap_addr->sa_data, sdata->u.ibss.bssid, ETH_ALEN);
 329                } else
 330                        memset(&ap_addr->sa_data, 0, ETH_ALEN);
 331                return 0;
 332        } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
 333                ap_addr->sa_family = ARPHRD_ETHER;
 334                memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
 335                return 0;
 336        }
 337
 338        return -EOPNOTSUPP;
 339}
 340
 341
 342static int ieee80211_ioctl_siwrate(struct net_device *dev,
 343                                  struct iw_request_info *info,
 344                                  struct iw_param *rate, char *extra)
 345{
 346        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 347        int i, err = -EINVAL;
 348        u32 target_rate = rate->value / 100000;
 349        struct ieee80211_sub_if_data *sdata;
 350        struct ieee80211_supported_band *sband;
 351
 352        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 353
 354        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 355
 356        /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
 357         * target_rate = X, rate->fixed = 1 means only rate X
 358         * target_rate = X, rate->fixed = 0 means all rates <= X */
 359        sdata->max_ratectrl_rateidx = -1;
 360        sdata->force_unicast_rateidx = -1;
 361        if (rate->value < 0)
 362                return 0;
 363
 364        for (i=0; i< sband->n_bitrates; i++) {
 365                struct ieee80211_rate *brate = &sband->bitrates[i];
 366                int this_rate = brate->bitrate;
 367
 368                if (target_rate == this_rate) {
 369                        sdata->max_ratectrl_rateidx = i;
 370                        if (rate->fixed)
 371                                sdata->force_unicast_rateidx = i;
 372                        err = 0;
 373                        break;
 374                }
 375        }
 376        return err;
 377}
 378
 379static int ieee80211_ioctl_giwrate(struct net_device *dev,
 380                                  struct iw_request_info *info,
 381                                  struct iw_param *rate, char *extra)
 382{
 383        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 384        struct sta_info *sta;
 385        struct ieee80211_sub_if_data *sdata;
 386        struct ieee80211_supported_band *sband;
 387
 388        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 389
 390        if (sdata->vif.type != NL80211_IFTYPE_STATION)
 391                return -EOPNOTSUPP;
 392
 393        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 394
 395        rcu_read_lock();
 396
 397        sta = sta_info_get(local, sdata->u.mgd.bssid);
 398
 399        if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
 400                rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
 401        else
 402                rate->value = 0;
 403
 404        rcu_read_unlock();
 405
 406        if (!sta)
 407                return -ENODEV;
 408
 409        rate->value *= 100000;
 410
 411        return 0;
 412}
 413
 414static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
 415                                      struct iw_request_info *info,
 416                                      union iwreq_data *data, char *extra)
 417{
 418        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 419        struct ieee80211_channel* chan = local->hw.conf.channel;
 420        bool reconf = false;
 421        u32 reconf_flags = 0;
 422        int new_power_level;
 423
 424        if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
 425                return -EINVAL;
 426        if (data->txpower.flags & IW_TXPOW_RANGE)
 427                return -EINVAL;
 428        if (!chan)
 429                return -EINVAL;
 430
 431        /* only change when not disabling */
 432        if (!data->txpower.disabled) {
 433                if (data->txpower.fixed) {
 434                        if (data->txpower.value < 0)
 435                                return -EINVAL;
 436                        new_power_level = data->txpower.value;
 437                        /*
 438                         * Debatable, but we cannot do a fixed power
 439                         * level above the regulatory constraint.
 440                         * Use "iwconfig wlan0 txpower 15dBm" instead.
 441                         */
 442                        if (new_power_level > chan->max_power)
 443                                return -EINVAL;
 444                } else {
 445                        /*
 446                         * Automatic power level setting, max being the value
 447                         * passed in from userland.
 448                         */
 449                        if (data->txpower.value < 0)
 450                                new_power_level = -1;
 451                        else
 452                                new_power_level = data->txpower.value;
 453                }
 454
 455                reconf = true;
 456
 457                /*
 458                 * ieee80211_hw_config() will limit to the channel's
 459                 * max power and possibly power constraint from AP.
 460                 */
 461                local->user_power_level = new_power_level;
 462        }
 463
 464        if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
 465                local->hw.conf.radio_enabled = !(data->txpower.disabled);
 466                reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
 467                ieee80211_led_radio(local, local->hw.conf.radio_enabled);
 468        }
 469
 470        if (reconf || reconf_flags)
 471                ieee80211_hw_config(local, reconf_flags);
 472
 473        return 0;
 474}
 475
 476static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
 477                                   struct iw_request_info *info,
 478                                   union iwreq_data *data, char *extra)
 479{
 480        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 481
 482        data->txpower.fixed = 1;
 483        data->txpower.disabled = !(local->hw.conf.radio_enabled);
 484        data->txpower.value = local->hw.conf.power_level;
 485        data->txpower.flags = IW_TXPOW_DBM;
 486
 487        return 0;
 488}
 489
 490static int ieee80211_ioctl_siwrts(struct net_device *dev,
 491                                  struct iw_request_info *info,
 492                                  struct iw_param *rts, char *extra)
 493{
 494        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 495
 496        if (rts->disabled)
 497                local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 498        else if (!rts->fixed)
 499                /* if the rts value is not fixed, then take default */
 500                local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 501        else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
 502                return -EINVAL;
 503        else
 504                local->rts_threshold = rts->value;
 505
 506        /* If the wlan card performs RTS/CTS in hardware/firmware,
 507         * configure it here */
 508
 509        if (local->ops->set_rts_threshold)
 510                local->ops->set_rts_threshold(local_to_hw(local),
 511                                             local->rts_threshold);
 512
 513        return 0;
 514}
 515
 516static int ieee80211_ioctl_giwrts(struct net_device *dev,
 517                                  struct iw_request_info *info,
 518                                  struct iw_param *rts, char *extra)
 519{
 520        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 521
 522        rts->value = local->rts_threshold;
 523        rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
 524        rts->fixed = 1;
 525
 526        return 0;
 527}
 528
 529
 530static int ieee80211_ioctl_siwfrag(struct net_device *dev,
 531                                   struct iw_request_info *info,
 532                                   struct iw_param *frag, char *extra)
 533{
 534        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 535
 536        if (frag->disabled)
 537                local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
 538        else if (!frag->fixed)
 539                local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
 540        else if (frag->value < 256 ||
 541                 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
 542                return -EINVAL;
 543        else {
 544                /* Fragment length must be even, so strip LSB. */
 545                local->fragmentation_threshold = frag->value & ~0x1;
 546        }
 547
 548        return 0;
 549}
 550
 551static int ieee80211_ioctl_giwfrag(struct net_device *dev,
 552                                   struct iw_request_info *info,
 553                                   struct iw_param *frag, char *extra)
 554{
 555        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 556
 557        frag->value = local->fragmentation_threshold;
 558        frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD);
 559        frag->fixed = 1;
 560
 561        return 0;
 562}
 563
 564
 565static int ieee80211_ioctl_siwretry(struct net_device *dev,
 566                                    struct iw_request_info *info,
 567                                    struct iw_param *retry, char *extra)
 568{
 569        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 570
 571        if (retry->disabled ||
 572            (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
 573                return -EINVAL;
 574
 575        if (retry->flags & IW_RETRY_MAX) {
 576                local->hw.conf.long_frame_max_tx_count = retry->value;
 577        } else if (retry->flags & IW_RETRY_MIN) {
 578                local->hw.conf.short_frame_max_tx_count = retry->value;
 579        } else {
 580                local->hw.conf.long_frame_max_tx_count = retry->value;
 581                local->hw.conf.short_frame_max_tx_count = retry->value;
 582        }
 583
 584        ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
 585
 586        return 0;
 587}
 588
 589
 590static int ieee80211_ioctl_giwretry(struct net_device *dev,
 591                                    struct iw_request_info *info,
 592                                    struct iw_param *retry, char *extra)
 593{
 594        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 595
 596        retry->disabled = 0;
 597        if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
 598                /* first return min value, iwconfig will ask max value
 599                 * later if needed */
 600                retry->flags |= IW_RETRY_LIMIT;
 601                retry->value = local->hw.conf.short_frame_max_tx_count;
 602                if (local->hw.conf.long_frame_max_tx_count !=
 603                    local->hw.conf.short_frame_max_tx_count)
 604                        retry->flags |= IW_RETRY_MIN;
 605                return 0;
 606        }
 607        if (retry->flags & IW_RETRY_MAX) {
 608                retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
 609                retry->value = local->hw.conf.long_frame_max_tx_count;
 610        }
 611
 612        return 0;
 613}
 614
 615static int ieee80211_ioctl_siwmlme(struct net_device *dev,
 616                                   struct iw_request_info *info,
 617                                   struct iw_point *data, char *extra)
 618{
 619        struct ieee80211_sub_if_data *sdata;
 620        struct iw_mlme *mlme = (struct iw_mlme *) extra;
 621
 622        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 623        if (!(sdata->vif.type == NL80211_IFTYPE_STATION))
 624                return -EINVAL;
 625
 626        switch (mlme->cmd) {
 627        case IW_MLME_DEAUTH:
 628                /* TODO: mlme->addr.sa_data */
 629                return ieee80211_sta_deauthenticate(sdata, mlme->reason_code);
 630        case IW_MLME_DISASSOC:
 631                /* TODO: mlme->addr.sa_data */
 632                return ieee80211_sta_disassociate(sdata, mlme->reason_code);
 633        default:
 634                return -EOPNOTSUPP;
 635        }
 636}
 637
 638
 639static int ieee80211_ioctl_siwencode(struct net_device *dev,
 640                                     struct iw_request_info *info,
 641                                     struct iw_point *erq, char *keybuf)
 642{
 643        struct ieee80211_sub_if_data *sdata;
 644        int idx, i, alg = ALG_WEP;
 645        u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 646        int remove = 0, ret;
 647
 648        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 649
 650        idx = erq->flags & IW_ENCODE_INDEX;
 651        if (idx == 0) {
 652                if (sdata->default_key)
 653                        for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 654                                if (sdata->default_key == sdata->keys[i]) {
 655                                        idx = i;
 656                                        break;
 657                                }
 658                        }
 659        } else if (idx < 1 || idx > 4)
 660                return -EINVAL;
 661        else
 662                idx--;
 663
 664        if (erq->flags & IW_ENCODE_DISABLED)
 665                remove = 1;
 666        else if (erq->length == 0) {
 667                /* No key data - just set the default TX key index */
 668                ieee80211_set_default_key(sdata, idx);
 669                return 0;
 670        }
 671
 672        ret = ieee80211_set_encryption(
 673                sdata, bcaddr,
 674                idx, alg, remove,
 675                !sdata->default_key,
 676                keybuf, erq->length);
 677
 678        if (!ret) {
 679                if (remove)
 680                        sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
 681                else
 682                        sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
 683        }
 684
 685        return ret;
 686}
 687
 688
 689static int ieee80211_ioctl_giwencode(struct net_device *dev,
 690                                     struct iw_request_info *info,
 691                                     struct iw_point *erq, char *key)
 692{
 693        struct ieee80211_sub_if_data *sdata;
 694        int idx, i;
 695
 696        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 697
 698        idx = erq->flags & IW_ENCODE_INDEX;
 699        if (idx < 1 || idx > 4) {
 700                idx = -1;
 701                if (!sdata->default_key)
 702                        idx = 0;
 703                else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 704                        if (sdata->default_key == sdata->keys[i]) {
 705                                idx = i;
 706                                break;
 707                        }
 708                }
 709                if (idx < 0)
 710                        return -EINVAL;
 711        } else
 712                idx--;
 713
 714        erq->flags = idx + 1;
 715
 716        if (!sdata->keys[idx]) {
 717                erq->length = 0;
 718                erq->flags |= IW_ENCODE_DISABLED;
 719                return 0;
 720        }
 721
 722        memcpy(key, sdata->keys[idx]->conf.key,
 723               min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
 724        erq->length = sdata->keys[idx]->conf.keylen;
 725        erq->flags |= IW_ENCODE_ENABLED;
 726
 727        if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 728                switch (sdata->u.mgd.auth_alg) {
 729                case WLAN_AUTH_OPEN:
 730                case WLAN_AUTH_LEAP:
 731                        erq->flags |= IW_ENCODE_OPEN;
 732                        break;
 733                case WLAN_AUTH_SHARED_KEY:
 734                        erq->flags |= IW_ENCODE_RESTRICTED;
 735                        break;
 736                }
 737        }
 738
 739        return 0;
 740}
 741
 742static int ieee80211_ioctl_siwpower(struct net_device *dev,
 743                                    struct iw_request_info *info,
 744                                    struct iw_param *wrq,
 745                                    char *extra)
 746{
 747        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 748        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 749        struct ieee80211_conf *conf = &local->hw.conf;
 750        int ret = 0, timeout = 0;
 751        bool ps;
 752
 753        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
 754                return -EOPNOTSUPP;
 755
 756        if (sdata->vif.type != NL80211_IFTYPE_STATION)
 757                return -EINVAL;
 758
 759        if (wrq->disabled) {
 760                ps = false;
 761                timeout = 0;
 762                goto set;
 763        }
 764
 765        switch (wrq->flags & IW_POWER_MODE) {
 766        case IW_POWER_ON:       /* If not specified */
 767        case IW_POWER_MODE:     /* If set all mask */
 768        case IW_POWER_ALL_R:    /* If explicitely state all */
 769                ps = true;
 770                break;
 771        default:                /* Otherwise we ignore */
 772                return -EINVAL;
 773        }
 774
 775        if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
 776                return -EINVAL;
 777
 778        if (wrq->flags & IW_POWER_TIMEOUT)
 779                timeout = wrq->value / 1000;
 780
 781 set:
 782        if (ps == local->powersave && timeout == conf->dynamic_ps_timeout)
 783                return ret;
 784
 785        local->powersave = ps;
 786        conf->dynamic_ps_timeout = timeout;
 787
 788        if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
 789                ret = ieee80211_hw_config(local,
 790                                          IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
 791
 792        if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
 793                return ret;
 794
 795        if (conf->dynamic_ps_timeout > 0 &&
 796            !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
 797                mod_timer(&local->dynamic_ps_timer, jiffies +
 798                          msecs_to_jiffies(conf->dynamic_ps_timeout));
 799        } else {
 800                if (local->powersave) {
 801                        if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
 802                                ieee80211_send_nullfunc(local, sdata, 1);
 803                        conf->flags |= IEEE80211_CONF_PS;
 804                        ret = ieee80211_hw_config(local,
 805                                        IEEE80211_CONF_CHANGE_PS);
 806                } else {
 807                        conf->flags &= ~IEEE80211_CONF_PS;
 808                        ret = ieee80211_hw_config(local,
 809                                        IEEE80211_CONF_CHANGE_PS);
 810                        if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
 811                                ieee80211_send_nullfunc(local, sdata, 0);
 812                        del_timer_sync(&local->dynamic_ps_timer);
 813                        cancel_work_sync(&local->dynamic_ps_enable_work);
 814                }
 815        }
 816
 817        return ret;
 818}
 819
 820static int ieee80211_ioctl_giwpower(struct net_device *dev,
 821                                    struct iw_request_info *info,
 822                                    union iwreq_data *wrqu,
 823                                    char *extra)
 824{
 825        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 826
 827        wrqu->power.disabled = !local->powersave;
 828
 829        return 0;
 830}
 831
 832static int ieee80211_ioctl_siwauth(struct net_device *dev,
 833                                   struct iw_request_info *info,
 834                                   struct iw_param *data, char *extra)
 835{
 836        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 837        int ret = 0;
 838
 839        switch (data->flags & IW_AUTH_INDEX) {
 840        case IW_AUTH_WPA_VERSION:
 841        case IW_AUTH_CIPHER_GROUP:
 842        case IW_AUTH_WPA_ENABLED:
 843        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
 844        case IW_AUTH_KEY_MGMT:
 845        case IW_AUTH_CIPHER_GROUP_MGMT:
 846                break;
 847        case IW_AUTH_CIPHER_PAIRWISE:
 848                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 849                        if (data->value & (IW_AUTH_CIPHER_WEP40 |
 850                            IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
 851                                sdata->u.mgd.flags |=
 852                                        IEEE80211_STA_TKIP_WEP_USED;
 853                        else
 854                                sdata->u.mgd.flags &=
 855                                        ~IEEE80211_STA_TKIP_WEP_USED;
 856                }
 857                break;
 858        case IW_AUTH_DROP_UNENCRYPTED:
 859                sdata->drop_unencrypted = !!data->value;
 860                break;
 861        case IW_AUTH_PRIVACY_INVOKED:
 862                if (sdata->vif.type != NL80211_IFTYPE_STATION)
 863                        ret = -EINVAL;
 864                else {
 865                        sdata->u.mgd.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
 866                        /*
 867                         * Privacy invoked by wpa_supplicant, store the
 868                         * value and allow associating to a protected
 869                         * network without having a key up front.
 870                         */
 871                        if (data->value)
 872                                sdata->u.mgd.flags |=
 873                                        IEEE80211_STA_PRIVACY_INVOKED;
 874                }
 875                break;
 876        case IW_AUTH_80211_AUTH_ALG:
 877                if (sdata->vif.type == NL80211_IFTYPE_STATION)
 878                        sdata->u.mgd.auth_algs = data->value;
 879                else
 880                        ret = -EOPNOTSUPP;
 881                break;
 882        case IW_AUTH_MFP:
 883                if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
 884                        ret = -EOPNOTSUPP;
 885                        break;
 886                }
 887                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 888                        switch (data->value) {
 889                        case IW_AUTH_MFP_DISABLED:
 890                                sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
 891                                break;
 892                        case IW_AUTH_MFP_OPTIONAL:
 893                                sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL;
 894                                break;
 895                        case IW_AUTH_MFP_REQUIRED:
 896                                sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
 897                                break;
 898                        default:
 899                                ret = -EINVAL;
 900                        }
 901                } else
 902                        ret = -EOPNOTSUPP;
 903                break;
 904        default:
 905                ret = -EOPNOTSUPP;
 906                break;
 907        }
 908        return ret;
 909}
 910
 911/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
 912static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
 913{
 914        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 915        struct iw_statistics *wstats = &local->wstats;
 916        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 917        struct sta_info *sta = NULL;
 918
 919        rcu_read_lock();
 920
 921        if (sdata->vif.type == NL80211_IFTYPE_STATION)
 922                sta = sta_info_get(local, sdata->u.mgd.bssid);
 923
 924        if (!sta) {
 925                wstats->discard.fragment = 0;
 926                wstats->discard.misc = 0;
 927                wstats->qual.qual = 0;
 928                wstats->qual.level = 0;
 929                wstats->qual.noise = 0;
 930                wstats->qual.updated = IW_QUAL_ALL_INVALID;
 931        } else {
 932                wstats->qual.updated = 0;
 933                /*
 934                 * mirror what cfg80211 does for iwrange/scan results,
 935                 * otherwise userspace gets confused.
 936                 */
 937                if (local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
 938                                       IEEE80211_HW_SIGNAL_DBM)) {
 939                        wstats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
 940                        wstats->qual.updated |= IW_QUAL_QUAL_UPDATED;
 941                } else {
 942                        wstats->qual.updated |= IW_QUAL_LEVEL_INVALID;
 943                        wstats->qual.updated |= IW_QUAL_QUAL_INVALID;
 944                }
 945
 946                if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
 947                        wstats->qual.level = sta->last_signal;
 948                        wstats->qual.qual = sta->last_signal;
 949                } else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
 950                        int sig = sta->last_signal;
 951
 952                        wstats->qual.updated |= IW_QUAL_DBM;
 953                        wstats->qual.level = sig;
 954                        if (sig < -110)
 955                                sig = -110;
 956                        else if (sig > -40)
 957                                sig = -40;
 958                        wstats->qual.qual = sig + 110;
 959                }
 960
 961                if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
 962                        /*
 963                         * This assumes that if driver reports noise, it also
 964                         * reports signal in dBm.
 965                         */
 966                        wstats->qual.noise = sta->last_noise;
 967                        wstats->qual.updated |= IW_QUAL_NOISE_UPDATED;
 968                } else {
 969                        wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
 970                }
 971        }
 972
 973        rcu_read_unlock();
 974
 975        return wstats;
 976}
 977
 978static int ieee80211_ioctl_giwauth(struct net_device *dev,
 979                                   struct iw_request_info *info,
 980                                   struct iw_param *data, char *extra)
 981{
 982        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 983        int ret = 0;
 984
 985        switch (data->flags & IW_AUTH_INDEX) {
 986        case IW_AUTH_80211_AUTH_ALG:
 987                if (sdata->vif.type == NL80211_IFTYPE_STATION)
 988                        data->value = sdata->u.mgd.auth_algs;
 989                else
 990                        ret = -EOPNOTSUPP;
 991                break;
 992        default:
 993                ret = -EOPNOTSUPP;
 994                break;
 995        }
 996        return ret;
 997}
 998
 999
1000static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1001                                        struct iw_request_info *info,
1002                                        struct iw_point *erq, char *extra)
1003{
1004        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1005        struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
1006        int uninitialized_var(alg), idx, i, remove = 0;
1007
1008        switch (ext->alg) {
1009        case IW_ENCODE_ALG_NONE:
1010                remove = 1;
1011                break;
1012        case IW_ENCODE_ALG_WEP:
1013                alg = ALG_WEP;
1014                break;
1015        case IW_ENCODE_ALG_TKIP:
1016                alg = ALG_TKIP;
1017                break;
1018        case IW_ENCODE_ALG_CCMP:
1019                alg = ALG_CCMP;
1020                break;
1021        case IW_ENCODE_ALG_AES_CMAC:
1022                alg = ALG_AES_CMAC;
1023                break;
1024        default:
1025                return -EOPNOTSUPP;
1026        }
1027
1028        if (erq->flags & IW_ENCODE_DISABLED)
1029                remove = 1;
1030
1031        idx = erq->flags & IW_ENCODE_INDEX;
1032        if (alg == ALG_AES_CMAC) {
1033                if (idx < NUM_DEFAULT_KEYS + 1 ||
1034                    idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
1035                        idx = -1;
1036                        if (!sdata->default_mgmt_key)
1037                                idx = 0;
1038                        else for (i = NUM_DEFAULT_KEYS;
1039                                  i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
1040                                  i++) {
1041                                if (sdata->default_mgmt_key == sdata->keys[i])
1042                                {
1043                                        idx = i;
1044                                        break;
1045                                }
1046                        }
1047                        if (idx < 0)
1048                                return -EINVAL;
1049                } else
1050                        idx--;
1051        } else {
1052                if (idx < 1 || idx > 4) {
1053                        idx = -1;
1054                        if (!sdata->default_key)
1055                                idx = 0;
1056                        else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1057                                if (sdata->default_key == sdata->keys[i]) {
1058                                        idx = i;
1059                                        break;
1060                                }
1061                        }
1062                        if (idx < 0)
1063                                return -EINVAL;
1064                } else
1065                        idx--;
1066        }
1067
1068        return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
1069                                        remove,
1070                                        ext->ext_flags &
1071                                        IW_ENCODE_EXT_SET_TX_KEY,
1072                                        ext->key, ext->key_len);
1073}
1074
1075
1076/* Structures to export the Wireless Handlers */
1077
1078static const iw_handler ieee80211_handler[] =
1079{
1080        (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
1081        (iw_handler) cfg80211_wext_giwname,             /* SIOCGIWNAME */
1082        (iw_handler) NULL,                              /* SIOCSIWNWID */
1083        (iw_handler) NULL,                              /* SIOCGIWNWID */
1084        (iw_handler) ieee80211_ioctl_siwfreq,           /* SIOCSIWFREQ */
1085        (iw_handler) ieee80211_ioctl_giwfreq,           /* SIOCGIWFREQ */
1086        (iw_handler) cfg80211_wext_siwmode,             /* SIOCSIWMODE */
1087        (iw_handler) cfg80211_wext_giwmode,             /* SIOCGIWMODE */
1088        (iw_handler) NULL,                              /* SIOCSIWSENS */
1089        (iw_handler) NULL,                              /* SIOCGIWSENS */
1090        (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
1091        (iw_handler) cfg80211_wext_giwrange,            /* SIOCGIWRANGE */
1092        (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
1093        (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
1094        (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
1095        (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
1096        (iw_handler) NULL,                              /* SIOCSIWSPY */
1097        (iw_handler) NULL,                              /* SIOCGIWSPY */
1098        (iw_handler) NULL,                              /* SIOCSIWTHRSPY */
1099        (iw_handler) NULL,                              /* SIOCGIWTHRSPY */
1100        (iw_handler) ieee80211_ioctl_siwap,             /* SIOCSIWAP */
1101        (iw_handler) ieee80211_ioctl_giwap,             /* SIOCGIWAP */
1102        (iw_handler) ieee80211_ioctl_siwmlme,           /* SIOCSIWMLME */
1103        (iw_handler) NULL,                              /* SIOCGIWAPLIST */
1104        (iw_handler) cfg80211_wext_siwscan,             /* SIOCSIWSCAN */
1105        (iw_handler) cfg80211_wext_giwscan,             /* SIOCGIWSCAN */
1106        (iw_handler) ieee80211_ioctl_siwessid,          /* SIOCSIWESSID */
1107        (iw_handler) ieee80211_ioctl_giwessid,          /* SIOCGIWESSID */
1108        (iw_handler) NULL,                              /* SIOCSIWNICKN */
1109        (iw_handler) NULL,                              /* SIOCGIWNICKN */
1110        (iw_handler) NULL,                              /* -- hole -- */
1111        (iw_handler) NULL,                              /* -- hole -- */
1112        (iw_handler) ieee80211_ioctl_siwrate,           /* SIOCSIWRATE */
1113        (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
1114        (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
1115        (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
1116        (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
1117        (iw_handler) ieee80211_ioctl_giwfrag,           /* SIOCGIWFRAG */
1118        (iw_handler) ieee80211_ioctl_siwtxpower,        /* SIOCSIWTXPOW */
1119        (iw_handler) ieee80211_ioctl_giwtxpower,        /* SIOCGIWTXPOW */
1120        (iw_handler) ieee80211_ioctl_siwretry,          /* SIOCSIWRETRY */
1121        (iw_handler) ieee80211_ioctl_giwretry,          /* SIOCGIWRETRY */
1122        (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
1123        (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
1124        (iw_handler) ieee80211_ioctl_siwpower,          /* SIOCSIWPOWER */
1125        (iw_handler) ieee80211_ioctl_giwpower,          /* SIOCGIWPOWER */
1126        (iw_handler) NULL,                              /* -- hole -- */
1127        (iw_handler) NULL,                              /* -- hole -- */
1128        (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
1129        (iw_handler) NULL,                              /* SIOCGIWGENIE */
1130        (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
1131        (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
1132        (iw_handler) ieee80211_ioctl_siwencodeext,      /* SIOCSIWENCODEEXT */
1133        (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
1134        (iw_handler) NULL,                              /* SIOCSIWPMKSA */
1135        (iw_handler) NULL,                              /* -- hole -- */
1136};
1137
1138const struct iw_handler_def ieee80211_iw_handler_def =
1139{
1140        .num_standard   = ARRAY_SIZE(ieee80211_handler),
1141        .standard       = (iw_handler *) ieee80211_handler,
1142        .get_wireless_stats = ieee80211_get_wireless_stats,
1143};
1144