linux/net/mac80211/ieee80211_ioctl.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 "ieee80211_rate.h"
  25#include "wpa.h"
  26#include "aes_ccm.h"
  27
  28
  29static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
  30                                    int idx, int alg, int remove,
  31                                    int set_tx_key, const u8 *_key,
  32                                    size_t key_len)
  33{
  34        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
  35        int ret = 0;
  36        struct sta_info *sta;
  37        struct ieee80211_key *key;
  38        struct ieee80211_sub_if_data *sdata;
  39
  40        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  41
  42        if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
  43                printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
  44                       dev->name, idx);
  45                return -EINVAL;
  46        }
  47
  48        if (is_broadcast_ether_addr(sta_addr)) {
  49                sta = NULL;
  50                key = sdata->keys[idx];
  51        } else {
  52                set_tx_key = 0;
  53                /*
  54                 * According to the standard, the key index of a pairwise
  55                 * key must be zero. However, some AP are broken when it
  56                 * comes to WEP key indices, so we work around this.
  57                 */
  58                if (idx != 0 && alg != ALG_WEP) {
  59                        printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
  60                               "individual key\n", dev->name);
  61                        return -EINVAL;
  62                }
  63
  64                sta = sta_info_get(local, sta_addr);
  65                if (!sta) {
  66#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
  67                        DECLARE_MAC_BUF(mac);
  68                        printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
  69                               "%s\n",
  70                               dev->name, print_mac(mac, sta_addr));
  71#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
  72
  73                        return -ENOENT;
  74                }
  75
  76                key = sta->key;
  77        }
  78
  79        if (remove) {
  80                ieee80211_key_free(key);
  81                key = NULL;
  82        } else {
  83                /*
  84                 * Automatically frees any old key if present.
  85                 */
  86                key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
  87                if (!key) {
  88                        ret = -ENOMEM;
  89                        goto err_out;
  90                }
  91        }
  92
  93        if (set_tx_key || (!sta && !sdata->default_key && key))
  94                ieee80211_set_default_key(sdata, idx);
  95
  96        ret = 0;
  97 err_out:
  98        if (sta)
  99                sta_info_put(sta);
 100        return ret;
 101}
 102
 103static int ieee80211_ioctl_siwgenie(struct net_device *dev,
 104                                    struct iw_request_info *info,
 105                                    struct iw_point *data, char *extra)
 106{
 107        struct ieee80211_sub_if_data *sdata;
 108
 109        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 110
 111        if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
 112                return -EOPNOTSUPP;
 113
 114        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 115            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 116                int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
 117                if (ret)
 118                        return ret;
 119                sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
 120                ieee80211_sta_req_auth(dev, &sdata->u.sta);
 121                return 0;
 122        }
 123
 124        return -EOPNOTSUPP;
 125}
 126
 127static int ieee80211_ioctl_giwname(struct net_device *dev,
 128                                   struct iw_request_info *info,
 129                                   char *name, char *extra)
 130{
 131        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 132
 133        switch (local->hw.conf.phymode) {
 134        case MODE_IEEE80211A:
 135                strcpy(name, "IEEE 802.11a");
 136                break;
 137        case MODE_IEEE80211B:
 138                strcpy(name, "IEEE 802.11b");
 139                break;
 140        case MODE_IEEE80211G:
 141                strcpy(name, "IEEE 802.11g");
 142                break;
 143        default:
 144                strcpy(name, "IEEE 802.11");
 145                break;
 146        }
 147
 148        return 0;
 149}
 150
 151
 152static int ieee80211_ioctl_giwrange(struct net_device *dev,
 153                                 struct iw_request_info *info,
 154                                 struct iw_point *data, char *extra)
 155{
 156        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 157        struct iw_range *range = (struct iw_range *) extra;
 158        struct ieee80211_hw_mode *mode = NULL;
 159        int c = 0;
 160
 161        data->length = sizeof(struct iw_range);
 162        memset(range, 0, sizeof(struct iw_range));
 163
 164        range->we_version_compiled = WIRELESS_EXT;
 165        range->we_version_source = 21;
 166        range->retry_capa = IW_RETRY_LIMIT;
 167        range->retry_flags = IW_RETRY_LIMIT;
 168        range->min_retry = 0;
 169        range->max_retry = 255;
 170        range->min_rts = 0;
 171        range->max_rts = 2347;
 172        range->min_frag = 256;
 173        range->max_frag = 2346;
 174
 175        range->encoding_size[0] = 5;
 176        range->encoding_size[1] = 13;
 177        range->num_encoding_sizes = 2;
 178        range->max_encoding_tokens = NUM_DEFAULT_KEYS;
 179
 180        range->max_qual.qual = local->hw.max_signal;
 181        range->max_qual.level = local->hw.max_rssi;
 182        range->max_qual.noise = local->hw.max_noise;
 183        range->max_qual.updated = local->wstats_flags;
 184
 185        range->avg_qual.qual = local->hw.max_signal/2;
 186        range->avg_qual.level = 0;
 187        range->avg_qual.noise = 0;
 188        range->avg_qual.updated = local->wstats_flags;
 189
 190        range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
 191                          IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
 192
 193        list_for_each_entry(mode, &local->modes_list, list) {
 194                int i = 0;
 195
 196                if (!(local->enabled_modes & (1 << mode->mode)) ||
 197                    (local->hw_modes & local->enabled_modes &
 198                     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
 199                        continue;
 200
 201                while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
 202                        struct ieee80211_channel *chan = &mode->channels[i];
 203
 204                        if (chan->flag & IEEE80211_CHAN_W_SCAN) {
 205                                range->freq[c].i = chan->chan;
 206                                range->freq[c].m = chan->freq * 100000;
 207                                range->freq[c].e = 1;
 208                                c++;
 209                        }
 210                        i++;
 211                }
 212        }
 213        range->num_channels = c;
 214        range->num_frequency = c;
 215
 216        IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
 217        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
 218        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
 219        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
 220
 221        return 0;
 222}
 223
 224
 225static int ieee80211_ioctl_siwmode(struct net_device *dev,
 226                                   struct iw_request_info *info,
 227                                   __u32 *mode, char *extra)
 228{
 229        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 230        int type;
 231
 232        if (sdata->type == IEEE80211_IF_TYPE_VLAN)
 233                return -EOPNOTSUPP;
 234
 235        switch (*mode) {
 236        case IW_MODE_INFRA:
 237                type = IEEE80211_IF_TYPE_STA;
 238                break;
 239        case IW_MODE_ADHOC:
 240                type = IEEE80211_IF_TYPE_IBSS;
 241                break;
 242        case IW_MODE_MONITOR:
 243                type = IEEE80211_IF_TYPE_MNTR;
 244                break;
 245        default:
 246                return -EINVAL;
 247        }
 248
 249        if (type == sdata->type)
 250                return 0;
 251        if (netif_running(dev))
 252                return -EBUSY;
 253
 254        ieee80211_if_reinit(dev);
 255        ieee80211_if_set_type(dev, type);
 256
 257        return 0;
 258}
 259
 260
 261static int ieee80211_ioctl_giwmode(struct net_device *dev,
 262                                   struct iw_request_info *info,
 263                                   __u32 *mode, char *extra)
 264{
 265        struct ieee80211_sub_if_data *sdata;
 266
 267        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 268        switch (sdata->type) {
 269        case IEEE80211_IF_TYPE_AP:
 270                *mode = IW_MODE_MASTER;
 271                break;
 272        case IEEE80211_IF_TYPE_STA:
 273                *mode = IW_MODE_INFRA;
 274                break;
 275        case IEEE80211_IF_TYPE_IBSS:
 276                *mode = IW_MODE_ADHOC;
 277                break;
 278        case IEEE80211_IF_TYPE_MNTR:
 279                *mode = IW_MODE_MONITOR;
 280                break;
 281        case IEEE80211_IF_TYPE_WDS:
 282                *mode = IW_MODE_REPEAT;
 283                break;
 284        case IEEE80211_IF_TYPE_VLAN:
 285                *mode = IW_MODE_SECOND;         /* FIXME */
 286                break;
 287        default:
 288                *mode = IW_MODE_AUTO;
 289                break;
 290        }
 291        return 0;
 292}
 293
 294int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
 295{
 296        struct ieee80211_hw_mode *mode;
 297        int c, set = 0;
 298        int ret = -EINVAL;
 299
 300        list_for_each_entry(mode, &local->modes_list, list) {
 301                if (!(local->enabled_modes & (1 << mode->mode)))
 302                        continue;
 303                for (c = 0; c < mode->num_channels; c++) {
 304                        struct ieee80211_channel *chan = &mode->channels[c];
 305                        if (chan->flag & IEEE80211_CHAN_W_SCAN &&
 306                            ((chan->chan == channel) || (chan->freq == freq))) {
 307                                local->oper_channel = chan;
 308                                local->oper_hw_mode = mode;
 309                                set = 1;
 310                                break;
 311                        }
 312                }
 313                if (set)
 314                        break;
 315        }
 316
 317        if (set) {
 318                if (local->sta_scanning)
 319                        ret = 0;
 320                else
 321                        ret = ieee80211_hw_config(local);
 322
 323                rate_control_clear(local);
 324        }
 325
 326        return ret;
 327}
 328
 329static int ieee80211_ioctl_siwfreq(struct net_device *dev,
 330                                   struct iw_request_info *info,
 331                                   struct iw_freq *freq, char *extra)
 332{
 333        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 334        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 335
 336        if (sdata->type == IEEE80211_IF_TYPE_STA)
 337                sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
 338
 339        /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
 340        if (freq->e == 0) {
 341                if (freq->m < 0) {
 342                        if (sdata->type == IEEE80211_IF_TYPE_STA)
 343                                sdata->u.sta.flags |=
 344                                        IEEE80211_STA_AUTO_CHANNEL_SEL;
 345                        return 0;
 346                } else
 347                        return ieee80211_set_channel(local, freq->m, -1);
 348        } else {
 349                int i, div = 1000000;
 350                for (i = 0; i < freq->e; i++)
 351                        div /= 10;
 352                if (div > 0)
 353                        return ieee80211_set_channel(local, -1, freq->m / div);
 354                else
 355                        return -EINVAL;
 356        }
 357}
 358
 359
 360static int ieee80211_ioctl_giwfreq(struct net_device *dev,
 361                                   struct iw_request_info *info,
 362                                   struct iw_freq *freq, char *extra)
 363{
 364        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 365
 366        /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
 367         * driver for the current channel with firmware-based management */
 368
 369        freq->m = local->hw.conf.freq;
 370        freq->e = 6;
 371
 372        return 0;
 373}
 374
 375
 376static int ieee80211_ioctl_siwessid(struct net_device *dev,
 377                                    struct iw_request_info *info,
 378                                    struct iw_point *data, char *ssid)
 379{
 380        struct ieee80211_sub_if_data *sdata;
 381        size_t len = data->length;
 382
 383        /* iwconfig uses nul termination in SSID.. */
 384        if (len > 0 && ssid[len - 1] == '\0')
 385                len--;
 386
 387        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 388        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 389            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 390                int ret;
 391                if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
 392                        if (len > IEEE80211_MAX_SSID_LEN)
 393                                return -EINVAL;
 394                        memcpy(sdata->u.sta.ssid, ssid, len);
 395                        sdata->u.sta.ssid_len = len;
 396                        return 0;
 397                }
 398                if (data->flags)
 399                        sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
 400                else
 401                        sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
 402                ret = ieee80211_sta_set_ssid(dev, ssid, len);
 403                if (ret)
 404                        return ret;
 405                ieee80211_sta_req_auth(dev, &sdata->u.sta);
 406                return 0;
 407        }
 408
 409        if (sdata->type == IEEE80211_IF_TYPE_AP) {
 410                memcpy(sdata->u.ap.ssid, ssid, len);
 411                memset(sdata->u.ap.ssid + len, 0,
 412                       IEEE80211_MAX_SSID_LEN - len);
 413                sdata->u.ap.ssid_len = len;
 414                return ieee80211_if_config(dev);
 415        }
 416        return -EOPNOTSUPP;
 417}
 418
 419
 420static int ieee80211_ioctl_giwessid(struct net_device *dev,
 421                                    struct iw_request_info *info,
 422                                    struct iw_point *data, char *ssid)
 423{
 424        size_t len;
 425
 426        struct ieee80211_sub_if_data *sdata;
 427        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 428        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 429            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 430                int res = ieee80211_sta_get_ssid(dev, ssid, &len);
 431                if (res == 0) {
 432                        data->length = len;
 433                        data->flags = 1;
 434                } else
 435                        data->flags = 0;
 436                return res;
 437        }
 438
 439        if (sdata->type == IEEE80211_IF_TYPE_AP) {
 440                len = sdata->u.ap.ssid_len;
 441                if (len > IW_ESSID_MAX_SIZE)
 442                        len = IW_ESSID_MAX_SIZE;
 443                memcpy(ssid, sdata->u.ap.ssid, len);
 444                data->length = len;
 445                data->flags = 1;
 446                return 0;
 447        }
 448        return -EOPNOTSUPP;
 449}
 450
 451
 452static int ieee80211_ioctl_siwap(struct net_device *dev,
 453                                 struct iw_request_info *info,
 454                                 struct sockaddr *ap_addr, char *extra)
 455{
 456        struct ieee80211_sub_if_data *sdata;
 457
 458        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 459        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 460            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 461                int ret;
 462                if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
 463                        memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
 464                               ETH_ALEN);
 465                        return 0;
 466                }
 467                if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
 468                        sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
 469                                IEEE80211_STA_AUTO_CHANNEL_SEL;
 470                else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
 471                        sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
 472                else
 473                        sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
 474                ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
 475                if (ret)
 476                        return ret;
 477                ieee80211_sta_req_auth(dev, &sdata->u.sta);
 478                return 0;
 479        } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 480                if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
 481                           ETH_ALEN) == 0)
 482                        return 0;
 483                return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
 484        }
 485
 486        return -EOPNOTSUPP;
 487}
 488
 489
 490static int ieee80211_ioctl_giwap(struct net_device *dev,
 491                                 struct iw_request_info *info,
 492                                 struct sockaddr *ap_addr, char *extra)
 493{
 494        struct ieee80211_sub_if_data *sdata;
 495
 496        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 497        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 498            sdata->type == IEEE80211_IF_TYPE_IBSS) {
 499                ap_addr->sa_family = ARPHRD_ETHER;
 500                memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
 501                return 0;
 502        } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 503                ap_addr->sa_family = ARPHRD_ETHER;
 504                memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
 505                return 0;
 506        }
 507
 508        return -EOPNOTSUPP;
 509}
 510
 511
 512static int ieee80211_ioctl_siwscan(struct net_device *dev,
 513                                   struct iw_request_info *info,
 514                                   union iwreq_data *wrqu, char *extra)
 515{
 516        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 517        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 518        struct iw_scan_req *req = NULL;
 519        u8 *ssid = NULL;
 520        size_t ssid_len = 0;
 521
 522        if (!netif_running(dev))
 523                return -ENETDOWN;
 524
 525        switch (sdata->type) {
 526        case IEEE80211_IF_TYPE_STA:
 527        case IEEE80211_IF_TYPE_IBSS:
 528                if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
 529                        ssid = sdata->u.sta.ssid;
 530                        ssid_len = sdata->u.sta.ssid_len;
 531                }
 532                break;
 533        case IEEE80211_IF_TYPE_AP:
 534                if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
 535                        ssid = sdata->u.ap.ssid;
 536                        ssid_len = sdata->u.ap.ssid_len;
 537                }
 538                break;
 539        default:
 540                return -EOPNOTSUPP;
 541        }
 542
 543        /* if SSID was specified explicitly then use that */
 544        if (wrqu->data.length == sizeof(struct iw_scan_req) &&
 545            wrqu->data.flags & IW_SCAN_THIS_ESSID) {
 546                req = (struct iw_scan_req *)extra;
 547                ssid = req->essid;
 548                ssid_len = req->essid_len;
 549        }
 550
 551        return ieee80211_sta_req_scan(dev, ssid, ssid_len);
 552}
 553
 554
 555static int ieee80211_ioctl_giwscan(struct net_device *dev,
 556                                   struct iw_request_info *info,
 557                                   struct iw_point *data, char *extra)
 558{
 559        int res;
 560        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 561        if (local->sta_scanning)
 562                return -EAGAIN;
 563        res = ieee80211_sta_scan_results(dev, extra, data->length);
 564        if (res >= 0) {
 565                data->length = res;
 566                return 0;
 567        }
 568        data->length = 0;
 569        return res;
 570}
 571
 572
 573static int ieee80211_ioctl_siwrate(struct net_device *dev,
 574                                  struct iw_request_info *info,
 575                                  struct iw_param *rate, char *extra)
 576{
 577        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 578        struct ieee80211_hw_mode *mode;
 579        int i;
 580        u32 target_rate = rate->value / 100000;
 581        struct ieee80211_sub_if_data *sdata;
 582
 583        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 584        if (!sdata->bss)
 585                return -ENODEV;
 586        mode = local->oper_hw_mode;
 587        /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
 588         * target_rate = X, rate->fixed = 1 means only rate X
 589         * target_rate = X, rate->fixed = 0 means all rates <= X */
 590        sdata->bss->max_ratectrl_rateidx = -1;
 591        sdata->bss->force_unicast_rateidx = -1;
 592        if (rate->value < 0)
 593                return 0;
 594        for (i=0; i < mode->num_rates; i++) {
 595                struct ieee80211_rate *rates = &mode->rates[i];
 596                int this_rate = rates->rate;
 597
 598                if (target_rate == this_rate) {
 599                        sdata->bss->max_ratectrl_rateidx = i;
 600                        if (rate->fixed)
 601                                sdata->bss->force_unicast_rateidx = i;
 602                        return 0;
 603                }
 604        }
 605        return -EINVAL;
 606}
 607
 608static int ieee80211_ioctl_giwrate(struct net_device *dev,
 609                                  struct iw_request_info *info,
 610                                  struct iw_param *rate, char *extra)
 611{
 612        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 613        struct sta_info *sta;
 614        struct ieee80211_sub_if_data *sdata;
 615
 616        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 617        if (sdata->type == IEEE80211_IF_TYPE_STA)
 618                sta = sta_info_get(local, sdata->u.sta.bssid);
 619        else
 620                return -EOPNOTSUPP;
 621        if (!sta)
 622                return -ENODEV;
 623        if (sta->txrate < local->oper_hw_mode->num_rates)
 624                rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
 625        else
 626                rate->value = 0;
 627        sta_info_put(sta);
 628        return 0;
 629}
 630
 631static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
 632                                      struct iw_request_info *info,
 633                                      union iwreq_data *data, char *extra)
 634{
 635        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 636        bool need_reconfig = 0;
 637
 638        if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
 639                return -EINVAL;
 640        if (data->txpower.flags & IW_TXPOW_RANGE)
 641                return -EINVAL;
 642        if (!data->txpower.fixed)
 643                return -EINVAL;
 644
 645        if (local->hw.conf.power_level != data->txpower.value) {
 646                local->hw.conf.power_level = data->txpower.value;
 647                need_reconfig = 1;
 648        }
 649        if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
 650                local->hw.conf.radio_enabled = !(data->txpower.disabled);
 651                need_reconfig = 1;
 652        }
 653        if (need_reconfig) {
 654                ieee80211_hw_config(local);
 655                /* The return value of hw_config is not of big interest here,
 656                 * as it doesn't say that it failed because of _this_ config
 657                 * change or something else. Ignore it. */
 658        }
 659
 660        return 0;
 661}
 662
 663static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
 664                                   struct iw_request_info *info,
 665                                   union iwreq_data *data, char *extra)
 666{
 667        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 668
 669        data->txpower.fixed = 1;
 670        data->txpower.disabled = !(local->hw.conf.radio_enabled);
 671        data->txpower.value = local->hw.conf.power_level;
 672        data->txpower.flags = IW_TXPOW_DBM;
 673
 674        return 0;
 675}
 676
 677static int ieee80211_ioctl_siwrts(struct net_device *dev,
 678                                  struct iw_request_info *info,
 679                                  struct iw_param *rts, char *extra)
 680{
 681        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 682
 683        if (rts->disabled)
 684                local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 685        else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
 686                return -EINVAL;
 687        else
 688                local->rts_threshold = rts->value;
 689
 690        /* If the wlan card performs RTS/CTS in hardware/firmware,
 691         * configure it here */
 692
 693        if (local->ops->set_rts_threshold)
 694                local->ops->set_rts_threshold(local_to_hw(local),
 695                                             local->rts_threshold);
 696
 697        return 0;
 698}
 699
 700static int ieee80211_ioctl_giwrts(struct net_device *dev,
 701                                  struct iw_request_info *info,
 702                                  struct iw_param *rts, char *extra)
 703{
 704        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 705
 706        rts->value = local->rts_threshold;
 707        rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
 708        rts->fixed = 1;
 709
 710        return 0;
 711}
 712
 713
 714static int ieee80211_ioctl_siwfrag(struct net_device *dev,
 715                                   struct iw_request_info *info,
 716                                   struct iw_param *frag, char *extra)
 717{
 718        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 719
 720        if (frag->disabled)
 721                local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
 722        else if (frag->value < 256 ||
 723                 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
 724                return -EINVAL;
 725        else {
 726                /* Fragment length must be even, so strip LSB. */
 727                local->fragmentation_threshold = frag->value & ~0x1;
 728        }
 729
 730        /* If the wlan card performs fragmentation in hardware/firmware,
 731         * configure it here */
 732
 733        if (local->ops->set_frag_threshold)
 734                local->ops->set_frag_threshold(
 735                        local_to_hw(local),
 736                        local->fragmentation_threshold);
 737
 738        return 0;
 739}
 740
 741static int ieee80211_ioctl_giwfrag(struct net_device *dev,
 742                                   struct iw_request_info *info,
 743                                   struct iw_param *frag, char *extra)
 744{
 745        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 746
 747        frag->value = local->fragmentation_threshold;
 748        frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
 749        frag->fixed = 1;
 750
 751        return 0;
 752}
 753
 754
 755static int ieee80211_ioctl_siwretry(struct net_device *dev,
 756                                    struct iw_request_info *info,
 757                                    struct iw_param *retry, char *extra)
 758{
 759        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 760
 761        if (retry->disabled ||
 762            (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
 763                return -EINVAL;
 764
 765        if (retry->flags & IW_RETRY_MAX)
 766                local->long_retry_limit = retry->value;
 767        else if (retry->flags & IW_RETRY_MIN)
 768                local->short_retry_limit = retry->value;
 769        else {
 770                local->long_retry_limit = retry->value;
 771                local->short_retry_limit = retry->value;
 772        }
 773
 774        if (local->ops->set_retry_limit) {
 775                return local->ops->set_retry_limit(
 776                        local_to_hw(local),
 777                        local->short_retry_limit,
 778                        local->long_retry_limit);
 779        }
 780
 781        return 0;
 782}
 783
 784
 785static int ieee80211_ioctl_giwretry(struct net_device *dev,
 786                                    struct iw_request_info *info,
 787                                    struct iw_param *retry, char *extra)
 788{
 789        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 790
 791        retry->disabled = 0;
 792        if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
 793                /* first return min value, iwconfig will ask max value
 794                 * later if needed */
 795                retry->flags |= IW_RETRY_LIMIT;
 796                retry->value = local->short_retry_limit;
 797                if (local->long_retry_limit != local->short_retry_limit)
 798                        retry->flags |= IW_RETRY_MIN;
 799                return 0;
 800        }
 801        if (retry->flags & IW_RETRY_MAX) {
 802                retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
 803                retry->value = local->long_retry_limit;
 804        }
 805
 806        return 0;
 807}
 808
 809static int ieee80211_ioctl_siwmlme(struct net_device *dev,
 810                                   struct iw_request_info *info,
 811                                   struct iw_point *data, char *extra)
 812{
 813        struct ieee80211_sub_if_data *sdata;
 814        struct iw_mlme *mlme = (struct iw_mlme *) extra;
 815
 816        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 817        if (sdata->type != IEEE80211_IF_TYPE_STA &&
 818            sdata->type != IEEE80211_IF_TYPE_IBSS)
 819                return -EINVAL;
 820
 821        switch (mlme->cmd) {
 822        case IW_MLME_DEAUTH:
 823                /* TODO: mlme->addr.sa_data */
 824                return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
 825        case IW_MLME_DISASSOC:
 826                /* TODO: mlme->addr.sa_data */
 827                return ieee80211_sta_disassociate(dev, mlme->reason_code);
 828        default:
 829                return -EOPNOTSUPP;
 830        }
 831}
 832
 833
 834static int ieee80211_ioctl_siwencode(struct net_device *dev,
 835                                     struct iw_request_info *info,
 836                                     struct iw_point *erq, char *keybuf)
 837{
 838        struct ieee80211_sub_if_data *sdata;
 839        int idx, i, alg = ALG_WEP;
 840        u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 841        int remove = 0;
 842
 843        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 844
 845        idx = erq->flags & IW_ENCODE_INDEX;
 846        if (idx == 0) {
 847                if (sdata->default_key)
 848                        for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 849                                if (sdata->default_key == sdata->keys[i]) {
 850                                        idx = i;
 851                                        break;
 852                                }
 853                        }
 854        } else if (idx < 1 || idx > 4)
 855                return -EINVAL;
 856        else
 857                idx--;
 858
 859        if (erq->flags & IW_ENCODE_DISABLED)
 860                remove = 1;
 861        else if (erq->length == 0) {
 862                /* No key data - just set the default TX key index */
 863                ieee80211_set_default_key(sdata, idx);
 864                return 0;
 865        }
 866
 867        return ieee80211_set_encryption(
 868                dev, bcaddr,
 869                idx, alg, remove,
 870                !sdata->default_key,
 871                keybuf, erq->length);
 872}
 873
 874
 875static int ieee80211_ioctl_giwencode(struct net_device *dev,
 876                                     struct iw_request_info *info,
 877                                     struct iw_point *erq, char *key)
 878{
 879        struct ieee80211_sub_if_data *sdata;
 880        int idx, i;
 881
 882        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 883
 884        idx = erq->flags & IW_ENCODE_INDEX;
 885        if (idx < 1 || idx > 4) {
 886                idx = -1;
 887                if (!sdata->default_key)
 888                        idx = 0;
 889                else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 890                        if (sdata->default_key == sdata->keys[i]) {
 891                                idx = i;
 892                                break;
 893                        }
 894                }
 895                if (idx < 0)
 896                        return -EINVAL;
 897        } else
 898                idx--;
 899
 900        erq->flags = idx + 1;
 901
 902        if (!sdata->keys[idx]) {
 903                erq->length = 0;
 904                erq->flags |= IW_ENCODE_DISABLED;
 905                return 0;
 906        }
 907
 908        memcpy(key, sdata->keys[idx]->conf.key,
 909               min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
 910        erq->length = sdata->keys[idx]->conf.keylen;
 911        erq->flags |= IW_ENCODE_ENABLED;
 912
 913        return 0;
 914}
 915
 916static int ieee80211_ioctl_siwauth(struct net_device *dev,
 917                                   struct iw_request_info *info,
 918                                   struct iw_param *data, char *extra)
 919{
 920        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 921        int ret = 0;
 922
 923        switch (data->flags & IW_AUTH_INDEX) {
 924        case IW_AUTH_WPA_VERSION:
 925        case IW_AUTH_CIPHER_PAIRWISE:
 926        case IW_AUTH_CIPHER_GROUP:
 927        case IW_AUTH_WPA_ENABLED:
 928        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
 929        case IW_AUTH_KEY_MGMT:
 930                break;
 931        case IW_AUTH_PRIVACY_INVOKED:
 932                if (sdata->type != IEEE80211_IF_TYPE_STA)
 933                        ret = -EINVAL;
 934                else {
 935                        sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
 936                        /*
 937                         * Privacy invoked by wpa_supplicant, store the
 938                         * value and allow associating to a protected
 939                         * network without having a key up front.
 940                         */
 941                        if (data->value)
 942                                sdata->u.sta.flags |=
 943                                        IEEE80211_STA_PRIVACY_INVOKED;
 944                }
 945                break;
 946        case IW_AUTH_80211_AUTH_ALG:
 947                if (sdata->type == IEEE80211_IF_TYPE_STA ||
 948                    sdata->type == IEEE80211_IF_TYPE_IBSS)
 949                        sdata->u.sta.auth_algs = data->value;
 950                else
 951                        ret = -EOPNOTSUPP;
 952                break;
 953        default:
 954                ret = -EOPNOTSUPP;
 955                break;
 956        }
 957        return ret;
 958}
 959
 960/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
 961static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
 962{
 963        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 964        struct iw_statistics *wstats = &local->wstats;
 965        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 966        struct sta_info *sta = NULL;
 967
 968        if (sdata->type == IEEE80211_IF_TYPE_STA ||
 969            sdata->type == IEEE80211_IF_TYPE_IBSS)
 970                sta = sta_info_get(local, sdata->u.sta.bssid);
 971        if (!sta) {
 972                wstats->discard.fragment = 0;
 973                wstats->discard.misc = 0;
 974                wstats->qual.qual = 0;
 975                wstats->qual.level = 0;
 976                wstats->qual.noise = 0;
 977                wstats->qual.updated = IW_QUAL_ALL_INVALID;
 978        } else {
 979                wstats->qual.level = sta->last_rssi;
 980                wstats->qual.qual = sta->last_signal;
 981                wstats->qual.noise = sta->last_noise;
 982                wstats->qual.updated = local->wstats_flags;
 983                sta_info_put(sta);
 984        }
 985        return wstats;
 986}
 987
 988static int ieee80211_ioctl_giwauth(struct net_device *dev,
 989                                   struct iw_request_info *info,
 990                                   struct iw_param *data, char *extra)
 991{
 992        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 993        int ret = 0;
 994
 995        switch (data->flags & IW_AUTH_INDEX) {
 996        case IW_AUTH_80211_AUTH_ALG:
 997                if (sdata->type == IEEE80211_IF_TYPE_STA ||
 998                    sdata->type == IEEE80211_IF_TYPE_IBSS)
 999                        data->value = sdata->u.sta.auth_algs;
1000                else
1001                        ret = -EOPNOTSUPP;
1002                break;
1003        default:
1004                ret = -EOPNOTSUPP;
1005                break;
1006        }
1007        return ret;
1008}
1009
1010
1011static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1012                                        struct iw_request_info *info,
1013                                        struct iw_point *erq, char *extra)
1014{
1015        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1016        struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
1017        int uninitialized_var(alg), idx, i, remove = 0;
1018
1019        switch (ext->alg) {
1020        case IW_ENCODE_ALG_NONE:
1021                remove = 1;
1022                break;
1023        case IW_ENCODE_ALG_WEP:
1024                alg = ALG_WEP;
1025                break;
1026        case IW_ENCODE_ALG_TKIP:
1027                alg = ALG_TKIP;
1028                break;
1029        case IW_ENCODE_ALG_CCMP:
1030                alg = ALG_CCMP;
1031                break;
1032        default:
1033                return -EOPNOTSUPP;
1034        }
1035
1036        if (erq->flags & IW_ENCODE_DISABLED)
1037                remove = 1;
1038
1039        idx = erq->flags & IW_ENCODE_INDEX;
1040        if (idx < 1 || idx > 4) {
1041                idx = -1;
1042                if (!sdata->default_key)
1043                        idx = 0;
1044                else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1045                        if (sdata->default_key == sdata->keys[i]) {
1046                                idx = i;
1047                                break;
1048                        }
1049                }
1050                if (idx < 0)
1051                        return -EINVAL;
1052        } else
1053                idx--;
1054
1055        return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
1056                                        remove,
1057                                        ext->ext_flags &
1058                                        IW_ENCODE_EXT_SET_TX_KEY,
1059                                        ext->key, ext->key_len);
1060}
1061
1062
1063/* Structures to export the Wireless Handlers */
1064
1065static const iw_handler ieee80211_handler[] =
1066{
1067        (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
1068        (iw_handler) ieee80211_ioctl_giwname,           /* SIOCGIWNAME */
1069        (iw_handler) NULL,                              /* SIOCSIWNWID */
1070        (iw_handler) NULL,                              /* SIOCGIWNWID */
1071        (iw_handler) ieee80211_ioctl_siwfreq,           /* SIOCSIWFREQ */
1072        (iw_handler) ieee80211_ioctl_giwfreq,           /* SIOCGIWFREQ */
1073        (iw_handler) ieee80211_ioctl_siwmode,           /* SIOCSIWMODE */
1074        (iw_handler) ieee80211_ioctl_giwmode,           /* SIOCGIWMODE */
1075        (iw_handler) NULL,                              /* SIOCSIWSENS */
1076        (iw_handler) NULL,                              /* SIOCGIWSENS */
1077        (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
1078        (iw_handler) ieee80211_ioctl_giwrange,          /* SIOCGIWRANGE */
1079        (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
1080        (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
1081        (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
1082        (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
1083        (iw_handler) NULL,                              /* SIOCSIWSPY */
1084        (iw_handler) NULL,                              /* SIOCGIWSPY */
1085        (iw_handler) NULL,                              /* SIOCSIWTHRSPY */
1086        (iw_handler) NULL,                              /* SIOCGIWTHRSPY */
1087        (iw_handler) ieee80211_ioctl_siwap,             /* SIOCSIWAP */
1088        (iw_handler) ieee80211_ioctl_giwap,             /* SIOCGIWAP */
1089        (iw_handler) ieee80211_ioctl_siwmlme,           /* SIOCSIWMLME */
1090        (iw_handler) NULL,                              /* SIOCGIWAPLIST */
1091        (iw_handler) ieee80211_ioctl_siwscan,           /* SIOCSIWSCAN */
1092        (iw_handler) ieee80211_ioctl_giwscan,           /* SIOCGIWSCAN */
1093        (iw_handler) ieee80211_ioctl_siwessid,          /* SIOCSIWESSID */
1094        (iw_handler) ieee80211_ioctl_giwessid,          /* SIOCGIWESSID */
1095        (iw_handler) NULL,                              /* SIOCSIWNICKN */
1096        (iw_handler) NULL,                              /* SIOCGIWNICKN */
1097        (iw_handler) NULL,                              /* -- hole -- */
1098        (iw_handler) NULL,                              /* -- hole -- */
1099        (iw_handler) ieee80211_ioctl_siwrate,           /* SIOCSIWRATE */
1100        (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
1101        (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
1102        (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
1103        (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
1104        (iw_handler) ieee80211_ioctl_giwfrag,           /* SIOCGIWFRAG */
1105        (iw_handler) ieee80211_ioctl_siwtxpower,        /* SIOCSIWTXPOW */
1106        (iw_handler) ieee80211_ioctl_giwtxpower,        /* SIOCGIWTXPOW */
1107        (iw_handler) ieee80211_ioctl_siwretry,          /* SIOCSIWRETRY */
1108        (iw_handler) ieee80211_ioctl_giwretry,          /* SIOCGIWRETRY */
1109        (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
1110        (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
1111        (iw_handler) NULL,                              /* SIOCSIWPOWER */
1112        (iw_handler) NULL,                              /* SIOCGIWPOWER */
1113        (iw_handler) NULL,                              /* -- hole -- */
1114        (iw_handler) NULL,                              /* -- hole -- */
1115        (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
1116        (iw_handler) NULL,                              /* SIOCGIWGENIE */
1117        (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
1118        (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
1119        (iw_handler) ieee80211_ioctl_siwencodeext,      /* SIOCSIWENCODEEXT */
1120        (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
1121        (iw_handler) NULL,                              /* SIOCSIWPMKSA */
1122        (iw_handler) NULL,                              /* -- hole -- */
1123};
1124
1125const struct iw_handler_def ieee80211_iw_handler_def =
1126{
1127        .num_standard   = ARRAY_SIZE(ieee80211_handler),
1128        .standard       = (iw_handler *) ieee80211_handler,
1129        .get_wireless_stats = ieee80211_get_wireless_stats,
1130};
1131