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