1 /* 2 * cfg80211 - wext compat code 3 * 4 * This is temporary code until all wireless functionality is migrated 5 * into cfg80211, when that happens all the exports here go away and 6 * we directly assign the wireless handlers of wireless interfaces. 7 * 8 * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> 9 */ 10 11 #include <linux/wireless.h> 12 #include <linux/nl80211.h> 13 #include <linux/if_arp.h> 14 #include <linux/etherdevice.h> 15 #include <net/iw_handler.h> 16 #include <net/cfg80211.h> 17 #include "core.h" 18 19 int cfg80211_wext_giwname(struct net_device *dev, 20 struct iw_request_info *info, 21 char *name, char *extra) 22 { 23 struct wireless_dev *wdev = dev->ieee80211_ptr; 24 struct ieee80211_supported_band *sband; 25 bool is_ht = false, is_a = false, is_b = false, is_g = false; 26 27 if (!wdev) 28 return -EOPNOTSUPP; 29 30 sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; 31 if (sband) { 32 is_a = true; 33 is_ht |= sband->ht_cap.ht_supported; 34 } 35 36 sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; 37 if (sband) { 38 int i; 39 /* Check for mandatory rates */ 40 for (i = 0; i < sband->n_bitrates; i++) { 41 if (sband->bitrates[i].bitrate == 10) 42 is_b = true; 43 if (sband->bitrates[i].bitrate == 60) 44 is_g = true; 45 } 46 is_ht |= sband->ht_cap.ht_supported; 47 } 48 49 strcpy(name, "IEEE 802.11"); 50 if (is_a) 51 strcat(name, "a"); 52 if (is_b) 53 strcat(name, "b"); 54 if (is_g) 55 strcat(name, "g"); 56 if (is_ht) 57 strcat(name, "n"); 58 59 return 0; 60 } 61 EXPORT_SYMBOL_GPL(cfg80211_wext_giwname); 62 63 int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, 64 u32 *mode, char *extra) 65 { 66 struct wireless_dev *wdev = dev->ieee80211_ptr; 67 struct cfg80211_registered_device *rdev; 68 struct vif_params vifparams; 69 enum nl80211_iftype type; 70 int ret; 71 72 if (!wdev) 73 return -EOPNOTSUPP; 74 75 rdev = wiphy_to_dev(wdev->wiphy); 76 77 if (!rdev->ops->change_virtual_intf) 78 return -EOPNOTSUPP; 79 80 /* don't support changing VLANs, you just re-create them */ 81 if (wdev->iftype == NL80211_IFTYPE_AP_VLAN) 82 return -EOPNOTSUPP; 83 84 switch (*mode) { 85 case IW_MODE_INFRA: 86 type = NL80211_IFTYPE_STATION; 87 break; 88 case IW_MODE_ADHOC: 89 type = NL80211_IFTYPE_ADHOC; 90 break; 91 case IW_MODE_REPEAT: 92 type = NL80211_IFTYPE_WDS; 93 break; 94 case IW_MODE_MONITOR: 95 type = NL80211_IFTYPE_MONITOR; 96 break; 97 default: 98 return -EINVAL; 99 } 100 101 if (type == wdev->iftype) 102 return 0; 103 104 memset(&vifparams, 0, sizeof(vifparams)); 105 106 ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, 107 NULL, &vifparams); 108 WARN_ON(!ret && wdev->iftype != type); 109 110 return ret; 111 } 112 EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); 113 114 int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, 115 u32 *mode, char *extra) 116 { 117 struct wireless_dev *wdev = dev->ieee80211_ptr; 118 119 if (!wdev) 120 return -EOPNOTSUPP; 121 122 switch (wdev->iftype) { 123 case NL80211_IFTYPE_AP: 124 *mode = IW_MODE_MASTER; 125 break; 126 case NL80211_IFTYPE_STATION: 127 *mode = IW_MODE_INFRA; 128 break; 129 case NL80211_IFTYPE_ADHOC: 130 *mode = IW_MODE_ADHOC; 131 break; 132 case NL80211_IFTYPE_MONITOR: 133 *mode = IW_MODE_MONITOR; 134 break; 135 case NL80211_IFTYPE_WDS: 136 *mode = IW_MODE_REPEAT; 137 break; 138 case NL80211_IFTYPE_AP_VLAN: 139 *mode = IW_MODE_SECOND; /* FIXME */ 140 break; 141 default: 142 *mode = IW_MODE_AUTO; 143 break; 144 } 145 return 0; 146 } 147 EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode); 148 149 150 int cfg80211_wext_giwrange(struct net_device *dev, 151 struct iw_request_info *info, 152 struct iw_point *data, char *extra) 153 { 154 struct wireless_dev *wdev = dev->ieee80211_ptr; 155 struct iw_range *range = (struct iw_range *) extra; 156 enum ieee80211_band band; 157 int c = 0; 158 159 if (!wdev) 160 return -EOPNOTSUPP; 161 162 data->length = sizeof(struct iw_range); 163 memset(range, 0, sizeof(struct iw_range)); 164 165 range->we_version_compiled = WIRELESS_EXT; 166 range->we_version_source = 21; 167 range->retry_capa = IW_RETRY_LIMIT; 168 range->retry_flags = IW_RETRY_LIMIT; 169 range->min_retry = 0; 170 range->max_retry = 255; 171 range->min_rts = 0; 172 range->max_rts = 2347; 173 range->min_frag = 256; 174 range->max_frag = 2346; 175 176 range->encoding_size[0] = 5; 177 range->encoding_size[1] = 13; 178 range->num_encoding_sizes = 2; 179 range->max_encoding_tokens = 4; 180 181 range->max_qual.updated = IW_QUAL_NOISE_INVALID; 182 183 switch (wdev->wiphy->signal_type) { 184 case CFG80211_SIGNAL_TYPE_NONE: 185 break; 186 case CFG80211_SIGNAL_TYPE_MBM: 187 range->max_qual.level = -110; 188 range->max_qual.qual = 70; 189 range->avg_qual.qual = 35; 190 range->max_qual.updated |= IW_QUAL_DBM; 191 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED; 192 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED; 193 break; 194 case CFG80211_SIGNAL_TYPE_UNSPEC: 195 range->max_qual.level = 100; 196 range->max_qual.qual = 100; 197 range->avg_qual.qual = 50; 198 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED; 199 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED; 200 break; 201 } 202 203 range->avg_qual.level = range->max_qual.level / 2; 204 range->avg_qual.noise = range->max_qual.noise / 2; 205 range->avg_qual.updated = range->max_qual.updated; 206 207 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | 208 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; 209 210 for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { 211 int i; 212 struct ieee80211_supported_band *sband; 213 214 sband = wdev->wiphy->bands[band]; 215 216 if (!sband) 217 continue; 218 219 for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) { 220 struct ieee80211_channel *chan = &sband->channels[i]; 221 222 if (!(chan->flags & IEEE80211_CHAN_DISABLED)) { 223 range->freq[c].i = 224 ieee80211_frequency_to_channel( 225 chan->center_freq); 226 range->freq[c].m = chan->center_freq; 227 range->freq[c].e = 6; 228 c++; 229 } 230 } 231 } 232 range->num_channels = c; 233 range->num_frequency = c; 234 235 IW_EVENT_CAPA_SET_KERNEL(range->event_capa); 236 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); 237 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); 238 239 range->scan_capa |= IW_SCAN_CAPA_ESSID; 240 241 return 0; 242 } 243 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange); 244 245 int cfg80211_wext_siwmlme(struct net_device *dev, 246 struct iw_request_info *info, 247 struct iw_point *data, char *extra) 248 { 249 struct wireless_dev *wdev = dev->ieee80211_ptr; 250 struct iw_mlme *mlme = (struct iw_mlme *)extra; 251 struct cfg80211_registered_device *rdev; 252 union { 253 struct cfg80211_disassoc_request disassoc; 254 struct cfg80211_deauth_request deauth; 255 } cmd; 256 257 if (!wdev) 258 return -EOPNOTSUPP; 259 260 rdev = wiphy_to_dev(wdev->wiphy); 261 262 if (wdev->iftype != NL80211_IFTYPE_STATION) 263 return -EINVAL; 264 265 if (mlme->addr.sa_family != ARPHRD_ETHER) 266 return -EINVAL; 267 268 memset(&cmd, 0, sizeof(cmd)); 269 270 switch (mlme->cmd) { 271 case IW_MLME_DEAUTH: 272 if (!rdev->ops->deauth) 273 return -EOPNOTSUPP; 274 cmd.deauth.peer_addr = mlme->addr.sa_data; 275 cmd.deauth.reason_code = mlme->reason_code; 276 return rdev->ops->deauth(wdev->wiphy, dev, &cmd.deauth); 277 case IW_MLME_DISASSOC: 278 if (!rdev->ops->disassoc) 279 return -EOPNOTSUPP; 280 cmd.disassoc.peer_addr = mlme->addr.sa_data; 281 cmd.disassoc.reason_code = mlme->reason_code; 282 return rdev->ops->disassoc(wdev->wiphy, dev, &cmd.disassoc); 283 default: 284 return -EOPNOTSUPP; 285 } 286 } 287 EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); 288 289 290 /** 291 * cfg80211_wext_freq - get wext frequency for non-"auto" 292 * @wiphy: the wiphy 293 * @freq: the wext freq encoding 294 * 295 * Returns a channel, %NULL for auto, or an ERR_PTR for errors! 296 */ 297 struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 298 struct iw_freq *freq) 299 { 300 struct ieee80211_channel *chan; 301 int f; 302 303 /* 304 * Parse frequency - return NULL for auto and 305 * -EINVAL for impossible things. 306 */ 307 if (freq->e == 0) { 308 if (freq->m < 0) 309 return NULL; 310 f = ieee80211_channel_to_frequency(freq->m); 311 } else { 312 int i, div = 1000000; 313 for (i = 0; i < freq->e; i++) 314 div /= 10; 315 if (div <= 0) 316 return ERR_PTR(-EINVAL); 317 f = freq->m / div; 318 } 319 320 /* 321 * Look up channel struct and return -EINVAL when 322 * it cannot be found. 323 */ 324 chan = ieee80211_get_channel(wiphy, f); 325 if (!chan) 326 return ERR_PTR(-EINVAL); 327 return chan; 328 } 329 EXPORT_SYMBOL_GPL(cfg80211_wext_freq); 330 331 int cfg80211_wext_siwrts(struct net_device *dev, 332 struct iw_request_info *info, 333 struct iw_param *rts, char *extra) 334 { 335 struct wireless_dev *wdev = dev->ieee80211_ptr; 336 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 337 u32 orts = wdev->wiphy->rts_threshold; 338 int err; 339 340 if (rts->disabled || !rts->fixed) 341 wdev->wiphy->rts_threshold = (u32) -1; 342 else if (rts->value < 0) 343 return -EINVAL; 344 else 345 wdev->wiphy->rts_threshold = rts->value; 346 347 err = rdev->ops->set_wiphy_params(wdev->wiphy, 348 WIPHY_PARAM_RTS_THRESHOLD); 349 if (err) 350 wdev->wiphy->rts_threshold = orts; 351 352 return err; 353 } 354 EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts); 355 356 int cfg80211_wext_giwrts(struct net_device *dev, 357 struct iw_request_info *info, 358 struct iw_param *rts, char *extra) 359 { 360 struct wireless_dev *wdev = dev->ieee80211_ptr; 361 362 rts->value = wdev->wiphy->rts_threshold; 363 rts->disabled = rts->value == (u32) -1; 364 rts->fixed = 1; 365 366 return 0; 367 } 368 EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts); 369 370 int cfg80211_wext_siwfrag(struct net_device *dev, 371 struct iw_request_info *info, 372 struct iw_param *frag, char *extra) 373 { 374 struct wireless_dev *wdev = dev->ieee80211_ptr; 375 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 376 u32 ofrag = wdev->wiphy->frag_threshold; 377 int err; 378 379 if (frag->disabled || !frag->fixed) 380 wdev->wiphy->frag_threshold = (u32) -1; 381 else if (frag->value < 256) 382 return -EINVAL; 383 else { 384 /* Fragment length must be even, so strip LSB. */ 385 wdev->wiphy->frag_threshold = frag->value & ~0x1; 386 } 387 388 err = rdev->ops->set_wiphy_params(wdev->wiphy, 389 WIPHY_PARAM_FRAG_THRESHOLD); 390 if (err) 391 wdev->wiphy->frag_threshold = ofrag; 392 393 return err; 394 } 395 EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag); 396 397 int cfg80211_wext_giwfrag(struct net_device *dev, 398 struct iw_request_info *info, 399 struct iw_param *frag, char *extra) 400 { 401 struct wireless_dev *wdev = dev->ieee80211_ptr; 402 403 frag->value = wdev->wiphy->frag_threshold; 404 frag->disabled = frag->value == (u32) -1; 405 frag->fixed = 1; 406 407 return 0; 408 } 409 EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag); 410 411 int cfg80211_wext_siwretry(struct net_device *dev, 412 struct iw_request_info *info, 413 struct iw_param *retry, char *extra) 414 { 415 struct wireless_dev *wdev = dev->ieee80211_ptr; 416 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 417 u32 changed = 0; 418 u8 olong = wdev->wiphy->retry_long; 419 u8 oshort = wdev->wiphy->retry_short; 420 int err; 421 422 if (retry->disabled || 423 (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) 424 return -EINVAL; 425 426 if (retry->flags & IW_RETRY_LONG) { 427 wdev->wiphy->retry_long = retry->value; 428 changed |= WIPHY_PARAM_RETRY_LONG; 429 } else if (retry->flags & IW_RETRY_SHORT) { 430 wdev->wiphy->retry_short = retry->value; 431 changed |= WIPHY_PARAM_RETRY_SHORT; 432 } else { 433 wdev->wiphy->retry_short = retry->value; 434 wdev->wiphy->retry_long = retry->value; 435 changed |= WIPHY_PARAM_RETRY_LONG; 436 changed |= WIPHY_PARAM_RETRY_SHORT; 437 } 438 439 if (!changed) 440 return 0; 441 442 err = rdev->ops->set_wiphy_params(wdev->wiphy, changed); 443 if (err) { 444 wdev->wiphy->retry_short = oshort; 445 wdev->wiphy->retry_long = olong; 446 } 447 448 return err; 449 } 450 EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry); 451 452 int cfg80211_wext_giwretry(struct net_device *dev, 453 struct iw_request_info *info, 454 struct iw_param *retry, char *extra) 455 { 456 struct wireless_dev *wdev = dev->ieee80211_ptr; 457 458 retry->disabled = 0; 459 460 if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) { 461 /* 462 * First return short value, iwconfig will ask long value 463 * later if needed 464 */ 465 retry->flags |= IW_RETRY_LIMIT; 466 retry->value = wdev->wiphy->retry_short; 467 if (wdev->wiphy->retry_long != wdev->wiphy->retry_short) 468 retry->flags |= IW_RETRY_LONG; 469 470 return 0; 471 } 472 473 if (retry->flags & IW_RETRY_LONG) { 474 retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; 475 retry->value = wdev->wiphy->retry_long; 476 } 477 478 return 0; 479 } 480 EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 481 482 static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 483 struct net_device *dev, const u8 *addr, 484 bool remove, bool tx_key, int idx, 485 struct key_params *params) 486 { 487 struct wireless_dev *wdev = dev->ieee80211_ptr; 488 int err; 489 490 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 491 if (!rdev->ops->set_default_mgmt_key) 492 return -EOPNOTSUPP; 493 494 if (idx < 4 || idx > 5) 495 return -EINVAL; 496 } else if (idx < 0 || idx > 3) 497 return -EINVAL; 498 499 if (remove) { 500 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 501 if (!err) { 502 if (idx == wdev->wext.default_key) 503 wdev->wext.default_key = -1; 504 else if (idx == wdev->wext.default_mgmt_key) 505 wdev->wext.default_mgmt_key = -1; 506 } 507 /* 508 * Applications using wireless extensions expect to be 509 * able to delete keys that don't exist, so allow that. 510 */ 511 if (err == -ENOENT) 512 return 0; 513 514 return err; 515 } else { 516 if (addr) 517 tx_key = false; 518 519 if (cfg80211_validate_key_settings(params, idx, addr)) 520 return -EINVAL; 521 522 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 523 if (err) 524 return err; 525 526 if (tx_key || (!addr && wdev->wext.default_key == -1)) { 527 err = rdev->ops->set_default_key(&rdev->wiphy, 528 dev, idx); 529 if (!err) 530 wdev->wext.default_key = idx; 531 return err; 532 } 533 534 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && 535 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { 536 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, 537 dev, idx); 538 if (!err) 539 wdev->wext.default_mgmt_key = idx; 540 return err; 541 } 542 543 return 0; 544 } 545 } 546 547 int cfg80211_wext_siwencode(struct net_device *dev, 548 struct iw_request_info *info, 549 struct iw_point *erq, char *keybuf) 550 { 551 struct wireless_dev *wdev = dev->ieee80211_ptr; 552 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 553 int idx, err; 554 bool remove = false; 555 struct key_params params; 556 557 /* no use -- only MFP (set_default_mgmt_key) is optional */ 558 if (!rdev->ops->del_key || 559 !rdev->ops->add_key || 560 !rdev->ops->set_default_key) 561 return -EOPNOTSUPP; 562 563 idx = erq->flags & IW_ENCODE_INDEX; 564 if (idx == 0) { 565 idx = wdev->wext.default_key; 566 if (idx < 0) 567 idx = 0; 568 } else if (idx < 1 || idx > 4) 569 return -EINVAL; 570 else 571 idx--; 572 573 if (erq->flags & IW_ENCODE_DISABLED) 574 remove = true; 575 else if (erq->length == 0) { 576 /* No key data - just set the default TX key index */ 577 err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx); 578 if (!err) 579 wdev->wext.default_key = idx; 580 return err; 581 } 582 583 memset(¶ms, 0, sizeof(params)); 584 params.key = keybuf; 585 params.key_len = erq->length; 586 if (erq->length == 5) 587 params.cipher = WLAN_CIPHER_SUITE_WEP40; 588 else if (erq->length == 13) 589 params.cipher = WLAN_CIPHER_SUITE_WEP104; 590 else if (!remove) 591 return -EINVAL; 592 593 return cfg80211_set_encryption(rdev, dev, NULL, remove, 594 wdev->wext.default_key == -1, 595 idx, ¶ms); 596 } 597 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode); 598 599 int cfg80211_wext_siwencodeext(struct net_device *dev, 600 struct iw_request_info *info, 601 struct iw_point *erq, char *extra) 602 { 603 struct wireless_dev *wdev = dev->ieee80211_ptr; 604 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 605 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; 606 const u8 *addr; 607 int idx; 608 bool remove = false; 609 struct key_params params; 610 u32 cipher; 611 612 /* no use -- only MFP (set_default_mgmt_key) is optional */ 613 if (!rdev->ops->del_key || 614 !rdev->ops->add_key || 615 !rdev->ops->set_default_key) 616 return -EOPNOTSUPP; 617 618 switch (ext->alg) { 619 case IW_ENCODE_ALG_NONE: 620 remove = true; 621 cipher = 0; 622 break; 623 case IW_ENCODE_ALG_WEP: 624 if (ext->key_len == 5) 625 cipher = WLAN_CIPHER_SUITE_WEP40; 626 else if (ext->key_len == 13) 627 cipher = WLAN_CIPHER_SUITE_WEP104; 628 else 629 return -EINVAL; 630 break; 631 case IW_ENCODE_ALG_TKIP: 632 cipher = WLAN_CIPHER_SUITE_TKIP; 633 break; 634 case IW_ENCODE_ALG_CCMP: 635 cipher = WLAN_CIPHER_SUITE_CCMP; 636 break; 637 case IW_ENCODE_ALG_AES_CMAC: 638 cipher = WLAN_CIPHER_SUITE_AES_CMAC; 639 break; 640 default: 641 return -EOPNOTSUPP; 642 } 643 644 if (erq->flags & IW_ENCODE_DISABLED) 645 remove = true; 646 647 idx = erq->flags & IW_ENCODE_INDEX; 648 if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 649 if (idx < 4 || idx > 5) { 650 idx = wdev->wext.default_mgmt_key; 651 if (idx < 0) 652 return -EINVAL; 653 } else 654 idx--; 655 } else { 656 if (idx < 1 || idx > 4) { 657 idx = wdev->wext.default_key; 658 if (idx < 0) 659 return -EINVAL; 660 } else 661 idx--; 662 } 663 664 addr = ext->addr.sa_data; 665 if (is_broadcast_ether_addr(addr)) 666 addr = NULL; 667 668 memset(¶ms, 0, sizeof(params)); 669 params.key = ext->key; 670 params.key_len = ext->key_len; 671 params.cipher = cipher; 672 673 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { 674 params.seq = ext->rx_seq; 675 params.seq_len = 6; 676 } 677 678 return cfg80211_set_encryption( 679 rdev, dev, addr, remove, 680 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 681 idx, ¶ms); 682 } 683 EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); 684 685 struct giwencode_cookie { 686 size_t buflen; 687 char *keybuf; 688 }; 689 690 static void giwencode_get_key_cb(void *cookie, struct key_params *params) 691 { 692 struct giwencode_cookie *data = cookie; 693 694 if (!params->key) { 695 data->buflen = 0; 696 return; 697 } 698 699 data->buflen = min_t(size_t, data->buflen, params->key_len); 700 memcpy(data->keybuf, params->key, data->buflen); 701 } 702 703 int cfg80211_wext_giwencode(struct net_device *dev, 704 struct iw_request_info *info, 705 struct iw_point *erq, char *keybuf) 706 { 707 struct wireless_dev *wdev = dev->ieee80211_ptr; 708 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 709 int idx, err; 710 struct giwencode_cookie data = { 711 .keybuf = keybuf, 712 .buflen = erq->length, 713 }; 714 715 if (!rdev->ops->get_key) 716 return -EOPNOTSUPP; 717 718 idx = erq->flags & IW_ENCODE_INDEX; 719 if (idx == 0) { 720 idx = wdev->wext.default_key; 721 if (idx < 0) 722 idx = 0; 723 } else if (idx < 1 || idx > 4) 724 return -EINVAL; 725 else 726 idx--; 727 728 erq->flags = idx + 1; 729 730 err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data, 731 giwencode_get_key_cb); 732 if (!err) { 733 erq->length = data.buflen; 734 erq->flags |= IW_ENCODE_ENABLED; 735 return 0; 736 } 737 738 if (err == -ENOENT) { 739 erq->flags |= IW_ENCODE_DISABLED; 740 erq->length = 0; 741 return 0; 742 } 743 744 return err; 745 } 746 EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); 747 748 int cfg80211_wext_siwtxpower(struct net_device *dev, 749 struct iw_request_info *info, 750 union iwreq_data *data, char *extra) 751 { 752 struct wireless_dev *wdev = dev->ieee80211_ptr; 753 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 754 enum tx_power_setting type; 755 int dbm = 0; 756 757 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) 758 return -EINVAL; 759 if (data->txpower.flags & IW_TXPOW_RANGE) 760 return -EINVAL; 761 762 if (!rdev->ops->set_tx_power) 763 return -EOPNOTSUPP; 764 765 /* only change when not disabling */ 766 if (!data->txpower.disabled) { 767 rfkill_set_sw_state(rdev->rfkill, false); 768 769 if (data->txpower.fixed) { 770 /* 771 * wext doesn't support negative values, see 772 * below where it's for automatic 773 */ 774 if (data->txpower.value < 0) 775 return -EINVAL; 776 dbm = data->txpower.value; 777 type = TX_POWER_FIXED; 778 /* TODO: do regulatory check! */ 779 } else { 780 /* 781 * Automatic power level setting, max being the value 782 * passed in from userland. 783 */ 784 if (data->txpower.value < 0) { 785 type = TX_POWER_AUTOMATIC; 786 } else { 787 dbm = data->txpower.value; 788 type = TX_POWER_LIMITED; 789 } 790 } 791 } else { 792 rfkill_set_sw_state(rdev->rfkill, true); 793 schedule_work(&rdev->rfkill_sync); 794 return 0; 795 } 796 797 return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);; 798 } 799 EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower); 800 801 int cfg80211_wext_giwtxpower(struct net_device *dev, 802 struct iw_request_info *info, 803 union iwreq_data *data, char *extra) 804 { 805 struct wireless_dev *wdev = dev->ieee80211_ptr; 806 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 807 int err, val; 808 809 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) 810 return -EINVAL; 811 if (data->txpower.flags & IW_TXPOW_RANGE) 812 return -EINVAL; 813 814 if (!rdev->ops->get_tx_power) 815 return -EOPNOTSUPP; 816 817 err = rdev->ops->get_tx_power(wdev->wiphy, &val); 818 if (err) 819 return err; 820 821 /* well... oh well */ 822 data->txpower.fixed = 1; 823 data->txpower.disabled = rfkill_blocked(rdev->rfkill); 824 data->txpower.value = val; 825 data->txpower.flags = IW_TXPOW_DBM; 826 827 return 0; 828 } 829 EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower); 830