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        {
 222                list_for_each_entry(network, &ieee->network_list, list) {
 223                        i++;
 224
 225                        if((stop-ev)<200)
 226                        {
 227                                err = -E2BIG;
 228                                break;
 229                        }
 230                        if (ieee->scan_age == 0 ||
 231                            time_after(network->last_scanned + ieee->scan_age, jiffies))
 232                        {
 233                                ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
 234                        }
 235                        else
 236                                IEEE80211_DEBUG_SCAN(
 237                                        "Not showing network '%s ("
 238                                        "%pM)' due to age (%lums).\n",
 239                                        escape_essid(network->ssid,
 240                                                     network->ssid_len),
 241                                        network->bssid,
 242                                        (jiffies - network->last_scanned) / (HZ / 100));
 243                }
 244        }
 245        spin_unlock_irqrestore(&ieee->lock, flags);
 246        up(&ieee->wx_sem);
 247        wrqu->data.length = ev -  extra;
 248        wrqu->data.flags = 0;
 249        IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
 250
 251        return err;
 252}
 253
 254int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 255                            struct iw_request_info *info,
 256                            union iwreq_data *wrqu, char *keybuf)
 257{
 258        struct iw_point *erq = &(wrqu->encoding);
 259        struct net_device *dev = ieee->dev;
 260        struct ieee80211_security sec = {
 261                .flags = 0
 262        };
 263        int i, key, key_provided, len;
 264        struct ieee80211_crypt_data **crypt;
 265
 266        IEEE80211_DEBUG_WX("SET_ENCODE\n");
 267
 268        key = erq->flags & IW_ENCODE_INDEX;
 269        if (key) {
 270                if (key > WEP_KEYS)
 271                        return -EINVAL;
 272                key--;
 273                key_provided = 1;
 274        } else {
 275                key_provided = 0;
 276                key = ieee->tx_keyidx;
 277        }
 278
 279        IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
 280                           "provided" : "default");
 281
 282        crypt = &ieee->crypt[key];
 283
 284        if (erq->flags & IW_ENCODE_DISABLED) {
 285                if (key_provided && *crypt) {
 286                        IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
 287                                           key);
 288                        ieee80211_crypt_delayed_deinit(ieee, crypt);
 289                } else
 290                        IEEE80211_DEBUG_WX("Disabling encryption.\n");
 291
 292                /* Check all the keys to see if any are still configured,
 293                 * and if no key index was provided, de-init them all */
 294                for (i = 0; i < WEP_KEYS; i++) {
 295                        if (ieee->crypt[i] != NULL) {
 296                                if (key_provided)
 297                                        break;
 298                                ieee80211_crypt_delayed_deinit(
 299                                        ieee, &ieee->crypt[i]);
 300                        }
 301                }
 302
 303                if (i == WEP_KEYS) {
 304                        sec.enabled = 0;
 305                        sec.level = SEC_LEVEL_0;
 306                        sec.flags |= SEC_ENABLED | SEC_LEVEL;
 307                }
 308
 309                goto done;
 310        }
 311
 312
 313
 314        sec.enabled = 1;
 315        sec.flags |= SEC_ENABLED;
 316
 317        if (*crypt != NULL && (*crypt)->ops != NULL &&
 318            strcmp((*crypt)->ops->name, "WEP") != 0) {
 319                /* changing to use WEP; deinit previously used algorithm
 320                 * on this key */
 321                ieee80211_crypt_delayed_deinit(ieee, crypt);
 322        }
 323
 324        if (*crypt == NULL) {
 325                struct ieee80211_crypt_data *new_crypt;
 326
 327                /* take WEP into use */
 328                new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
 329                                    GFP_KERNEL);
 330                if (new_crypt == NULL)
 331                        return -ENOMEM;
 332                new_crypt->ops = ieee80211_get_crypto_ops("WEP");
 333                if (!new_crypt->ops)
 334                        new_crypt->ops = ieee80211_get_crypto_ops("WEP");
 335
 336                if (new_crypt->ops)
 337                        new_crypt->priv = new_crypt->ops->init(key);
 338
 339                if (!new_crypt->ops || !new_crypt->priv) {
 340                        kfree(new_crypt);
 341                        new_crypt = NULL;
 342
 343                        printk(KERN_WARNING "%s: could not initialize WEP: "
 344                               "load module ieee80211_crypt_wep\n",
 345                               dev->name);
 346                        return -EOPNOTSUPP;
 347                }
 348                *crypt = new_crypt;
 349        }
 350
 351        /* If a new key was provided, set it up */
 352        if (erq->length > 0) {
 353                len = erq->length <= 5 ? 5 : 13;
 354                memcpy(sec.keys[key], keybuf, erq->length);
 355                if (len > erq->length)
 356                        memset(sec.keys[key] + erq->length, 0,
 357                               len - erq->length);
 358                IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
 359                                   key, escape_essid(sec.keys[key], len),
 360                                   erq->length, len);
 361                sec.key_sizes[key] = len;
 362                (*crypt)->ops->set_key(sec.keys[key], len, NULL,
 363                                       (*crypt)->priv);
 364                sec.flags |= (1 << key);
 365                /* This ensures a key will be activated if no key is
 366                 * explicitely set */
 367                if (key == sec.active_key)
 368                        sec.flags |= SEC_ACTIVE_KEY;
 369                ieee->tx_keyidx = key;//by wb 080312
 370        } else {
 371                len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
 372                                             NULL, (*crypt)->priv);
 373                if (len == 0) {
 374                        /* Set a default key of all 0 */
 375                        IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
 376                                           key);
 377                        memset(sec.keys[key], 0, 13);
 378                        (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
 379                                               (*crypt)->priv);
 380                        sec.key_sizes[key] = 13;
 381                        sec.flags |= (1 << key);
 382                }
 383
 384                /* No key data - just set the default TX key index */
 385                if (key_provided) {
 386                        IEEE80211_DEBUG_WX(
 387                                "Setting key %d to default Tx key.\n", key);
 388                        ieee->tx_keyidx = key;
 389                        sec.active_key = key;
 390                        sec.flags |= SEC_ACTIVE_KEY;
 391                }
 392        }
 393
 394 done:
 395        ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
 396        sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
 397        sec.flags |= SEC_AUTH_MODE;
 398        IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
 399                           "OPEN" : "SHARED KEY");
 400
 401        /* For now we just support WEP, so only set that security level...
 402         * TODO: When WPA is added this is one place that needs to change */
 403        sec.flags |= SEC_LEVEL;
 404        sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
 405
 406        if (ieee->set_security)
 407                ieee->set_security(dev, &sec);
 408
 409        /* Do not reset port if card is in Managed mode since resetting will
 410         * generate new IEEE 802.11 authentication which may end up in looping
 411         * with IEEE 802.1X.  If your hardware requires a reset after WEP
 412         * configuration (for example... Prism2), implement the reset_port in
 413         * the callbacks structures used to initialize the 802.11 stack. */
 414        if (ieee->reset_on_keychange &&
 415            ieee->iw_mode != IW_MODE_INFRA &&
 416            ieee->reset_port && ieee->reset_port(dev)) {
 417                printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
 418                return -EINVAL;
 419        }
 420        return 0;
 421}
 422
 423int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
 424                            struct iw_request_info *info,
 425                            union iwreq_data *wrqu, char *keybuf)
 426{
 427        struct iw_point *erq = &(wrqu->encoding);
 428        int len, key;
 429        struct ieee80211_crypt_data *crypt;
 430
 431        IEEE80211_DEBUG_WX("GET_ENCODE\n");
 432
 433        if(ieee->iw_mode == IW_MODE_MONITOR)
 434                return -1;
 435
 436        key = erq->flags & IW_ENCODE_INDEX;
 437        if (key) {
 438                if (key > WEP_KEYS)
 439                        return -EINVAL;
 440                key--;
 441        } else
 442                key = ieee->tx_keyidx;
 443
 444        crypt = ieee->crypt[key];
 445        erq->flags = key + 1;
 446
 447        if (crypt == NULL || crypt->ops == NULL) {
 448                erq->length = 0;
 449                erq->flags |= IW_ENCODE_DISABLED;
 450                return 0;
 451        }
 452
 453        if (strcmp(crypt->ops->name, "WEP") != 0) {
 454                /* only WEP is supported with wireless extensions, so just
 455                 * report that encryption is used */
 456                erq->length = 0;
 457                erq->flags |= IW_ENCODE_ENABLED;
 458                return 0;
 459        }
 460
 461        len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
 462        erq->length = (len >= 0 ? len : 0);
 463
 464        erq->flags |= IW_ENCODE_ENABLED;
 465
 466        if (ieee->open_wep)
 467                erq->flags |= IW_ENCODE_OPEN;
 468        else
 469                erq->flags |= IW_ENCODE_RESTRICTED;
 470
 471        return 0;
 472}
 473
 474int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
 475                               struct iw_request_info *info,
 476                               union iwreq_data *wrqu, char *extra)
 477{
 478        struct net_device *dev = ieee->dev;
 479        struct iw_point *encoding = &wrqu->encoding;
 480        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 481        int i, idx, ret = 0;
 482        int group_key = 0;
 483        const char *alg;
 484        struct ieee80211_crypto_ops *ops;
 485        struct ieee80211_crypt_data **crypt;
 486
 487        struct ieee80211_security sec = {
 488                .flags = 0,
 489        };
 490        //printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
 491        idx = encoding->flags & IW_ENCODE_INDEX;
 492        if (idx) {
 493                if (idx < 1 || idx > WEP_KEYS)
 494                        return -EINVAL;
 495                idx--;
 496        } else
 497                idx = ieee->tx_keyidx;
 498
 499        if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
 500                crypt = &ieee->crypt[idx];
 501                group_key = 1;
 502        } else {
 503                /* some Cisco APs use idx>0 for unicast in dynamic WEP */
 504                //printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
 505                if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
 506                        return -EINVAL;
 507                if (ieee->iw_mode == IW_MODE_INFRA)
 508                        crypt = &ieee->crypt[idx];
 509                else
 510                        return -EINVAL;
 511        }
 512
 513        sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
 514        if ((encoding->flags & IW_ENCODE_DISABLED) ||
 515            ext->alg == IW_ENCODE_ALG_NONE) {
 516                if (*crypt)
 517                        ieee80211_crypt_delayed_deinit(ieee, crypt);
 518
 519                for (i = 0; i < WEP_KEYS; i++)
 520                        if (ieee->crypt[i] != NULL)
 521                                break;
 522
 523                if (i == WEP_KEYS) {
 524                        sec.enabled = 0;
 525                      //  sec.encrypt = 0;
 526                        sec.level = SEC_LEVEL_0;
 527                        sec.flags |= SEC_LEVEL;
 528                }
 529                //printk("disabled: flag:%x\n", encoding->flags);
 530                goto done;
 531        }
 532
 533        sec.enabled = 1;
 534    //    sec.encrypt = 1;
 535
 536        switch (ext->alg) {
 537        case IW_ENCODE_ALG_WEP:
 538                alg = "WEP";
 539                break;
 540        case IW_ENCODE_ALG_TKIP:
 541                alg = "TKIP";
 542                break;
 543        case IW_ENCODE_ALG_CCMP:
 544                alg = "CCMP";
 545                break;
 546        default:
 547                IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
 548                                   dev->name, ext->alg);
 549                ret = -EINVAL;
 550                goto done;
 551        }
 552//      printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
 553
 554         ops = ieee80211_get_crypto_ops(alg);
 555        if (ops == NULL)
 556                ops = ieee80211_get_crypto_ops(alg);
 557        if (ops == NULL) {
 558                IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
 559                                   dev->name, ext->alg);
 560                printk("========>unknown crypto alg %d\n", ext->alg);
 561                ret = -EINVAL;
 562                goto done;
 563        }
 564
 565        if (*crypt == NULL || (*crypt)->ops != ops) {
 566                struct ieee80211_crypt_data *new_crypt;
 567
 568                ieee80211_crypt_delayed_deinit(ieee, crypt);
 569
 570                new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
 571                if (new_crypt == NULL) {
 572                        ret = -ENOMEM;
 573                        goto done;
 574                }
 575                new_crypt->ops = ops;
 576                if (new_crypt->ops)
 577                        new_crypt->priv = new_crypt->ops->init(idx);
 578                if (new_crypt->priv == NULL) {
 579                        kfree(new_crypt);
 580                        ret = -EINVAL;
 581                        goto done;
 582                }
 583                *crypt = new_crypt;
 584
 585        }
 586
 587        if (ext->key_len > 0 && (*crypt)->ops->set_key &&
 588            (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
 589                                   (*crypt)->priv) < 0) {
 590                IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
 591                printk("key setting failed\n");
 592                ret = -EINVAL;
 593                goto done;
 594        }
 595#if 1
 596 //skip_host_crypt:
 597        //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
 598        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
 599                ieee->tx_keyidx = idx;
 600                sec.active_key = idx;
 601                sec.flags |= SEC_ACTIVE_KEY;
 602        }
 603
 604        if (ext->alg != IW_ENCODE_ALG_NONE) {
 605                memcpy(sec.keys[idx], ext->key, ext->key_len);
 606                sec.key_sizes[idx] = ext->key_len;
 607                sec.flags |= (1 << idx);
 608                if (ext->alg == IW_ENCODE_ALG_WEP) {
 609                      //  sec.encode_alg[idx] = SEC_ALG_WEP;
 610                        sec.flags |= SEC_LEVEL;
 611                        sec.level = SEC_LEVEL_1;
 612                } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
 613                      //  sec.encode_alg[idx] = SEC_ALG_TKIP;
 614                        sec.flags |= SEC_LEVEL;
 615                        sec.level = SEC_LEVEL_2;
 616                } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
 617                       // sec.encode_alg[idx] = SEC_ALG_CCMP;
 618                        sec.flags |= SEC_LEVEL;
 619                        sec.level = SEC_LEVEL_3;
 620                }
 621                /* Don't set sec level for group keys. */
 622                if (group_key)
 623                        sec.flags &= ~SEC_LEVEL;
 624        }
 625#endif
 626done:
 627        if (ieee->set_security)
 628                ieee->set_security(ieee->dev, &sec);
 629
 630         if (ieee->reset_on_keychange &&
 631            ieee->iw_mode != IW_MODE_INFRA &&
 632            ieee->reset_port && ieee->reset_port(dev)) {
 633                IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
 634                return -EINVAL;
 635        }
 636
 637        return ret;
 638}
 639int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
 640                               struct iw_request_info *info,
 641                               union iwreq_data *wrqu, char *extra)
 642{
 643        struct iw_mlme *mlme = (struct iw_mlme *) extra;
 644//      printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd);
 645#if 1
 646        switch (mlme->cmd) {
 647        case IW_MLME_DEAUTH:
 648        case IW_MLME_DISASSOC:
 649        //      printk("disassoc now\n");
 650                ieee80211_disassociate(ieee);
 651                break;
 652         default:
 653                return -EOPNOTSUPP;
 654        }
 655#endif
 656        return 0;
 657}
 658
 659int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
 660                               struct iw_request_info *info,
 661                               struct iw_param *data, char *extra)
 662{
 663/*
 664         struct ieee80211_security sec = {
 665                .flags = SEC_AUTH_MODE,
 666        }
 667*/
 668        //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value);
 669        switch (data->flags & IW_AUTH_INDEX) {
 670        case IW_AUTH_WPA_VERSION:
 671             /*need to support wpa2 here*/
 672                //printk("wpa version:%x\n", data->value);
 673                break;
 674        case IW_AUTH_CIPHER_PAIRWISE:
 675        case IW_AUTH_CIPHER_GROUP:
 676        case IW_AUTH_KEY_MGMT:
 677                /*
 678 *                  * Host AP driver does not use these parameters and allows
 679 *                                   * wpa_supplicant to control them internally.
 680 *                                                    */
 681                break;
 682        case IW_AUTH_TKIP_COUNTERMEASURES:
 683                ieee->tkip_countermeasures = data->value;
 684                break;
 685        case IW_AUTH_DROP_UNENCRYPTED:
 686                ieee->drop_unencrypted = data->value;
 687                break;
 688
 689        case IW_AUTH_80211_AUTH_ALG:
 690                ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
 691                //printk("open_wep:%d\n", ieee->open_wep);
 692                break;
 693
 694#if 1
 695        case IW_AUTH_WPA_ENABLED:
 696                ieee->wpa_enabled = (data->value)?1:0;
 697                //printk("enable wpa:%d\n", ieee->wpa_enabled);
 698                break;
 699
 700#endif
 701        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
 702                ieee->ieee802_1x = data->value;
 703                break;
 704        case IW_AUTH_PRIVACY_INVOKED:
 705                ieee->privacy_invoked = data->value;
 706                break;
 707        default:
 708                return -EOPNOTSUPP;
 709        }
 710        return 0;
 711}
 712
 713#if 1
 714int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
 715{
 716        u8 *buf = NULL;
 717
 718        if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
 719        {
 720                printk("return error out, len:%zu\n", len);
 721        return -EINVAL;
 722        }
 723
 724        if (len)
 725        {
 726                if (len != ie[1]+2){
 727                        printk("len:%zu, ie:%d\n", len, ie[1]);
 728                        return -EINVAL;
 729                }
 730                buf = kmemdup(ie, len, GFP_KERNEL);
 731                if (buf == NULL)
 732                        return -ENOMEM;
 733                kfree(ieee->wpa_ie);
 734                ieee->wpa_ie = buf;
 735                ieee->wpa_ie_len = len;
 736        }
 737        else{
 738                kfree(ieee->wpa_ie);
 739                ieee->wpa_ie = NULL;
 740                ieee->wpa_ie_len = 0;
 741        }
 742//      printk("<=====out %s()\n", __func__);
 743
 744        return 0;
 745
 746}
 747#endif
 748