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