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