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