linux/net/mac80211/cfg.c
<<
>>
Prefs
   1/*
   2 * mac80211 configuration hooks for cfg80211
   3 *
   4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
   5 *
   6 * This file is GPLv2 as found in COPYING.
   7 */
   8
   9#include <linux/ieee80211.h>
  10#include <linux/nl80211.h>
  11#include <linux/rtnetlink.h>
  12#include <net/net_namespace.h>
  13#include <linux/rcupdate.h>
  14#include <net/cfg80211.h>
  15#include "ieee80211_i.h"
  16#include "driver-ops.h"
  17#include "cfg.h"
  18#include "rate.h"
  19#include "mesh.h"
  20
  21static bool nl80211_type_check(enum nl80211_iftype type)
  22{
  23        switch (type) {
  24        case NL80211_IFTYPE_ADHOC:
  25        case NL80211_IFTYPE_STATION:
  26        case NL80211_IFTYPE_MONITOR:
  27#ifdef CONFIG_MAC80211_MESH
  28        case NL80211_IFTYPE_MESH_POINT:
  29#endif
  30        case NL80211_IFTYPE_AP:
  31        case NL80211_IFTYPE_AP_VLAN:
  32        case NL80211_IFTYPE_WDS:
  33                return true;
  34        default:
  35                return false;
  36        }
  37}
  38
  39static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
  40                               enum nl80211_iftype type, u32 *flags,
  41                               struct vif_params *params)
  42{
  43        struct ieee80211_local *local = wiphy_priv(wiphy);
  44        struct net_device *dev;
  45        struct ieee80211_sub_if_data *sdata;
  46        int err;
  47
  48        if (!nl80211_type_check(type))
  49                return -EINVAL;
  50
  51        err = ieee80211_if_add(local, name, &dev, type, params);
  52        if (err || type != NL80211_IFTYPE_MONITOR || !flags)
  53                return err;
  54
  55        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  56        sdata->u.mntr_flags = *flags;
  57        return 0;
  58}
  59
  60static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev)
  61{
  62        ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev));
  63
  64        return 0;
  65}
  66
  67static int ieee80211_change_iface(struct wiphy *wiphy,
  68                                  struct net_device *dev,
  69                                  enum nl80211_iftype type, u32 *flags,
  70                                  struct vif_params *params)
  71{
  72        struct ieee80211_sub_if_data *sdata;
  73        int ret;
  74
  75        if (netif_running(dev))
  76                return -EBUSY;
  77
  78        if (!nl80211_type_check(type))
  79                return -EINVAL;
  80
  81        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  82
  83        ret = ieee80211_if_change_type(sdata, type);
  84        if (ret)
  85                return ret;
  86
  87        if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
  88                ieee80211_sdata_set_mesh_id(sdata,
  89                                            params->mesh_id_len,
  90                                            params->mesh_id);
  91
  92        if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
  93                return 0;
  94
  95        sdata->u.mntr_flags = *flags;
  96        return 0;
  97}
  98
  99static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 100                             u8 key_idx, const u8 *mac_addr,
 101                             struct key_params *params)
 102{
 103        struct ieee80211_sub_if_data *sdata;
 104        struct sta_info *sta = NULL;
 105        enum ieee80211_key_alg alg;
 106        struct ieee80211_key *key;
 107        int err;
 108
 109        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 110
 111        switch (params->cipher) {
 112        case WLAN_CIPHER_SUITE_WEP40:
 113        case WLAN_CIPHER_SUITE_WEP104:
 114                alg = ALG_WEP;
 115                break;
 116        case WLAN_CIPHER_SUITE_TKIP:
 117                alg = ALG_TKIP;
 118                break;
 119        case WLAN_CIPHER_SUITE_CCMP:
 120                alg = ALG_CCMP;
 121                break;
 122        case WLAN_CIPHER_SUITE_AES_CMAC:
 123                alg = ALG_AES_CMAC;
 124                break;
 125        default:
 126                return -EINVAL;
 127        }
 128
 129        key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key,
 130                                  params->seq_len, params->seq);
 131        if (!key)
 132                return -ENOMEM;
 133
 134        rcu_read_lock();
 135
 136        if (mac_addr) {
 137                sta = sta_info_get(sdata->local, mac_addr);
 138                if (!sta) {
 139                        ieee80211_key_free(key);
 140                        err = -ENOENT;
 141                        goto out_unlock;
 142                }
 143        }
 144
 145        ieee80211_key_link(key, sdata, sta);
 146
 147        err = 0;
 148 out_unlock:
 149        rcu_read_unlock();
 150
 151        return err;
 152}
 153
 154static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 155                             u8 key_idx, const u8 *mac_addr)
 156{
 157        struct ieee80211_sub_if_data *sdata;
 158        struct sta_info *sta;
 159        int ret;
 160
 161        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 162
 163        rcu_read_lock();
 164
 165        if (mac_addr) {
 166                ret = -ENOENT;
 167
 168                sta = sta_info_get(sdata->local, mac_addr);
 169                if (!sta)
 170                        goto out_unlock;
 171
 172                if (sta->key) {
 173                        ieee80211_key_free(sta->key);
 174                        WARN_ON(sta->key);
 175                        ret = 0;
 176                }
 177
 178                goto out_unlock;
 179        }
 180
 181        if (!sdata->keys[key_idx]) {
 182                ret = -ENOENT;
 183                goto out_unlock;
 184        }
 185
 186        ieee80211_key_free(sdata->keys[key_idx]);
 187        WARN_ON(sdata->keys[key_idx]);
 188
 189        ret = 0;
 190 out_unlock:
 191        rcu_read_unlock();
 192
 193        return ret;
 194}
 195
 196static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 197                             u8 key_idx, const u8 *mac_addr, void *cookie,
 198                             void (*callback)(void *cookie,
 199                                              struct key_params *params))
 200{
 201        struct ieee80211_sub_if_data *sdata;
 202        struct sta_info *sta = NULL;
 203        u8 seq[6] = {0};
 204        struct key_params params;
 205        struct ieee80211_key *key;
 206        u32 iv32;
 207        u16 iv16;
 208        int err = -ENOENT;
 209
 210        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 211
 212        rcu_read_lock();
 213
 214        if (mac_addr) {
 215                sta = sta_info_get(sdata->local, mac_addr);
 216                if (!sta)
 217                        goto out;
 218
 219                key = sta->key;
 220        } else
 221                key = sdata->keys[key_idx];
 222
 223        if (!key)
 224                goto out;
 225
 226        memset(&params, 0, sizeof(params));
 227
 228        switch (key->conf.alg) {
 229        case ALG_TKIP:
 230                params.cipher = WLAN_CIPHER_SUITE_TKIP;
 231
 232                iv32 = key->u.tkip.tx.iv32;
 233                iv16 = key->u.tkip.tx.iv16;
 234
 235                if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
 236                        drv_get_tkip_seq(sdata->local,
 237                                         key->conf.hw_key_idx,
 238                                         &iv32, &iv16);
 239
 240                seq[0] = iv16 & 0xff;
 241                seq[1] = (iv16 >> 8) & 0xff;
 242                seq[2] = iv32 & 0xff;
 243                seq[3] = (iv32 >> 8) & 0xff;
 244                seq[4] = (iv32 >> 16) & 0xff;
 245                seq[5] = (iv32 >> 24) & 0xff;
 246                params.seq = seq;
 247                params.seq_len = 6;
 248                break;
 249        case ALG_CCMP:
 250                params.cipher = WLAN_CIPHER_SUITE_CCMP;
 251                seq[0] = key->u.ccmp.tx_pn[5];
 252                seq[1] = key->u.ccmp.tx_pn[4];
 253                seq[2] = key->u.ccmp.tx_pn[3];
 254                seq[3] = key->u.ccmp.tx_pn[2];
 255                seq[4] = key->u.ccmp.tx_pn[1];
 256                seq[5] = key->u.ccmp.tx_pn[0];
 257                params.seq = seq;
 258                params.seq_len = 6;
 259                break;
 260        case ALG_WEP:
 261                if (key->conf.keylen == 5)
 262                        params.cipher = WLAN_CIPHER_SUITE_WEP40;
 263                else
 264                        params.cipher = WLAN_CIPHER_SUITE_WEP104;
 265                break;
 266        case ALG_AES_CMAC:
 267                params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
 268                seq[0] = key->u.aes_cmac.tx_pn[5];
 269                seq[1] = key->u.aes_cmac.tx_pn[4];
 270                seq[2] = key->u.aes_cmac.tx_pn[3];
 271                seq[3] = key->u.aes_cmac.tx_pn[2];
 272                seq[4] = key->u.aes_cmac.tx_pn[1];
 273                seq[5] = key->u.aes_cmac.tx_pn[0];
 274                params.seq = seq;
 275                params.seq_len = 6;
 276                break;
 277        }
 278
 279        params.key = key->conf.key;
 280        params.key_len = key->conf.keylen;
 281
 282        callback(cookie, &params);
 283        err = 0;
 284
 285 out:
 286        rcu_read_unlock();
 287        return err;
 288}
 289
 290static int ieee80211_config_default_key(struct wiphy *wiphy,
 291                                        struct net_device *dev,
 292                                        u8 key_idx)
 293{
 294        struct ieee80211_sub_if_data *sdata;
 295
 296        rcu_read_lock();
 297
 298        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 299        ieee80211_set_default_key(sdata, key_idx);
 300
 301        rcu_read_unlock();
 302
 303        return 0;
 304}
 305
 306static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
 307                                             struct net_device *dev,
 308                                             u8 key_idx)
 309{
 310        struct ieee80211_sub_if_data *sdata;
 311
 312        rcu_read_lock();
 313
 314        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 315        ieee80211_set_default_mgmt_key(sdata, key_idx);
 316
 317        rcu_read_unlock();
 318
 319        return 0;
 320}
 321
 322static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 323{
 324        struct ieee80211_sub_if_data *sdata = sta->sdata;
 325
 326        sinfo->generation = sdata->local->sta_generation;
 327
 328        sinfo->filled = STATION_INFO_INACTIVE_TIME |
 329                        STATION_INFO_RX_BYTES |
 330                        STATION_INFO_TX_BYTES |
 331                        STATION_INFO_RX_PACKETS |
 332                        STATION_INFO_TX_PACKETS |
 333                        STATION_INFO_TX_BITRATE;
 334
 335        sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 336        sinfo->rx_bytes = sta->rx_bytes;
 337        sinfo->tx_bytes = sta->tx_bytes;
 338        sinfo->rx_packets = sta->rx_packets;
 339        sinfo->tx_packets = sta->tx_packets;
 340
 341        if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
 342                sinfo->filled |= STATION_INFO_SIGNAL;
 343                sinfo->signal = (s8)sta->last_signal;
 344        }
 345
 346        sinfo->txrate.flags = 0;
 347        if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
 348                sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
 349        if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
 350                sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
 351        if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
 352                sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
 353
 354        if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
 355                struct ieee80211_supported_band *sband;
 356                sband = sta->local->hw.wiphy->bands[
 357                                sta->local->hw.conf.channel->band];
 358                sinfo->txrate.legacy =
 359                        sband->bitrates[sta->last_tx_rate.idx].bitrate;
 360        } else
 361                sinfo->txrate.mcs = sta->last_tx_rate.idx;
 362
 363        if (ieee80211_vif_is_mesh(&sdata->vif)) {
 364#ifdef CONFIG_MAC80211_MESH
 365                sinfo->filled |= STATION_INFO_LLID |
 366                                 STATION_INFO_PLID |
 367                                 STATION_INFO_PLINK_STATE;
 368
 369                sinfo->llid = le16_to_cpu(sta->llid);
 370                sinfo->plid = le16_to_cpu(sta->plid);
 371                sinfo->plink_state = sta->plink_state;
 372#endif
 373        }
 374}
 375
 376
 377static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
 378                                 int idx, u8 *mac, struct station_info *sinfo)
 379{
 380        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 381        struct sta_info *sta;
 382        int ret = -ENOENT;
 383
 384        rcu_read_lock();
 385
 386        sta = sta_info_get_by_idx(local, idx, dev);
 387        if (sta) {
 388                ret = 0;
 389                memcpy(mac, sta->sta.addr, ETH_ALEN);
 390                sta_set_sinfo(sta, sinfo);
 391        }
 392
 393        rcu_read_unlock();
 394
 395        return ret;
 396}
 397
 398static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 399                                 u8 *mac, struct station_info *sinfo)
 400{
 401        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 402        struct sta_info *sta;
 403        int ret = -ENOENT;
 404
 405        rcu_read_lock();
 406
 407        /* XXX: verify sta->dev == dev */
 408
 409        sta = sta_info_get(local, mac);
 410        if (sta) {
 411                ret = 0;
 412                sta_set_sinfo(sta, sinfo);
 413        }
 414
 415        rcu_read_unlock();
 416
 417        return ret;
 418}
 419
 420/*
 421 * This handles both adding a beacon and setting new beacon info
 422 */
 423static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 424                                   struct beacon_parameters *params)
 425{
 426        struct beacon_data *new, *old;
 427        int new_head_len, new_tail_len;
 428        int size;
 429        int err = -EINVAL;
 430
 431        old = sdata->u.ap.beacon;
 432
 433        /* head must not be zero-length */
 434        if (params->head && !params->head_len)
 435                return -EINVAL;
 436
 437        /*
 438         * This is a kludge. beacon interval should really be part
 439         * of the beacon information.
 440         */
 441        if (params->interval &&
 442            (sdata->vif.bss_conf.beacon_int != params->interval)) {
 443                sdata->vif.bss_conf.beacon_int = params->interval;
 444                ieee80211_bss_info_change_notify(sdata,
 445                                                 BSS_CHANGED_BEACON_INT);
 446        }
 447
 448        /* Need to have a beacon head if we don't have one yet */
 449        if (!params->head && !old)
 450                return err;
 451
 452        /* sorry, no way to start beaconing without dtim period */
 453        if (!params->dtim_period && !old)
 454                return err;
 455
 456        /* new or old head? */
 457        if (params->head)
 458                new_head_len = params->head_len;
 459        else
 460                new_head_len = old->head_len;
 461
 462        /* new or old tail? */
 463        if (params->tail || !old)
 464                /* params->tail_len will be zero for !params->tail */
 465                new_tail_len = params->tail_len;
 466        else
 467                new_tail_len = old->tail_len;
 468
 469        size = sizeof(*new) + new_head_len + new_tail_len;
 470
 471        new = kzalloc(size, GFP_KERNEL);
 472        if (!new)
 473                return -ENOMEM;
 474
 475        /* start filling the new info now */
 476
 477        /* new or old dtim period? */
 478        if (params->dtim_period)
 479                new->dtim_period = params->dtim_period;
 480        else
 481                new->dtim_period = old->dtim_period;
 482
 483        /*
 484         * pointers go into the block we allocated,
 485         * memory is | beacon_data | head | tail |
 486         */
 487        new->head = ((u8 *) new) + sizeof(*new);
 488        new->tail = new->head + new_head_len;
 489        new->head_len = new_head_len;
 490        new->tail_len = new_tail_len;
 491
 492        /* copy in head */
 493        if (params->head)
 494                memcpy(new->head, params->head, new_head_len);
 495        else
 496                memcpy(new->head, old->head, new_head_len);
 497
 498        /* copy in optional tail */
 499        if (params->tail)
 500                memcpy(new->tail, params->tail, new_tail_len);
 501        else
 502                if (old)
 503                        memcpy(new->tail, old->tail, new_tail_len);
 504
 505        rcu_assign_pointer(sdata->u.ap.beacon, new);
 506
 507        synchronize_rcu();
 508
 509        kfree(old);
 510
 511        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
 512                                                BSS_CHANGED_BEACON);
 513        return 0;
 514}
 515
 516static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
 517                                struct beacon_parameters *params)
 518{
 519        struct ieee80211_sub_if_data *sdata;
 520        struct beacon_data *old;
 521
 522        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 523
 524        old = sdata->u.ap.beacon;
 525
 526        if (old)
 527                return -EALREADY;
 528
 529        return ieee80211_config_beacon(sdata, params);
 530}
 531
 532static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 533                                struct beacon_parameters *params)
 534{
 535        struct ieee80211_sub_if_data *sdata;
 536        struct beacon_data *old;
 537
 538        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 539
 540        old = sdata->u.ap.beacon;
 541
 542        if (!old)
 543                return -ENOENT;
 544
 545        return ieee80211_config_beacon(sdata, params);
 546}
 547
 548static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
 549{
 550        struct ieee80211_sub_if_data *sdata;
 551        struct beacon_data *old;
 552
 553        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 554
 555        old = sdata->u.ap.beacon;
 556
 557        if (!old)
 558                return -ENOENT;
 559
 560        rcu_assign_pointer(sdata->u.ap.beacon, NULL);
 561        synchronize_rcu();
 562        kfree(old);
 563
 564        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
 565        return 0;
 566}
 567
 568/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
 569struct iapp_layer2_update {
 570        u8 da[ETH_ALEN];        /* broadcast */
 571        u8 sa[ETH_ALEN];        /* STA addr */
 572        __be16 len;             /* 6 */
 573        u8 dsap;                /* 0 */
 574        u8 ssap;                /* 0 */
 575        u8 control;
 576        u8 xid_info[3];
 577} __attribute__ ((packed));
 578
 579static void ieee80211_send_layer2_update(struct sta_info *sta)
 580{
 581        struct iapp_layer2_update *msg;
 582        struct sk_buff *skb;
 583
 584        /* Send Level 2 Update Frame to update forwarding tables in layer 2
 585         * bridge devices */
 586
 587        skb = dev_alloc_skb(sizeof(*msg));
 588        if (!skb)
 589                return;
 590        msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
 591
 592        /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
 593         * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
 594
 595        memset(msg->da, 0xff, ETH_ALEN);
 596        memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
 597        msg->len = htons(6);
 598        msg->dsap = 0;
 599        msg->ssap = 0x01;       /* NULL LSAP, CR Bit: Response */
 600        msg->control = 0xaf;    /* XID response lsb.1111F101.
 601                                 * F=0 (no poll command; unsolicited frame) */
 602        msg->xid_info[0] = 0x81;        /* XID format identifier */
 603        msg->xid_info[1] = 1;   /* LLC types/classes: Type 1 LLC */
 604        msg->xid_info[2] = 0;   /* XID sender's receive window size (RW) */
 605
 606        skb->dev = sta->sdata->dev;
 607        skb->protocol = eth_type_trans(skb, sta->sdata->dev);
 608        memset(skb->cb, 0, sizeof(skb->cb));
 609        netif_rx(skb);
 610}
 611
 612static void sta_apply_parameters(struct ieee80211_local *local,
 613                                 struct sta_info *sta,
 614                                 struct station_parameters *params)
 615{
 616        u32 rates;
 617        int i, j;
 618        struct ieee80211_supported_band *sband;
 619        struct ieee80211_sub_if_data *sdata = sta->sdata;
 620        u32 mask, set;
 621
 622        sband = local->hw.wiphy->bands[local->oper_channel->band];
 623
 624        spin_lock_bh(&sta->lock);
 625        mask = params->sta_flags_mask;
 626        set = params->sta_flags_set;
 627
 628        if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
 629                sta->flags &= ~WLAN_STA_AUTHORIZED;
 630                if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
 631                        sta->flags |= WLAN_STA_AUTHORIZED;
 632        }
 633
 634        if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
 635                sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
 636                if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
 637                        sta->flags |= WLAN_STA_SHORT_PREAMBLE;
 638        }
 639
 640        if (mask & BIT(NL80211_STA_FLAG_WME)) {
 641                sta->flags &= ~WLAN_STA_WME;
 642                if (set & BIT(NL80211_STA_FLAG_WME))
 643                        sta->flags |= WLAN_STA_WME;
 644        }
 645
 646        if (mask & BIT(NL80211_STA_FLAG_MFP)) {
 647                sta->flags &= ~WLAN_STA_MFP;
 648                if (set & BIT(NL80211_STA_FLAG_MFP))
 649                        sta->flags |= WLAN_STA_MFP;
 650        }
 651        spin_unlock_bh(&sta->lock);
 652
 653        /*
 654         * cfg80211 validates this (1-2007) and allows setting the AID
 655         * only when creating a new station entry
 656         */
 657        if (params->aid)
 658                sta->sta.aid = params->aid;
 659
 660        /*
 661         * FIXME: updating the following information is racy when this
 662         *        function is called from ieee80211_change_station().
 663         *        However, all this information should be static so
 664         *        maybe we should just reject attemps to change it.
 665         */
 666
 667        if (params->listen_interval >= 0)
 668                sta->listen_interval = params->listen_interval;
 669
 670        if (params->supported_rates) {
 671                rates = 0;
 672
 673                for (i = 0; i < params->supported_rates_len; i++) {
 674                        int rate = (params->supported_rates[i] & 0x7f) * 5;
 675                        for (j = 0; j < sband->n_bitrates; j++) {
 676                                if (sband->bitrates[j].bitrate == rate)
 677                                        rates |= BIT(j);
 678                        }
 679                }
 680                sta->sta.supp_rates[local->oper_channel->band] = rates;
 681        }
 682
 683        if (params->ht_capa)
 684                ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
 685                                                  params->ht_capa,
 686                                                  &sta->sta.ht_cap);
 687
 688        if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
 689                switch (params->plink_action) {
 690                case PLINK_ACTION_OPEN:
 691                        mesh_plink_open(sta);
 692                        break;
 693                case PLINK_ACTION_BLOCK:
 694                        mesh_plink_block(sta);
 695                        break;
 696                }
 697        }
 698}
 699
 700static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 701                                 u8 *mac, struct station_parameters *params)
 702{
 703        struct ieee80211_local *local = wiphy_priv(wiphy);
 704        struct sta_info *sta;
 705        struct ieee80211_sub_if_data *sdata;
 706        int err;
 707        int layer2_update;
 708
 709        if (params->vlan) {
 710                sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 711
 712                if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 713                    sdata->vif.type != NL80211_IFTYPE_AP)
 714                        return -EINVAL;
 715        } else
 716                sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 717
 718        if (compare_ether_addr(mac, dev->dev_addr) == 0)
 719                return -EINVAL;
 720
 721        if (is_multicast_ether_addr(mac))
 722                return -EINVAL;
 723
 724        sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
 725        if (!sta)
 726                return -ENOMEM;
 727
 728        sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
 729
 730        sta_apply_parameters(local, sta, params);
 731
 732        rate_control_rate_init(sta);
 733
 734        layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 735                sdata->vif.type == NL80211_IFTYPE_AP;
 736
 737        rcu_read_lock();
 738
 739        err = sta_info_insert(sta);
 740        if (err) {
 741                /* STA has been freed */
 742                if (err == -EEXIST && layer2_update) {
 743                        /* Need to update layer 2 devices on reassociation */
 744                        sta = sta_info_get(local, mac);
 745                        if (sta)
 746                                ieee80211_send_layer2_update(sta);
 747                }
 748                rcu_read_unlock();
 749                return err;
 750        }
 751
 752        if (layer2_update)
 753                ieee80211_send_layer2_update(sta);
 754
 755        rcu_read_unlock();
 756
 757        return 0;
 758}
 759
 760static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
 761                                 u8 *mac)
 762{
 763        struct ieee80211_local *local = wiphy_priv(wiphy);
 764        struct ieee80211_sub_if_data *sdata;
 765        struct sta_info *sta;
 766
 767        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 768
 769        if (mac) {
 770                rcu_read_lock();
 771
 772                /* XXX: get sta belonging to dev */
 773                sta = sta_info_get(local, mac);
 774                if (!sta) {
 775                        rcu_read_unlock();
 776                        return -ENOENT;
 777                }
 778
 779                sta_info_unlink(&sta);
 780                rcu_read_unlock();
 781
 782                sta_info_destroy(sta);
 783        } else
 784                sta_info_flush(local, sdata);
 785
 786        return 0;
 787}
 788
 789static int ieee80211_change_station(struct wiphy *wiphy,
 790                                    struct net_device *dev,
 791                                    u8 *mac,
 792                                    struct station_parameters *params)
 793{
 794        struct ieee80211_local *local = wiphy_priv(wiphy);
 795        struct sta_info *sta;
 796        struct ieee80211_sub_if_data *vlansdata;
 797
 798        rcu_read_lock();
 799
 800        /* XXX: get sta belonging to dev */
 801        sta = sta_info_get(local, mac);
 802        if (!sta) {
 803                rcu_read_unlock();
 804                return -ENOENT;
 805        }
 806
 807        if (params->vlan && params->vlan != sta->sdata->dev) {
 808                vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 809
 810                if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 811                    vlansdata->vif.type != NL80211_IFTYPE_AP) {
 812                        rcu_read_unlock();
 813                        return -EINVAL;
 814                }
 815
 816                sta->sdata = vlansdata;
 817                ieee80211_send_layer2_update(sta);
 818        }
 819
 820        sta_apply_parameters(local, sta, params);
 821
 822        rcu_read_unlock();
 823
 824        return 0;
 825}
 826
 827#ifdef CONFIG_MAC80211_MESH
 828static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
 829                                 u8 *dst, u8 *next_hop)
 830{
 831        struct ieee80211_local *local = wiphy_priv(wiphy);
 832        struct ieee80211_sub_if_data *sdata;
 833        struct mesh_path *mpath;
 834        struct sta_info *sta;
 835        int err;
 836
 837        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 838
 839        rcu_read_lock();
 840        sta = sta_info_get(local, next_hop);
 841        if (!sta) {
 842                rcu_read_unlock();
 843                return -ENOENT;
 844        }
 845
 846        err = mesh_path_add(dst, sdata);
 847        if (err) {
 848                rcu_read_unlock();
 849                return err;
 850        }
 851
 852        mpath = mesh_path_lookup(dst, sdata);
 853        if (!mpath) {
 854                rcu_read_unlock();
 855                return -ENXIO;
 856        }
 857        mesh_path_fix_nexthop(mpath, sta);
 858
 859        rcu_read_unlock();
 860        return 0;
 861}
 862
 863static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
 864                                 u8 *dst)
 865{
 866        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 867
 868        if (dst)
 869                return mesh_path_del(dst, sdata);
 870
 871        mesh_path_flush(sdata);
 872        return 0;
 873}
 874
 875static int ieee80211_change_mpath(struct wiphy *wiphy,
 876                                    struct net_device *dev,
 877                                    u8 *dst, u8 *next_hop)
 878{
 879        struct ieee80211_local *local = wiphy_priv(wiphy);
 880        struct ieee80211_sub_if_data *sdata;
 881        struct mesh_path *mpath;
 882        struct sta_info *sta;
 883
 884        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 885
 886        rcu_read_lock();
 887
 888        sta = sta_info_get(local, next_hop);
 889        if (!sta) {
 890                rcu_read_unlock();
 891                return -ENOENT;
 892        }
 893
 894        mpath = mesh_path_lookup(dst, sdata);
 895        if (!mpath) {
 896                rcu_read_unlock();
 897                return -ENOENT;
 898        }
 899
 900        mesh_path_fix_nexthop(mpath, sta);
 901
 902        rcu_read_unlock();
 903        return 0;
 904}
 905
 906static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
 907                            struct mpath_info *pinfo)
 908{
 909        if (mpath->next_hop)
 910                memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
 911        else
 912                memset(next_hop, 0, ETH_ALEN);
 913
 914        pinfo->generation = mesh_paths_generation;
 915
 916        pinfo->filled = MPATH_INFO_FRAME_QLEN |
 917                        MPATH_INFO_DSN |
 918                        MPATH_INFO_METRIC |
 919                        MPATH_INFO_EXPTIME |
 920                        MPATH_INFO_DISCOVERY_TIMEOUT |
 921                        MPATH_INFO_DISCOVERY_RETRIES |
 922                        MPATH_INFO_FLAGS;
 923
 924        pinfo->frame_qlen = mpath->frame_queue.qlen;
 925        pinfo->dsn = mpath->dsn;
 926        pinfo->metric = mpath->metric;
 927        if (time_before(jiffies, mpath->exp_time))
 928                pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
 929        pinfo->discovery_timeout =
 930                        jiffies_to_msecs(mpath->discovery_timeout);
 931        pinfo->discovery_retries = mpath->discovery_retries;
 932        pinfo->flags = 0;
 933        if (mpath->flags & MESH_PATH_ACTIVE)
 934                pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
 935        if (mpath->flags & MESH_PATH_RESOLVING)
 936                pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
 937        if (mpath->flags & MESH_PATH_DSN_VALID)
 938                pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
 939        if (mpath->flags & MESH_PATH_FIXED)
 940                pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
 941        if (mpath->flags & MESH_PATH_RESOLVING)
 942                pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
 943
 944        pinfo->flags = mpath->flags;
 945}
 946
 947static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
 948                               u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
 949
 950{
 951        struct ieee80211_sub_if_data *sdata;
 952        struct mesh_path *mpath;
 953
 954        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 955
 956        rcu_read_lock();
 957        mpath = mesh_path_lookup(dst, sdata);
 958        if (!mpath) {
 959                rcu_read_unlock();
 960                return -ENOENT;
 961        }
 962        memcpy(dst, mpath->dst, ETH_ALEN);
 963        mpath_set_pinfo(mpath, next_hop, pinfo);
 964        rcu_read_unlock();
 965        return 0;
 966}
 967
 968static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
 969                                 int idx, u8 *dst, u8 *next_hop,
 970                                 struct mpath_info *pinfo)
 971{
 972        struct ieee80211_sub_if_data *sdata;
 973        struct mesh_path *mpath;
 974
 975        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 976
 977        rcu_read_lock();
 978        mpath = mesh_path_lookup_by_idx(idx, sdata);
 979        if (!mpath) {
 980                rcu_read_unlock();
 981                return -ENOENT;
 982        }
 983        memcpy(dst, mpath->dst, ETH_ALEN);
 984        mpath_set_pinfo(mpath, next_hop, pinfo);
 985        rcu_read_unlock();
 986        return 0;
 987}
 988
 989static int ieee80211_get_mesh_params(struct wiphy *wiphy,
 990                                struct net_device *dev,
 991                                struct mesh_config *conf)
 992{
 993        struct ieee80211_sub_if_data *sdata;
 994        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 995
 996        memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config));
 997        return 0;
 998}
 999
