linux/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
<<
>>
Prefs
   1/******************************************************************************
   2
   3  Copyright(c) 2004 Intel Corporation. All rights reserved.
   4
   5  Portions of this file are based on the WEP enablement code provided by the
   6  Host AP project hostap-drivers v0.1.3
   7  Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
   8  <jkmaline@cc.hut.fi>
   9  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
  10
  11  This program is free software; you can redistribute it and/or modify it
  12  under the terms of version 2 of the GNU General Public License as
  13  published by the Free Software Foundation.
  14
  15  This program is distributed in the hope that it will be useful, but WITHOUT
  16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  18  more details.
  19
  20  You should have received a copy of the GNU General Public License along with
  21  this program; if not, write to the Free Software Foundation, Inc., 59
  22  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  23
  24  The full GNU General Public License is included in this distribution in the
  25  file called LICENSE.
  26
  27  Contact Information:
  28  James P. Ketrenos <ipw2100-admin@linux.intel.com>
  29  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30
  31******************************************************************************/
  32#include <linux/wireless.h>
  33#include <linux/kmod.h>
  34#include <linux/slab.h>
  35#include <linux/module.h>
  36
  37#include "ieee80211.h"
  38static const char *ieee80211_modes[] = {
  39        "?", "a", "b", "ab", "g", "ag", "bg", "abg"
  40};
  41
  42#define MAX_CUSTOM_LEN 64
  43static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
  44                                           char *start, char *stop,
  45                                           struct ieee80211_network *network,
  46                                           struct iw_request_info *info)
  47{
  48        char custom[MAX_CUSTOM_LEN];
  49        char *p;
  50        struct iw_event iwe;
  51        int i, j;
  52        u8 max_rate, rate;
  53
  54        /* First entry *MUST* be the AP MAC address */
  55        iwe.cmd = SIOCGIWAP;
  56        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
  57        memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
  58        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
  59
  60        /* Remaining entries will be displayed in the order we provide them */
  61
  62        /* Add the ESSID */
  63        iwe.cmd = SIOCGIWESSID;
  64        iwe.u.data.flags = 1;
  65        //YJ,modified,080903,for hidden ap
  66        //if (network->flags & NETWORK_EMPTY_ESSID) {
  67        if (network->ssid_len == 0) {
  68        //YJ,modified,080903,end
  69                iwe.u.data.length = sizeof("<hidden>");
  70                start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
  71        } else {
  72                iwe.u.data.length = min(network->ssid_len, (u8)32);
  73                start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
  74        }
  75        //printk("ESSID: %s\n",network->ssid);
  76        /* Add the protocol name */
  77        iwe.cmd = SIOCGIWNAME;
  78        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
  79        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
  80
  81        /* Add mode */
  82        iwe.cmd = SIOCGIWMODE;
  83        if (network->capability &
  84            (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
  85                if (network->capability & WLAN_CAPABILITY_BSS)
  86                        iwe.u.mode = IW_MODE_MASTER;
  87                else
  88                        iwe.u.mode = IW_MODE_ADHOC;
  89
  90                start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
  91        }
  92
  93        /* Add frequency/channel */
  94        iwe.cmd = SIOCGIWFREQ;
  95/*      iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
  96        iwe.u.freq.e = 3; */
  97        iwe.u.freq.m = network->channel;
  98        iwe.u.freq.e = 0;
  99        iwe.u.freq.i = 0;
 100        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
 101
 102        /* Add encryption capability */
 103        iwe.cmd = SIOCGIWENCODE;
 104        if (network->capability & WLAN_CAPABILITY_PRIVACY)
 105                iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 106        else
 107                iwe.u.data.flags = IW_ENCODE_DISABLED;
 108        iwe.u.data.length = 0;
 109        start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
 110
 111        /* Add basic and extended rates */
 112        max_rate = 0;
 113        p = custom;
 114        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
 115        for (i = 0, j = 0; i < network->rates_len; ) {
 116                if (j < network->rates_ex_len &&
 117                    ((network->rates_ex[j] & 0x7F) <
 118                     (network->rates[i] & 0x7F)))
 119                        rate = network->rates_ex[j++] & 0x7F;
 120                else
 121                        rate = network->rates[i++] & 0x7F;
 122                if (rate > max_rate)
 123                        max_rate = rate;
 124                p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
 125                              "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
 126        }
 127        for (; j < network->rates_ex_len; j++) {
 128                rate = network->rates_ex[j] & 0x7F;
 129                p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
 130                              "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
 131                if (rate > max_rate)
 132                        max_rate = rate;
 133        }
 134
 135        iwe.cmd = SIOCGIWRATE;
 136        iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
 137        iwe.u.bitrate.value = max_rate * 500000;
 138        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
 139
 140        iwe.cmd = IWEVCUSTOM;
 141        iwe.u.data.length = p - custom;
 142        if (iwe.u.data.length)
 143                start = iwe_stream_add_point(info, start, stop, &iwe, custom);
 144
 145        /* Add quality statistics */
 146        /* TODO: Fix these values... */
 147        if (network->stats.signal == 0 || network->stats.rssi == 0)
 148        printk("========>signal:%d, rssi:%d\n", network->stats.signal, network->stats.rssi);
 149        iwe.cmd = IWEVQUAL;
 150//      printk("SIGNAL: %d,RSSI: %d,NOISE: %d\n",network->stats.signal,network->stats.rssi,network->stats.noise);
 151        iwe.u.qual.qual = network->stats.signalstrength;
 152        iwe.u.qual.level = network->stats.signal;
 153        iwe.u.qual.noise = network->stats.noise;
 154        iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
 155        if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
 156                iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
 157        if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
 158                iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
 159        if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
 160                iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
 161        iwe.u.qual.updated = 7;
 162        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
 163
 164        iwe.cmd = IWEVCUSTOM;
 165        p = custom;
 166
 167        iwe.u.data.length = p - custom;
 168        if (iwe.u.data.length)
 169                start = iwe_stream_add_point(info, start, stop, &iwe, custom);
 170
 171        memset(&iwe, 0, sizeof(iwe));
 172        if (network->wpa_ie_len) {
 173        //      printk("wpa_ie_len:%d\n", network->wpa_ie_len);
 174                char buf[MAX_WPA_IE_LEN];
 175                memcpy(buf, network->wpa_ie, network->wpa_ie_len);
 176                iwe.cmd = IWEVGENIE;
 177                iwe.u.data.length = network->wpa_ie_len;
 178                start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 179        }
 180
 181        memset(&iwe, 0, sizeof(iwe));
 182        if (network->rsn_ie_len) {
 183        //      printk("=====>rsn_ie_len:\n", network->rsn_ie_len);
 184                char buf[MAX_WPA_IE_LEN];
 185                memcpy(buf, network->rsn_ie, network->rsn_ie_len);
 186                iwe.cmd = IWEVGENIE;
 187                iwe.u.data.length = network->rsn_ie_len;
 188                start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 189        }
 190
 191        /* Add EXTRA: Age to display seconds since last beacon/probe response
 192         * for given network. */
 193        iwe.cmd = IWEVCUSTOM;
 194        p = custom;
 195        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
 196                      " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
 197        iwe.u.data.length = p - custom;
 198        if (iwe.u.data.length)
 199                start = iwe_stream_add_point(info, start, stop, &iwe, custom);
 200
 201        return start;
 202}
 203
 204int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 205                          struct iw_request_info *info,
 206                          union iwreq_data *wrqu, char *extra)
 207{
 208        struct ieee80211_network *network;
 209        unsigned long flags;
 210        int err = 0;
 211        char *ev = extra;
 212        char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
 213        //char *stop = ev + IW_SCAN_MAX_DATA;
 214        int i = 0;
 215
 216        IEEE80211_DEBUG_WX("Getting scan\n");
 217        down(&ieee->wx_sem);
 218        spin_lock_irqsave(&ieee->lock, flags);
 219
 220        if (!ieee->bHwRadioOff) {
 221                list_for_each_entry(network, &ieee->network_list, list) {
 222                        i++;
 223
 224                        if ((stop-ev) < 200) {
 225                                err = -E2BIG;
 226                                break;
 227                        }
 228                        if (ieee->scan_age == 0 ||
 229                            time_after(network->last_scanned + ieee->scan_age, jiffies)) {
 230                                ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
 231                        } else
 232                                IEEE80211_DEBUG_SCAN(
 233                                        "Not showing network '%s ("
 234                                        "%pM)' due to age (%lums).\n",
 235                                        escape_essid(network->ssid,
 236                                                     network->ssid_len),
 237                                        network->bssid,
 238                                        (jiffies - network->last_scanned) / (HZ / 100));
 239                }
 240        }
 241        spin_unlock_irqrestore(&ieee->lock, flags);
 242        up(&ieee->wx_sem);
 243        wrqu->data.length = ev -  extra;
 244        wrqu->data.flags = 0;
 245        IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
 246
 247        return err;
 248}
 249
 250int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 251                            struct iw_request_info *info,
 252                            union iwreq_data *wrqu, char *keybuf)
 253{
 254        struct iw_point *erq = &(wrqu->encoding);
 255        struct net_device *dev = ieee->dev;
 256        struct ieee80211_security sec = {
 257                .flags = 0
 258        };
 259        int i, key, key_provided, len;
 260        struct ieee80211_crypt_data **crypt;
 261
 262        IEEE80211_DEBUG_WX("SET_ENCODE\n");
 263
 264        key = erq->flags & IW_ENCODE_INDEX;
 265        if (key) {
 266                if (key > WEP_KEYS)
 267                        return -EINVAL;
 268                key--;
 269                key_provided = 1;
 270        } else {
 271                key_provided = 0;
 272                key = ieee->tx_keyidx;
 273        }
 274
 275        IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
 276                           "provided" : "default");
 277
 278        crypt = &ieee->crypt[key];
 279
 280        if (erq->flags & IW_ENCODE_DISABLED) {
 281                if (key_provided && *crypt) {
 282                        IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
 283                                           key);
 284                        ieee80211_crypt_delayed_deinit(ieee, crypt);
 285                } else
 286                        IEEE80211_DEBUG_WX("Disabling encryption.\n");
 287
 288                /* Check all the keys to see if any are still configured,
 289                 * and if no key index was provided, de-init them all */
 290                for (i = 0; i < WEP_KEYS; i++) {
 291                        if (ieee->crypt[i] != NULL) {
 292                                if (key_provided)
 293                                        break;
 294                                ieee80211_crypt_delayed_deinit(
 295                                        ieee, &ieee->crypt[i]);
 296                        }
 297                }
 298
 299                if (i == WEP_KEYS) {
 300                        sec.enabled = 0;
 301                        sec.level = SEC_LEVEL_0;
 302                        sec.flags |= SEC_ENABLED | SEC_LEVEL;
 303                }
 304
 305                goto done;
 306        }
 307
 308
 309
 310        sec.enabled = 1;
 311        sec.flags |= SEC_ENABLED;
 312
 313        if (*crypt != NULL && (*crypt)->ops != NULL &&
 314            strcmp((*crypt)->ops->name, "WEP") != 0) {
 315                /* changing to use WEP; deinit previously used algorithm
 316                 * on this key */
 317                ieee80211_crypt_delayed_deinit(ieee, crypt);
 318        }
 319
 320        if (*crypt == NULL) {
 321                struct ieee80211_crypt_data *new_crypt;
 322
 323                /* take WEP into use */
 324                new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
 325                                    GFP_KERNEL);
 326                if (new_crypt == NULL)
 327                        return -ENOMEM;
 328                new_crypt->ops = ieee80211_get_crypto_ops("WEP");
 329                if (!new_crypt->ops)
 330                        new_crypt->ops = ieee80211_get_crypto_ops("WEP");
 331
 332                if (new_crypt->ops)
 333                        new_crypt->priv = new_crypt->ops->init(key);
 334
 335                if (!new_crypt->ops || !new_crypt->priv) {
 336                        kfree(new_crypt);
 337                        new_crypt = NULL;
 338
 339                        netdev_warn(ieee->dev,
 340                                    "could not initialize WEP: load module ieee80211_crypt_wep\n");
 341                        return -EOPNOTSUPP;
 342                }
 343                *crypt = new_crypt;
 344        }
 345
 346        /* If a new key was provided, set it up */
 347        if (erq->length > 0) {
 348                len = erq->length <= 5 ? 5 : 13;
 349                memcpy(sec.keys[key], keybuf, erq->length);
 350                if (len > erq->length)
 351                        memset(sec.keys[key] + erq->length, 0,
 352                               len - erq->length);
 353                IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
 354                                   key, escape_essid(sec.keys[key], len),
 355                                   erq->length, len);
 356                sec.key_sizes[key] = len;
 357                (*crypt)->ops->set_key(sec.keys[key], len, NULL,
 358                                       (*crypt)->priv);
 359                sec.flags |= (1 << key);
 360                /* This ensures a key will be activated if no key is
 361                 * explicitly set */
 362                if (key == sec.active_key)
 363                        sec.flags |= SEC_ACTIVE_KEY;
 364                ieee->tx_keyidx = key;//by wb 080312
 365        } else {
 366                len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
 367                                             NULL, (*crypt)->priv);
 368                if (len == 0) {
 369                        /* Set a default key of all 0 */
 370                        IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
 371                                           key);
 372                        memset(sec.keys[key], 0, 13);
 373                        (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
 374                                               (*crypt)->priv);
 375                        sec.key_sizes[key] = 13;
 376                        sec.flags |= (1 << key);
 377                }
 378
 379                /* No key data - just set the default TX key index */
 380                if (key_provided) {
 381                        IEEE80211_DEBUG_WX(
 382                                "Setting key %d to default Tx key.\n", key);
 383                        ieee->tx_keyidx = key;
 384                        sec.active_key = key;
 385                        sec.flags |= SEC_ACTIVE_KEY;
 386                }
 387        }
 388
 389 done:
 390        ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
 391        sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
 392        sec.flags |= SEC_AUTH_MODE;
 393        IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
 394                           "OPEN" : "SHARED KEY");
 395
 396        /* For now we just support WEP, so only set that security level...
 397         * TODO: When WPA is added this is one place that needs to change */
 398        sec.flags |= SEC_LEVEL;
 399        sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
 400
 401        if (ieee->set_security)
 402                ieee->set_security(dev, &sec);
 403
 404        /* Do not reset port if card is in Managed mode since resetting will
 405         * generate new IEEE 802.11 authentication which may end up in looping
 406         * with IEEE 802.1X.  If your hardware requires a reset after WEP
 407         * configuration (for example... Prism2), implement the reset_port in
 408         * the callbacks structures used to initialize the 802.11 stack. */
 409        if (ieee->reset_on_keychange &&
 410            ieee->iw_mode != IW_MODE_INFRA &&
 411            ieee->reset_port && ieee->reset_port(dev)) {
 412                netdev_dbg(ieee->dev, "reset_port failed\n");
 413                return -EINVAL;
 414        }
 415        return 0;
 416}
 417
 418int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
 419                            struct iw_request_info *info,
 420                            union iwreq_data *wrqu, char *keybuf)
 421{
 422        struct iw_point *erq = &(wrqu->encoding);
 423        int len, key;
 424        struct ieee80211_crypt_data *crypt;
 425
 426        IEEE80211_DEBUG_WX("GET_ENCODE\n");
 427
 428        if (ieee->iw_mode == IW_MODE_MONITOR)
 429                return -1;
 430
 431        key = erq->flags & IW_ENCODE_INDEX;
 432        if (key) {
 433                if (key > WEP_KEYS)
 434                        return -EINVAL;
 435                key--;
 436        } else
 437                key = ieee->tx_keyidx;
 438
 439        crypt = ieee->crypt[key];
 440        erq->flags = key + 1;
 441
 442        if (crypt == NULL || crypt->ops == NULL) {
 443                erq->length = 0;
 444                erq->flags |= IW_ENCODE_DISABLED;
 445                return 0;
 446        }
 447
 448        if (strcmp(crypt->ops->name, "WEP") != 0) {
 449                /* only WEP is supported with wireless extensions, so just
 450                 * report that encryption is used */
 451                erq->length = 0;
 452                erq->flags |= IW_ENCODE_ENABLED;
 453                return 0;
 454        }
 455
 456        len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
 457        erq->length = (len >= 0 ? len : 0);
 458
 459        erq->flags |= IW_ENCODE_ENABLED;
 460
 461        if (ieee->open_wep)
 462                erq->flags |= IW_ENCODE_OPEN;
 463        else
 464                erq->flags |= IW_ENCODE_RESTRICTED;
 465
 466        return 0;
 467}
 468
 469int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
 470                                struct iw_request_info *info,
 471                                union iwreq_data *wrqu, char *extra)
 472{
 473        struct net_device *dev = ieee->dev;
 474        struct iw_point *encoding = &wrqu->encoding;
 475        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 476        int i, idx, ret = 0;
 477        int group_key = 0;
 478        const char *alg;
 479        struct ieee80211_crypto_ops *ops;
 480        struct ieee80211_crypt_data **crypt;
 481
 482        struct ieee80211_security sec = {
 483                .flags = 0,
 484        };
 485        //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
 486        idx = encoding->flags & IW_ENCODE_INDEX;
 487        if (idx) {
 488                if (idx < 1 || idx > WEP_KEYS)
 489                        return -EINVAL;
 490                idx--;
 491        } else
 492                idx = ieee->tx_keyidx;
 493
 494        if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
 495                crypt = &ieee->crypt[idx];
 496                group_key = 1;
 497        } else {
 498                /* some Cisco APs use idx>0 for unicast in dynamic WEP */
 499                //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
 500                if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
 501                        return -EINVAL;
 502                if (ieee->iw_mode == IW_MODE_INFRA)
 503                        crypt = &ieee->crypt[idx];
 504                else
 505                        return -EINVAL;
 506        }
 507
 508        sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
 509        if ((encoding->flags & IW_ENCODE_DISABLED) ||
 510            ext->alg == IW_ENCODE_ALG_NONE) {
 511                if (*crypt)
 512                        ieee80211_crypt_delayed_deinit(ieee, crypt);
 513
 514                for (i = 0; i < WEP_KEYS; i++)
 515                        if (ieee->crypt[i] != NULL)
 516                                break;
 517
 518                if (i == WEP_KEYS) {
 519                        sec.enabled = 0;
 520                        // sec.encrypt = 0;
 521                        sec.level = SEC_LEVEL_0;
 522                        sec.flags |= SEC_LEVEL;
 523                }
 524                //printk("disabled: flag:%x\n", encoding->flags);
 525                goto done;
 526        }
 527
 528        sec.enabled = 1;
 529    //    sec.encrypt = 1;
 530
 531        switch (ext->alg) {
 532        case IW_ENCODE_ALG_WEP:
 533                alg = "WEP";
 534                break;
 535        case IW_ENCODE_ALG_TKIP:
 536                alg = "TKIP";
 537                break;
 538        case IW_ENCODE_ALG_CCMP:
 539                alg = "CCMP";
 540                break;
 541        default:
 542                IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
 543                                   dev->name, ext->alg);
 544                ret = -EINVAL;
 545                goto done;
 546        }
 547//      printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
 548
 549        ops = ieee80211_get_crypto_ops(alg);
 550        if (ops == NULL)
 551                ops = ieee80211_get_crypto_ops(alg);
 552        if (ops == NULL) {
 553                IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
 554                                   dev->name, ext->alg);
 555                printk("========>unknown crypto alg %d\n", ext->alg);
 556                ret = -EINVAL;
 557                goto done;
 558        }
 559
 560        if (*crypt == NULL || (*crypt)->ops != ops) {
 561                struct ieee80211_crypt_data *new_crypt;
 562
 563                ieee80211_crypt_delayed_deinit(ieee, crypt);
 564
 565                new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
 566                if (new_crypt == NULL) {
 567                        ret = -ENOMEM;
 568                        goto done;
 569                }
 570                new_crypt->ops = ops;
 571                if (new_crypt->ops)
 572                        new_crypt->priv = new_crypt->ops->init(idx);
 573                if (new_crypt->priv == NULL) {
 574                        kfree(new_crypt);
 575                        ret = -EINVAL;
 576                        goto done;
 577                }
 578                *crypt = new_crypt;
 579
 580        }
 581
 582        if (ext->key_len > 0 && (*crypt)->ops->set_key &&
 583            (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
 584                                   (*crypt)->priv) < 0) {
 585                IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
 586                printk("key setting failed\n");
 587                ret = -EINVAL;
 588                goto done;
 589        }
 590#if 1
 591 //skip_host_crypt:
 592        //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
 593        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
 594                ieee->tx_keyidx = idx;
 595                sec.active_key = idx;
 596                sec.flags |= SEC_ACTIVE_KEY;
 597        }
 598
 599        if (ext->alg != IW_ENCODE_ALG_NONE) {
 600                memcpy(sec.keys[idx], ext->key, ext->key_len);
 601                sec.key_sizes[idx] = ext->key_len;
 602                sec.flags |= (1 << idx);
 603                if (ext->alg == IW_ENCODE_ALG_WEP) {
 604                      //  sec.encode_alg[idx] = SEC_ALG_WEP;
 605                        sec.flags |= SEC_LEVEL;
 606                        sec.level = SEC_LEVEL_1;
 607                } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
 608                      //  sec.encode_alg[idx] = SEC_ALG_TKIP;
 609                        sec.flags |= SEC_LEVEL;
 610                        sec.level = SEC_LEVEL_2;
 611                } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
 612                       // sec.encode_alg[idx] = SEC_ALG_CCMP;
 613                        sec.flags |= SEC_LEVEL;
 614                        sec.level = SEC_LEVEL_3;
 615                }
 616                /* Don't set sec level for group keys. */
 617                if (group_key)
 618                        sec.flags &= ~SEC_LEVEL;
 619        }
 620#endif
 621done:
 622        if (ieee->set_security)
 623                ieee->set_security(ieee->dev, &sec);
 624
 625         if (ieee->reset_on_keychange &&
 626            ieee->iw_mode != IW_MODE_INFRA &&
 627            ieee->reset_port && ieee->reset_port(dev)) {
 628                IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
 629                return -EINVAL;
 630        }
 631
 632        return ret;
 633}
 634int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
 635                               struct iw_request_info *info,
 636                               union iwreq_data *wrqu, char *extra)
 637{
 638        struct iw_mlme *mlme = (struct iw_mlme *) extra;
 639//      printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
 640#if 1
 641        switch (mlme->cmd) {
 642        case IW_MLME_DEAUTH:
 643        case IW_MLME_DISASSOC:
 644        //      printk("disassoc now\n");
 645                ieee80211_disassociate(ieee);
 646                break;
 647         default:
 648                return -EOPNOTSUPP;
 649        }
 650#endif
 651        return 0;
 652}
 653
 654int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
 655                               struct iw_request_info *info,
 656                               struct iw_param *data, char *extra)
 657{
 658/*
 659         struct ieee80211_security sec = {
 660                .flags = SEC_AUTH_MODE,
 661        }
 662*/
 663        //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
 664        switch (data->flags & IW_AUTH_INDEX) {
 665        case IW_AUTH_WPA_VERSION:
 666             /*need to support wpa2 here*/
 667                //printk("wpa version:%x\n", data->value);
 668                break;
 669        case IW_AUTH_CIPHER_PAIRWISE:
 670        case IW_AUTH_CIPHER_GROUP:
 671        case IW_AUTH_KEY_MGMT:
 672                /*
 673 *                  * Host AP driver does not use these parameters and allows
 674 *                                   * wpa_supplicant to control them internally.
 675 *                                                    */
 676                break;
 677        case IW_AUTH_TKIP_COUNTERMEASURES:
 678                ieee->tkip_countermeasures = data->value;
 679                break;
 680        case IW_AUTH_DROP_UNENCRYPTED:
 681                ieee->drop_unencrypted = data->value;
 682                break;
 683
 684        case IW_AUTH_80211_AUTH_ALG:
 685                ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0;
 686                //printk("open_wep:%d\n", ieee->open_wep);
 687                break;
 688
 689#if 1
 690        case IW_AUTH_WPA_ENABLED:
 691                ieee->wpa_enabled = (data->value) ? 1 : 0;
 692                //printk("enable wpa:%d\n", ieee->wpa_enabled);
 693                break;
 694
 695#endif
 696        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
 697                ieee->ieee802_1x = data->value;
 698                break;
 699        case IW_AUTH_PRIVACY_INVOKED:
 700                ieee->privacy_invoked = data->value;
 701                break;
 702        default:
 703                return -EOPNOTSUPP;
 704        }
 705        return 0;
 706}
 707
 708#if 1
 709int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
 710{
 711        u8 *buf = NULL;
 712
 713        if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
 714                printk("return error out, len:%zu\n", len);
 715        return -EINVAL;
 716        }
 717
 718        if (len) {
 719                if (len != ie[1]+2) {
 720                        printk("len:%zu, ie:%d\n", len, ie[1]);
 721                        return -EINVAL;
 722                }
 723                buf = kmemdup(ie, len, GFP_KERNEL);
 724                if (buf == NULL)
 725                        return -ENOMEM;
 726                kfree(ieee->wpa_ie);
 727                ieee->wpa_ie = buf;
 728                ieee->wpa_ie_len = len;
 729        } else {
 730                kfree(ieee->wpa_ie);
 731                ieee->wpa_ie = NULL;
 732                ieee->wpa_ie_len = 0;
 733        }
 734//      printk("<=====out %s()\n", __func__);
 735
 736        return 0;
 737
 738}
 739#endif
 740