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