1000static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
1001{
1002        return (mask >> (parm-1)) & 0x1;
1003}
1004
1005static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1006                                struct net_device *dev,
1007                                const struct mesh_config *nconf, u32 mask)
1008{
1009        struct mesh_config *conf;
1010        struct ieee80211_sub_if_data *sdata;
1011        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1012
1013        /* Set the config options which we are interested in setting */
1014        conf = &(sdata->u.mesh.mshcfg);
1015        if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask))
1016                conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout;
1017        if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask))
1018                conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout;
1019        if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask))
1020                conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout;
1021        if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask))
1022                conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks;
1023        if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask))
1024                conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries;
1025        if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
1026                conf->dot11MeshTTL = nconf->dot11MeshTTL;
1027        if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
1028                conf->auto_open_plinks = nconf->auto_open_plinks;
1029        if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
1030                conf->dot11MeshHWMPmaxPREQretries =
1031                        nconf->dot11MeshHWMPmaxPREQretries;
1032        if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))
1033                conf->path_refresh_time = nconf->path_refresh_time;
1034        if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))
1035                conf->min_discovery_timeout = nconf->min_discovery_timeout;
1036        if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))
1037                conf->dot11MeshHWMPactivePathTimeout =
1038                        nconf->dot11MeshHWMPactivePathTimeout;
1039        if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
1040                conf->dot11MeshHWMPpreqMinInterval =
1041                        nconf->dot11MeshHWMPpreqMinInterval;
1042        if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
1043                           mask))
1044                conf->dot11MeshHWMPnetDiameterTraversalTime =
1045                        nconf->dot11MeshHWMPnetDiameterTraversalTime;
1046        return 0;
1047}
1048
1049#endif
1050
1051static int ieee80211_change_bss(struct wiphy *wiphy,
1052                                struct net_device *dev,
1053                                struct bss_parameters *params)
1054{
1055        struct ieee80211_sub_if_data *sdata;
1056        u32 changed = 0;
1057
1058        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1059
1060        if (params->use_cts_prot >= 0) {
1061                sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
1062                changed |= BSS_CHANGED_ERP_CTS_PROT;
1063        }
1064        if (params->use_short_preamble >= 0) {
1065                sdata->vif.bss_conf.use_short_preamble =
1066                        params->use_short_preamble;
1067                changed |= BSS_CHANGED_ERP_PREAMBLE;
1068        }
1069        if (params->use_short_slot_time >= 0) {
1070                sdata->vif.bss_conf.use_short_slot =
1071                        params->use_short_slot_time;
1072                changed |= BSS_CHANGED_ERP_SLOT;
1073        }
1074
1075        if (params->basic_rates) {
1076                int i, j;
1077                u32 rates = 0;
1078                struct ieee80211_local *local = wiphy_priv(wiphy);
1079                struct ieee80211_supported_band *sband =
1080                        wiphy->bands[local->oper_channel->band];
1081
1082                for (i = 0; i < params->basic_rates_len; i++) {
1083                        int rate = (params->basic_rates[i] & 0x7f) * 5;
1084                        for (j = 0; j < sband->n_bitrates; j++) {
1085                                if (sband->bitrates[j].bitrate == rate)
1086                                        rates |= BIT(j);
1087                        }
1088                }
1089                sdata->vif.bss_conf.basic_rates = rates;
1090                changed |= BSS_CHANGED_BASIC_RATES;
1091        }
1092
1093        ieee80211_bss_info_change_notify(sdata, changed);
1094
1095        return 0;
1096}
1097
1098static int ieee80211_set_txq_params(struct wiphy *wiphy,
1099                                    struct ieee80211_txq_params *params)
1100{
1101        struct ieee80211_local *local = wiphy_priv(wiphy);
1102        struct ieee80211_tx_queue_params p;
1103
1104        if (!local->ops->conf_tx)
1105                return -EOPNOTSUPP;
1106
1107        memset(&p, 0, sizeof(p));
1108        p.aifs = params->aifs;
1109        p.cw_max = params->cwmax;
1110        p.cw_min = params->cwmin;
1111        p.txop = params->txop;
1112        if (drv_conf_tx(local, params->queue, &p)) {
1113                printk(KERN_DEBUG "%s: failed to set TX queue "
1114                       "parameters for queue %d\n",
1115                       wiphy_name(local->hw.wiphy), params->queue);
1116                return -EINVAL;
1117        }
1118
1119        return 0;
1120}
1121
1122static int ieee80211_set_channel(struct wiphy *wiphy,
1123                                 struct ieee80211_channel *chan,
1124                                 enum nl80211_channel_type channel_type)
1125{
1126        struct ieee80211_local *local = wiphy_priv(wiphy);
1127
1128        local->oper_channel = chan;
1129        local->oper_channel_type = channel_type;
1130
1131        return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
1132}
1133
1134#ifdef CONFIG_PM
1135static int ieee80211_suspend(struct wiphy *wiphy)
1136{
1137        return __ieee80211_suspend(wiphy_priv(wiphy));
1138}
1139
1140static int ieee80211_resume(struct wiphy *wiphy)
1141{
1142        return __ieee80211_resume(wiphy_priv(wiphy));
1143}
1144#else
1145#define ieee80211_suspend NULL
1146#define ieee80211_resume NULL
1147#endif
1148
1149static int ieee80211_scan(struct wiphy *wiphy,
1150                          struct net_device *dev,
1151                          struct cfg80211_scan_request *req)
1152{
1153        struct ieee80211_sub_if_data *sdata;
1154
1155        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1156
1157        if (sdata->vif.type != NL80211_IFTYPE_STATION &&
1158            sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1159            sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
1160            (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon))
1161                return -EOPNOTSUPP;
1162
1163        return ieee80211_request_scan(sdata, req);
1164}
1165
1166static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
1167                          struct cfg80211_auth_request *req)
1168{
1169        return ieee80211_mgd_auth(IEEE80211_DEV_TO_SUB_IF(dev), req);
1170}
1171
1172static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
1173                           struct cfg80211_assoc_request *req)
1174{
1175        return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
1176}
1177
1178static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
1179                            struct cfg80211_deauth_request *req,
1180                            void *cookie)
1181{
1182        return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev),
1183                                    req, cookie);
1184}
1185
1186static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
1187                              struct cfg80211_disassoc_request *req,
1188                              void *cookie)
1189{
1190        return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev),
1191                                      req, cookie);
1192}
1193
1194static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1195                               struct cfg80211_ibss_params *params)
1196{
1197        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1198
1199        return ieee80211_ibss_join(sdata, params);
1200}
1201
1202static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1203{
1204        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1205
1206        return ieee80211_ibss_leave(sdata);
1207}
1208
1209static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1210{
1211        struct ieee80211_local *local = wiphy_priv(wiphy);
1212        int err;
1213
1214        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1215                err = drv_set_rts_threshold(local, wiphy->rts_threshold);
1216
1217                if (err)
1218                        return err;
1219        }
1220
1221        if (changed & WIPHY_PARAM_RETRY_SHORT)
1222                local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
1223        if (changed & WIPHY_PARAM_RETRY_LONG)
1224                local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
1225        if (changed &
1226            (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
1227                ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
1228
1229        return 0;
1230}
1231
1232static int ieee80211_set_tx_power(struct wiphy *wiphy,
1233                                  enum tx_power_setting type, int dbm)
1234{
1235        struct ieee80211_local *local = wiphy_priv(wiphy);
1236        struct ieee80211_channel *chan = local->hw.conf.channel;
1237        u32 changes = 0;
1238
1239        switch (type) {
1240        case TX_POWER_AUTOMATIC:
1241                local->user_power_level = -1;
1242                break;
1243        case TX_POWER_LIMITED:
1244                if (dbm < 0)
1245                        return -EINVAL;
1246                local->user_power_level = dbm;
1247                break;
1248        case TX_POWER_FIXED:
1249                if (dbm < 0)
1250                        return -EINVAL;
1251                /* TODO: move to cfg80211 when it knows the channel */
1252                if (dbm > chan->max_power)
1253                        return -EINVAL;
1254                local->user_power_level = dbm;
1255                break;
1256        }
1257
1258        ieee80211_hw_config(local, changes);
1259
1260        return 0;
1261}
1262
1263static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
1264{
1265        struct ieee80211_local *local = wiphy_priv(wiphy);
1266
1267        *dbm = local->hw.conf.power_level;
1268
1269        return 0;
1270}
1271
1272static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
1273                                  u8 *addr)
1274{
1275        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1276
1277        memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN);
1278
1279        return 0;
1280}
1281
1282static void ieee80211_rfkill_poll(struct wiphy *wiphy)
1283{
1284        struct ieee80211_local *local = wiphy_priv(wiphy);
1285
1286        drv_rfkill_poll(local);
1287}
1288
1289#ifdef CONFIG_NL80211_TESTMODE
1290static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
1291{
1292        struct ieee80211_local *local = wiphy_priv(wiphy);
1293
1294        if (!local->ops->testmode_cmd)
1295                return -EOPNOTSUPP;
1296
1297        return local->ops->testmode_cmd(&local->hw, data, len);
1298}
1299#endif
1300
1301static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1302                                    bool enabled, int timeout)
1303{
1304        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1305        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1306        struct ieee80211_conf *conf = &local->hw.conf;
1307
1308        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
1309                return -EOPNOTSUPP;
1310
1311        if (enabled == sdata->u.mgd.powersave &&
1312            timeout == conf->dynamic_ps_timeout)
1313                return 0;
1314
1315        sdata->u.mgd.powersave = enabled;
1316        conf->dynamic_ps_timeout = timeout;
1317
1318        if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
1319                ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
1320
1321        ieee80211_recalc_ps(local, -1);
1322
1323        return 0;
1324}
1325
1326static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
1327                                      struct net_device *dev,
1328                                      const u8 *addr,
1329                                      const struct cfg80211_bitrate_mask *mask)
1330{
1331        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1332        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1333        int i, err = -EINVAL;
1334        u32 target_rate;
1335        struct ieee80211_supported_band *sband;
1336
1337        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1338
1339        /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
1340         * target_rate = X, rate->fixed = 1 means only rate X
1341         * target_rate = X, rate->fixed = 0 means all rates <= X */
1342        sdata->max_ratectrl_rateidx = -1;
1343        sdata->force_unicast_rateidx = -1;
1344
1345        if (mask->fixed)
1346                target_rate = mask->fixed / 100;
1347        else if (mask->maxrate)
1348                target_rate = mask->maxrate / 100;
1349        else
1350                return 0;
1351
1352        for (i=0; i< sband->n_bitrates; i++) {
1353                struct ieee80211_rate *brate = &sband->bitrates[i];
1354                int this_rate = brate->bitrate;
1355
1356                if (target_rate == this_rate) {
1357                        sdata->max_ratectrl_rateidx = i;
1358                        if (mask->fixed)
1359                                sdata->force_unicast_rateidx = i;
1360                        err = 0;
1361                        break;
1362                }
1363        }
1364
1365        return err;
1366}
1367
1368struct cfg80211_ops mac80211_config_ops = {
1369        .add_virtual_intf = ieee80211_add_iface,
1370        .del_virtual_intf = ieee80211_del_iface,
1371        .change_virtual_intf = ieee80211_change_iface,
1372        .add_key = ieee80211_add_key,
1373        .del_key = ieee80211_del_key,
1374        .get_key = ieee80211_get_key,
1375        .set_default_key = ieee80211_config_default_key,
1376        .set_default_mgmt_key = ieee80211_config_default_mgmt_key,
1377        .add_beacon = ieee80211_add_beacon,
1378        .set_beacon = ieee80211_set_beacon,
1379        .del_beacon = ieee80211_del_beacon,
1380        .add_station = ieee80211_add_station,
1381        .del_station = ieee80211_del_station,
1382        .change_station = ieee80211_change_station,
1383        .get_station = ieee80211_get_station,
1384        .dump_station = ieee80211_dump_station,
1385#ifdef CONFIG_MAC80211_MESH
1386        .add_mpath = ieee80211_add_mpath,
1387        .del_mpath = ieee80211_del_mpath,
1388        .change_mpath = ieee80211_change_mpath,
1389        .get_mpath = ieee80211_get_mpath,
1390        .dump_mpath = ieee80211_dump_mpath,
1391        .set_mesh_params = ieee80211_set_mesh_params,
1392        .get_mesh_params = ieee80211_get_mesh_params,
1393#endif
1394        .change_bss = ieee80211_change_bss,
1395        .set_txq_params = ieee80211_set_txq_params,
1396        .set_channel = ieee80211_set_channel,
1397        .suspend = ieee80211_suspend,
1398        .resume = ieee80211_resume,
1399        .scan = ieee80211_scan,
1400        .auth = ieee80211_auth,
1401        .assoc = ieee80211_assoc,
1402        .deauth = ieee80211_deauth,
1403        .disassoc = ieee80211_disassoc,
1404        .join_ibss = ieee80211_join_ibss,
1405        .leave_ibss = ieee80211_leave_ibss,
1406        .set_wiphy_params = ieee80211_set_wiphy_params,
1407        .set_tx_power = ieee80211_set_tx_power,
1408        .get_tx_power = ieee80211_get_tx_power,
1409        .set_wds_peer = ieee80211_set_wds_peer,
1410        .rfkill_poll = ieee80211_rfkill_poll,
1411        CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
1412        .set_power_mgmt = ieee80211_set_power_mgmt,
1413        .set_bitrate_mask = ieee80211_set_bitrate_mask,
1414};
1415
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.