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 //skip_host_crypt: 596 //printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags); 597 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { 598 ieee->tx_keyidx = idx; 599 sec.active_key = idx; 600 sec.flags |= SEC_ACTIVE_KEY; 601 } 602 603 if (ext->alg != IW_ENCODE_ALG_NONE) { 604 memcpy(sec.keys[idx], ext->key, ext->key_len); 605 sec.key_sizes[idx] = ext->key_len; 606 sec.flags |= (1 << idx); 607 if (ext->alg == IW_ENCODE_ALG_WEP) { 608 // sec.encode_alg[idx] = SEC_ALG_WEP; 609 sec.flags |= SEC_LEVEL; 610 sec.level = SEC_LEVEL_1; 611 } else if (ext->alg == IW_ENCODE_ALG_TKIP) { 612 // sec.encode_alg[idx] = SEC_ALG_TKIP; 613 sec.flags |= SEC_LEVEL; 614 sec.level = SEC_LEVEL_2; 615 } else if (ext->alg == IW_ENCODE_ALG_CCMP) { 616 // sec.encode_alg[idx] = SEC_ALG_CCMP; 617 sec.flags |= SEC_LEVEL; 618 sec.level = SEC_LEVEL_3; 619 } 620 /* Don't set sec level for group keys. */ 621 if (group_key) 622 sec.flags &= ~SEC_LEVEL; 623 } 624done: 625 if (ieee->set_security) 626 ieee->set_security(ieee->dev, &sec); 627 628 if (ieee->reset_on_keychange && 629 ieee->iw_mode != IW_MODE_INFRA && 630 ieee->reset_port && ieee->reset_port(dev)) { 631 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name); 632 return -EINVAL; 633 } 634 635 return ret; 636} 637int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, 638 struct iw_request_info *info, 639 union iwreq_data *wrqu, char *extra) 640{ 641 struct iw_mlme *mlme = (struct iw_mlme *) extra; 642// printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd); 643 switch (mlme->cmd) { 644 case IW_MLME_DEAUTH: 645 case IW_MLME_DISASSOC: 646 // printk("disassoc now\n"); 647 ieee80211_disassociate(ieee); 648 break; 649 default: 650 return -EOPNOTSUPP; 651 } 652 return 0; 653} 654 655int ieee80211_wx_set_auth(struct ieee80211_device *ieee, 656 struct iw_request_info *info, 657 struct iw_param *data, char *extra) 658{ 659/* 660 struct ieee80211_security sec = { 661 .flags = SEC_AUTH_MODE, 662 } 663*/ 664 //printk("set auth:flag:%x, data value:%x\n", data->flags, data->value); 665 switch (data->flags & IW_AUTH_INDEX) { 666 case IW_AUTH_WPA_VERSION: 667 /*need to support wpa2 here*/ 668 //printk("wpa version:%x\n", data->value); 669 break; 670 case IW_AUTH_CIPHER_PAIRWISE: 671 case IW_AUTH_CIPHER_GROUP: 672 case IW_AUTH_KEY_MGMT: 673 /* 674 * * Host AP driver does not use these parameters and allows 675 * * wpa_supplicant to control them internally. 676 * */ 677 break; 678 case IW_AUTH_TKIP_COUNTERMEASURES: 679 ieee->tkip_countermeasures = data->value; 680 break; 681 case IW_AUTH_DROP_UNENCRYPTED: 682 ieee->drop_unencrypted = data->value; 683 break; 684 685 case IW_AUTH_80211_AUTH_ALG: 686 ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0; 687 //printk("open_wep:%d\n", ieee->open_wep); 688 break; 689 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 case IW_AUTH_RX_UNENCRYPTED_EAPOL: 695 ieee->ieee802_1x = data->value; 696 break; 697 case IW_AUTH_PRIVACY_INVOKED: 698 ieee->privacy_invoked = data->value; 699 break; 700 default: 701 return -EOPNOTSUPP; 702 } 703 return 0; 704} 705 706int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) 707{ 708 u8 *buf = NULL; 709 710 if (len>MAX_WPA_IE_LEN || (len && ie == NULL)) 711 { 712 printk("return error out, len:%zu\n", len); 713 return -EINVAL; 714 } 715 716 if (len) 717 { 718 if (len != ie[1]+2){ 719 printk("len:%zu, ie:%d\n", len, ie[1]); 720 return -EINVAL; 721 } 722 buf = kmemdup(ie, len, GFP_KERNEL); 723 if (buf == NULL) 724 return -ENOMEM; 725 kfree(ieee->wpa_ie); 726 ieee->wpa_ie = buf; 727 ieee->wpa_ie_len = len; 728 } 729 else{ 730 if (ieee->wpa_ie) 731 kfree(ieee->wpa_ie); 732 ieee->wpa_ie = NULL; 733 ieee->wpa_ie_len = 0; 734 } 735// printk("<=====out %s()\n", __func__); 736 737 return 0; 738 739} 740