diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 14 | ||||
-rw-r--r-- | net/wireless/genregdb.awk | 1 | ||||
-rw-r--r-- | net/wireless/ibss.c | 4 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_ccmp.c | 1 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_tkip.c | 3 | ||||
-rw-r--r-- | net/wireless/lib80211_crypt_wep.c | 1 | ||||
-rw-r--r-- | net/wireless/reg.c | 659 | ||||
-rw-r--r-- | net/wireless/scan.c | 5 | ||||
-rw-r--r-- | net/wireless/sme.c | 2 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 1 |
10 files changed, 25 insertions, 666 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 47fcfd0eebc2..f65c6494ede9 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -472,24 +472,22 @@ int wiphy_register(struct wiphy *wiphy) | |||
472 | /* check and set up bitrates */ | 472 | /* check and set up bitrates */ |
473 | ieee80211_set_bitrate_flags(wiphy); | 473 | ieee80211_set_bitrate_flags(wiphy); |
474 | 474 | ||
475 | mutex_lock(&cfg80211_mutex); | ||
476 | |||
475 | res = device_add(&rdev->wiphy.dev); | 477 | res = device_add(&rdev->wiphy.dev); |
476 | if (res) | 478 | if (res) |
477 | return res; | 479 | goto out_unlock; |
478 | 480 | ||
479 | res = rfkill_register(rdev->rfkill); | 481 | res = rfkill_register(rdev->rfkill); |
480 | if (res) | 482 | if (res) |
481 | goto out_rm_dev; | 483 | goto out_rm_dev; |
482 | 484 | ||
483 | mutex_lock(&cfg80211_mutex); | ||
484 | |||
485 | /* set up regulatory info */ | 485 | /* set up regulatory info */ |
486 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); | 486 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); |
487 | 487 | ||
488 | list_add_rcu(&rdev->list, &cfg80211_rdev_list); | 488 | list_add_rcu(&rdev->list, &cfg80211_rdev_list); |
489 | cfg80211_rdev_list_generation++; | 489 | cfg80211_rdev_list_generation++; |
490 | 490 | ||
491 | mutex_unlock(&cfg80211_mutex); | ||
492 | |||
493 | /* add to debugfs */ | 491 | /* add to debugfs */ |
494 | rdev->wiphy.debugfsdir = | 492 | rdev->wiphy.debugfsdir = |
495 | debugfs_create_dir(wiphy_name(&rdev->wiphy), | 493 | debugfs_create_dir(wiphy_name(&rdev->wiphy), |
@@ -509,11 +507,15 @@ int wiphy_register(struct wiphy *wiphy) | |||
509 | } | 507 | } |
510 | 508 | ||
511 | cfg80211_debugfs_rdev_add(rdev); | 509 | cfg80211_debugfs_rdev_add(rdev); |
510 | mutex_unlock(&cfg80211_mutex); | ||
512 | 511 | ||
513 | return 0; | 512 | return 0; |
514 | 513 | ||
515 | out_rm_dev: | 514 | out_rm_dev: |
516 | device_del(&rdev->wiphy.dev); | 515 | device_del(&rdev->wiphy.dev); |
516 | |||
517 | out_unlock: | ||
518 | mutex_unlock(&cfg80211_mutex); | ||
517 | return res; | 519 | return res; |
518 | } | 520 | } |
519 | EXPORT_SYMBOL(wiphy_register); | 521 | EXPORT_SYMBOL(wiphy_register); |
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 3cc9e69880a8..53c143f5e770 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
@@ -21,6 +21,7 @@ BEGIN { | |||
21 | print "" | 21 | print "" |
22 | print "#include <linux/nl80211.h>" | 22 | print "#include <linux/nl80211.h>" |
23 | print "#include <net/cfg80211.h>" | 23 | print "#include <net/cfg80211.h>" |
24 | print "#include \"regdb.h\"" | ||
24 | print "" | 25 | print "" |
25 | regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" | 26 | regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" |
26 | } | 27 | } |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index adcabba02e20..27a8ce9343c3 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -247,8 +247,10 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
247 | if (!netif_running(wdev->netdev)) | 247 | if (!netif_running(wdev->netdev)) |
248 | return 0; | 248 | return 0; |
249 | 249 | ||
250 | if (wdev->wext.keys) | 250 | if (wdev->wext.keys) { |
251 | wdev->wext.keys->def = wdev->wext.default_key; | 251 | wdev->wext.keys->def = wdev->wext.default_key; |
252 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; | ||
253 | } | ||
252 | 254 | ||
253 | wdev->wext.ibss.privacy = wdev->wext.default_key != -1; | 255 | wdev->wext.ibss.privacy = wdev->wext.default_key != -1; |
254 | 256 | ||
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index b7fa31d5fd13..dacb3b4b1bdb 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c | |||
@@ -467,7 +467,6 @@ static struct lib80211_crypto_ops lib80211_crypt_ccmp = { | |||
467 | .name = "CCMP", | 467 | .name = "CCMP", |
468 | .init = lib80211_ccmp_init, | 468 | .init = lib80211_ccmp_init, |
469 | .deinit = lib80211_ccmp_deinit, | 469 | .deinit = lib80211_ccmp_deinit, |
470 | .build_iv = lib80211_ccmp_hdr, | ||
471 | .encrypt_mpdu = lib80211_ccmp_encrypt, | 470 | .encrypt_mpdu = lib80211_ccmp_encrypt, |
472 | .decrypt_mpdu = lib80211_ccmp_decrypt, | 471 | .decrypt_mpdu = lib80211_ccmp_decrypt, |
473 | .encrypt_msdu = NULL, | 472 | .encrypt_msdu = NULL, |
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 8cbdb32ff316..0fe40510e2cb 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c | |||
@@ -578,7 +578,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) | |||
578 | } | 578 | } |
579 | 579 | ||
580 | if (ieee80211_is_data_qos(hdr11->frame_control)) { | 580 | if (ieee80211_is_data_qos(hdr11->frame_control)) { |
581 | hdr[12] = le16_to_cpu(*ieee80211_get_qos_ctl(hdr11)) | 581 | hdr[12] = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(hdr11))) |
582 | & IEEE80211_QOS_CTL_TID_MASK; | 582 | & IEEE80211_QOS_CTL_TID_MASK; |
583 | } else | 583 | } else |
584 | hdr[12] = 0; /* priority */ | 584 | hdr[12] = 0; /* priority */ |
@@ -757,7 +757,6 @@ static struct lib80211_crypto_ops lib80211_crypt_tkip = { | |||
757 | .name = "TKIP", | 757 | .name = "TKIP", |
758 | .init = lib80211_tkip_init, | 758 | .init = lib80211_tkip_init, |
759 | .deinit = lib80211_tkip_deinit, | 759 | .deinit = lib80211_tkip_deinit, |
760 | .build_iv = lib80211_tkip_hdr, | ||
761 | .encrypt_mpdu = lib80211_tkip_encrypt, | 760 | .encrypt_mpdu = lib80211_tkip_encrypt, |
762 | .decrypt_mpdu = lib80211_tkip_decrypt, | 761 | .decrypt_mpdu = lib80211_tkip_decrypt, |
763 | .encrypt_msdu = lib80211_michael_mic_add, | 762 | .encrypt_msdu = lib80211_michael_mic_add, |
diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c index 6d41e05ca33b..e2e88878ba35 100644 --- a/net/wireless/lib80211_crypt_wep.c +++ b/net/wireless/lib80211_crypt_wep.c | |||
@@ -269,7 +269,6 @@ static struct lib80211_crypto_ops lib80211_crypt_wep = { | |||
269 | .name = "WEP", | 269 | .name = "WEP", |
270 | .init = lib80211_wep_init, | 270 | .init = lib80211_wep_init, |
271 | .deinit = lib80211_wep_deinit, | 271 | .deinit = lib80211_wep_deinit, |
272 | .build_iv = lib80211_wep_build_iv, | ||
273 | .encrypt_mpdu = lib80211_wep_encrypt, | 272 | .encrypt_mpdu = lib80211_wep_encrypt, |
274 | .decrypt_mpdu = lib80211_wep_decrypt, | 273 | .decrypt_mpdu = lib80211_wep_decrypt, |
275 | .encrypt_msdu = NULL, | 274 | .encrypt_msdu = NULL, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1ac2bdd46ecf..ec4e76f95044 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -67,17 +67,9 @@ static struct platform_device *reg_pdev; | |||
67 | const struct ieee80211_regdomain *cfg80211_regdomain; | 67 | const struct ieee80211_regdomain *cfg80211_regdomain; |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * We use this as a place for the rd structure built from the | ||
71 | * last parsed country IE to rest until CRDA gets back to us with | ||
72 | * what it thinks should apply for the same country | ||
73 | */ | ||
74 | static const struct ieee80211_regdomain *country_ie_regdomain; | ||
75 | |||
76 | /* | ||
77 | * Protects static reg.c components: | 70 | * Protects static reg.c components: |
78 | * - cfg80211_world_regdom | 71 | * - cfg80211_world_regdom |
79 | * - cfg80211_regdom | 72 | * - cfg80211_regdom |
80 | * - country_ie_regdomain | ||
81 | * - last_request | 73 | * - last_request |
82 | */ | 74 | */ |
83 | static DEFINE_MUTEX(reg_mutex); | 75 | static DEFINE_MUTEX(reg_mutex); |
@@ -275,25 +267,6 @@ static bool is_user_regdom_saved(void) | |||
275 | return true; | 267 | return true; |
276 | } | 268 | } |
277 | 269 | ||
278 | /** | ||
279 | * country_ie_integrity_changes - tells us if the country IE has changed | ||
280 | * @checksum: checksum of country IE of fields we are interested in | ||
281 | * | ||
282 | * If the country IE has not changed you can ignore it safely. This is | ||
283 | * useful to determine if two devices are seeing two different country IEs | ||
284 | * even on the same alpha2. Note that this will return false if no IE has | ||
285 | * been set on the wireless core yet. | ||
286 | */ | ||
287 | static bool country_ie_integrity_changes(u32 checksum) | ||
288 | { | ||
289 | /* If no IE has been set then the checksum doesn't change */ | ||
290 | if (unlikely(!last_request->country_ie_checksum)) | ||
291 | return false; | ||
292 | if (unlikely(last_request->country_ie_checksum != checksum)) | ||
293 | return true; | ||
294 | return false; | ||
295 | } | ||
296 | |||
297 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, | 270 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, |
298 | const struct ieee80211_regdomain *src_regd) | 271 | const struct ieee80211_regdomain *src_regd) |
299 | { | 272 | { |
@@ -506,471 +479,6 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, | |||
506 | } | 479 | } |
507 | 480 | ||
508 | /* | 481 | /* |
509 | * This is a work around for sanity checking ieee80211_channel_to_frequency()'s | ||
510 | * work. ieee80211_channel_to_frequency() can for example currently provide a | ||
511 | * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be | ||
512 | * an AP providing channel 8 on a country IE triplet when it sent this on the | ||
513 | * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz | ||
514 | * channel. | ||
515 | * | ||
516 | * This can be removed once ieee80211_channel_to_frequency() takes in a band. | ||
517 | */ | ||
518 | static bool chan_in_band(int chan, enum ieee80211_band band) | ||
519 | { | ||
520 | int center_freq = ieee80211_channel_to_frequency(chan); | ||
521 | |||
522 | switch (band) { | ||
523 | case IEEE80211_BAND_2GHZ: | ||
524 | if (center_freq <= 2484) | ||
525 | return true; | ||
526 | return false; | ||
527 | case IEEE80211_BAND_5GHZ: | ||
528 | if (center_freq >= 5005) | ||
529 | return true; | ||
530 | return false; | ||
531 | default: | ||
532 | return false; | ||
533 | } | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Some APs may send a country IE triplet for each channel they | ||
538 | * support and while this is completely overkill and silly we still | ||
539 | * need to support it. We avoid making a single rule for each channel | ||
540 | * though and to help us with this we use this helper to find the | ||
541 | * actual subband end channel. These type of country IE triplet | ||
542 | * scenerios are handled then, all yielding two regulaotry rules from | ||
543 | * parsing a country IE: | ||
544 | * | ||
545 | * [1] | ||
546 | * [2] | ||
547 | * [36] | ||
548 | * [40] | ||
549 | * | ||
550 | * [1] | ||
551 | * [2-4] | ||
552 | * [5-12] | ||
553 | * [36] | ||
554 | * [40-44] | ||
555 | * | ||
556 | * [1-4] | ||
557 | * [5-7] | ||
558 | * [36-44] | ||
559 | * [48-64] | ||
560 | * | ||
561 | * [36-36] | ||
562 | * [40-40] | ||
563 | * [44-44] | ||
564 | * [48-48] | ||
565 | * [52-52] | ||
566 | * [56-56] | ||
567 | * [60-60] | ||
568 | * [64-64] | ||
569 | * [100-100] | ||
570 | * [104-104] | ||
571 | * [108-108] | ||
572 | * [112-112] | ||
573 | * [116-116] | ||
574 | * [120-120] | ||
575 | * [124-124] | ||
576 | * [128-128] | ||
577 | * [132-132] | ||
578 | * [136-136] | ||
579 | * [140-140] | ||
580 | * | ||
581 | * Returns 0 if the IE has been found to be invalid in the middle | ||
582 | * somewhere. | ||
583 | */ | ||
584 | static int max_subband_chan(enum ieee80211_band band, | ||
585 | int orig_cur_chan, | ||
586 | int orig_end_channel, | ||
587 | s8 orig_max_power, | ||
588 | u8 **country_ie, | ||
589 | u8 *country_ie_len) | ||
590 | { | ||
591 | u8 *triplets_start = *country_ie; | ||
592 | u8 len_at_triplet = *country_ie_len; | ||
593 | int end_subband_chan = orig_end_channel; | ||
594 | |||
595 | /* | ||
596 | * We'll deal with padding for the caller unless | ||
597 | * its not immediate and we don't process any channels | ||
598 | */ | ||
599 | if (*country_ie_len == 1) { | ||
600 | *country_ie += 1; | ||
601 | *country_ie_len -= 1; | ||
602 | return orig_end_channel; | ||
603 | } | ||
604 | |||
605 | /* Move to the next triplet and then start search */ | ||
606 | *country_ie += 3; | ||
607 | *country_ie_len -= 3; | ||
608 | |||
609 | if (!chan_in_band(orig_cur_chan, band)) | ||
610 | return 0; | ||
611 | |||
612 | while (*country_ie_len >= 3) { | ||
613 | int end_channel = 0; | ||
614 | struct ieee80211_country_ie_triplet *triplet = | ||
615 | (struct ieee80211_country_ie_triplet *) *country_ie; | ||
616 | int cur_channel = 0, next_expected_chan; | ||
617 | |||
618 | /* means last triplet is completely unrelated to this one */ | ||
619 | if (triplet->ext.reg_extension_id >= | ||
620 | IEEE80211_COUNTRY_EXTENSION_ID) { | ||
621 | *country_ie -= 3; | ||
622 | *country_ie_len += 3; | ||
623 | break; | ||
624 | } | ||
625 | |||
626 | if (triplet->chans.first_channel == 0) { | ||
627 | *country_ie += 1; | ||
628 | *country_ie_len -= 1; | ||
629 | if (*country_ie_len != 0) | ||
630 | return 0; | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | if (triplet->chans.num_channels == 0) | ||
635 | return 0; | ||
636 | |||
637 | /* Monitonically increasing channel order */ | ||
638 | if (triplet->chans.first_channel <= end_subband_chan) | ||
639 | return 0; | ||
640 | |||
641 | if (!chan_in_band(triplet->chans.first_channel, band)) | ||
642 | return 0; | ||
643 | |||
644 | /* 2 GHz */ | ||
645 | if (triplet->chans.first_channel <= 14) { | ||
646 | end_channel = triplet->chans.first_channel + | ||
647 | triplet->chans.num_channels - 1; | ||
648 | } | ||
649 | else { | ||
650 | end_channel = triplet->chans.first_channel + | ||
651 | (4 * (triplet->chans.num_channels - 1)); | ||
652 | } | ||
653 | |||
654 | if (!chan_in_band(end_channel, band)) | ||
655 | return 0; | ||
656 | |||
657 | if (orig_max_power != triplet->chans.max_power) { | ||
658 | *country_ie -= 3; | ||
659 | *country_ie_len += 3; | ||
660 | break; | ||
661 | } | ||
662 | |||
663 | cur_channel = triplet->chans.first_channel; | ||
664 | |||
665 | /* The key is finding the right next expected channel */ | ||
666 | if (band == IEEE80211_BAND_2GHZ) | ||
667 | next_expected_chan = end_subband_chan + 1; | ||
668 | else | ||
669 | next_expected_chan = end_subband_chan + 4; | ||
670 | |||
671 | if (cur_channel != next_expected_chan) { | ||
672 | *country_ie -= 3; | ||
673 | *country_ie_len += 3; | ||
674 | break; | ||
675 | } | ||
676 | |||
677 | end_subband_chan = end_channel; | ||
678 | |||
679 | /* Move to the next one */ | ||
680 | *country_ie += 3; | ||
681 | *country_ie_len -= 3; | ||
682 | |||
683 | /* | ||
684 | * Padding needs to be dealt with if we processed | ||
685 | * some channels. | ||
686 | */ | ||
687 | if (*country_ie_len == 1) { | ||
688 | *country_ie += 1; | ||
689 | *country_ie_len -= 1; | ||
690 | break; | ||
691 | } | ||
692 | |||
693 | /* If seen, the IE is invalid */ | ||
694 | if (*country_ie_len == 2) | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | if (end_subband_chan == orig_end_channel) { | ||
699 | *country_ie = triplets_start; | ||
700 | *country_ie_len = len_at_triplet; | ||
701 | return orig_end_channel; | ||
702 | } | ||
703 | |||
704 | return end_subband_chan; | ||
705 | } | ||
706 | |||
707 | /* | ||
708 | * Converts a country IE to a regulatory domain. A regulatory domain | ||
709 | * structure has a lot of information which the IE doesn't yet have, | ||
710 | * so for the other values we use upper max values as we will intersect | ||
711 | * with our userspace regulatory agent to get lower bounds. | ||
712 | */ | ||
713 | static struct ieee80211_regdomain *country_ie_2_rd( | ||
714 | enum ieee80211_band band, | ||
715 | u8 *country_ie, | ||
716 | u8 country_ie_len, | ||
717 | u32 *checksum) | ||
718 | { | ||
719 | struct ieee80211_regdomain *rd = NULL; | ||
720 | unsigned int i = 0; | ||
721 | char alpha2[2]; | ||
722 | u32 flags = 0; | ||
723 | u32 num_rules = 0, size_of_regd = 0; | ||
724 | u8 *triplets_start = NULL; | ||
725 | u8 len_at_triplet = 0; | ||
726 | /* the last channel we have registered in a subband (triplet) */ | ||
727 | int last_sub_max_channel = 0; | ||
728 | |||
729 | *checksum = 0xDEADBEEF; | ||
730 | |||
731 | /* Country IE requirements */ | ||
732 | BUG_ON(country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN || | ||
733 | country_ie_len & 0x01); | ||
734 | |||
735 | alpha2[0] = country_ie[0]; | ||
736 | alpha2[1] = country_ie[1]; | ||
737 | |||
738 | /* | ||
739 | * Third octet can be: | ||
740 | * 'I' - Indoor | ||
741 | * 'O' - Outdoor | ||
742 | * | ||
743 | * anything else we assume is no restrictions | ||
744 | */ | ||
745 | if (country_ie[2] == 'I') | ||
746 | flags = NL80211_RRF_NO_OUTDOOR; | ||
747 | else if (country_ie[2] == 'O') | ||
748 | flags = NL80211_RRF_NO_INDOOR; | ||
749 | |||
750 | country_ie += 3; | ||
751 | country_ie_len -= 3; | ||
752 | |||
753 | triplets_start = country_ie; | ||
754 | len_at_triplet = country_ie_len; | ||
755 | |||
756 | *checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8); | ||
757 | |||
758 | /* | ||
759 | * We need to build a reg rule for each triplet, but first we must | ||
760 | * calculate the number of reg rules we will need. We will need one | ||
761 | * for each channel subband | ||
762 | */ | ||
763 | while (country_ie_len >= 3) { | ||
764 | int end_channel = 0; | ||
765 | struct ieee80211_country_ie_triplet *triplet = | ||
766 | (struct ieee80211_country_ie_triplet *) country_ie; | ||
767 | int cur_sub_max_channel = 0, cur_channel = 0; | ||
768 | |||
769 | if (triplet->ext.reg_extension_id >= | ||
770 | IEEE80211_COUNTRY_EXTENSION_ID) { | ||
771 | country_ie += 3; | ||
772 | country_ie_len -= 3; | ||
773 | continue; | ||
774 | } | ||
775 | |||
776 | /* | ||
777 | * APs can add padding to make length divisible | ||
778 | * by two, required by the spec. | ||
779 | */ | ||
780 | if (triplet->chans.first_channel == 0) { | ||
781 | country_ie++; | ||
782 | country_ie_len--; | ||
783 | /* This is expected to be at the very end only */ | ||
784 | if (country_ie_len != 0) | ||
785 | return NULL; | ||
786 | break; | ||
787 | } | ||
788 | |||
789 | if (triplet->chans.num_channels == 0) | ||
790 | return NULL; | ||
791 | |||
792 | if (!chan_in_band(triplet->chans.first_channel, band)) | ||
793 | return NULL; | ||
794 | |||
795 | /* 2 GHz */ | ||
796 | if (band == IEEE80211_BAND_2GHZ) | ||
797 | end_channel = triplet->chans.first_channel + | ||
798 | triplet->chans.num_channels - 1; | ||
799 | else | ||
800 | /* | ||
801 | * 5 GHz -- For example in country IEs if the first | ||
802 | * channel given is 36 and the number of channels is 4 | ||
803 | * then the individual channel numbers defined for the | ||
804 | * 5 GHz PHY by these parameters are: 36, 40, 44, and 48 | ||
805 | * and not 36, 37, 38, 39. | ||
806 | * | ||
807 | * See: http://tinyurl.com/11d-clarification | ||
808 | */ | ||
809 | end_channel = triplet->chans.first_channel + | ||
810 | (4 * (triplet->chans.num_channels - 1)); | ||
811 | |||
812 | cur_channel = triplet->chans.first_channel; | ||
813 | |||
814 | /* | ||
815 | * Enhancement for APs that send a triplet for every channel | ||
816 | * or for whatever reason sends triplets with multiple channels | ||
817 | * separated when in fact they should be together. | ||
818 | */ | ||
819 | end_channel = max_subband_chan(band, | ||
820 | cur_channel, | ||
821 | end_channel, | ||
822 | triplet->chans.max_power, | ||
823 | &country_ie, | ||
824 | &country_ie_len); | ||
825 | if (!end_channel) | ||
826 | return NULL; | ||
827 | |||
828 | if (!chan_in_band(end_channel, band)) | ||
829 | return NULL; | ||
830 | |||
831 | cur_sub_max_channel = end_channel; | ||
832 | |||
833 | /* Basic sanity check */ | ||
834 | if (cur_sub_max_channel < cur_channel) | ||
835 | return NULL; | ||
836 | |||
837 | /* | ||
838 | * Do not allow overlapping channels. Also channels | ||
839 | * passed in each subband must be monotonically | ||
840 | * increasing | ||
841 | */ | ||
842 | if (last_sub_max_channel) { | ||
843 | if (cur_channel <= last_sub_max_channel) | ||
844 | return NULL; | ||
845 | if (cur_sub_max_channel <= last_sub_max_channel) | ||
846 | return NULL; | ||
847 | } | ||
848 | |||
849 | /* | ||
850 | * When dot11RegulatoryClassesRequired is supported | ||
851 | * we can throw ext triplets as part of this soup, | ||
852 | * for now we don't care when those change as we | ||
853 | * don't support them | ||
854 | */ | ||
855 | *checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) | | ||
856 | ((cur_sub_max_channel ^ cur_sub_max_channel) << 16) | | ||
857 | ((triplet->chans.max_power ^ cur_sub_max_channel) << 24); | ||
858 | |||
859 | last_sub_max_channel = cur_sub_max_channel; | ||
860 | |||
861 | num_rules++; | ||
862 | |||
863 | if (country_ie_len >= 3) { | ||
864 | country_ie += 3; | ||
865 | country_ie_len -= 3; | ||
866 | } | ||
867 | |||
868 | /* | ||
869 | * Note: this is not a IEEE requirement but | ||
870 | * simply a memory requirement | ||
871 | */ | ||
872 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) | ||
873 | return NULL; | ||
874 | } | ||
875 | |||
876 | country_ie = triplets_start; | ||
877 | country_ie_len = len_at_triplet; | ||
878 | |||
879 | size_of_regd = sizeof(struct ieee80211_regdomain) + | ||
880 | (num_rules * sizeof(struct ieee80211_reg_rule)); | ||
881 | |||
882 | rd = kzalloc(size_of_regd, GFP_KERNEL); | ||
883 | if (!rd) | ||
884 | return NULL; | ||
885 | |||
886 | rd->n_reg_rules = num_rules; | ||
887 | rd->alpha2[0] = alpha2[0]; | ||
888 | rd->alpha2[1] = alpha2[1]; | ||
889 | |||
890 | /* This time around we fill in the rd */ | ||
891 | while (country_ie_len >= 3) { | ||
892 | int end_channel = 0; | ||
893 | struct ieee80211_country_ie_triplet *triplet = | ||
894 | (struct ieee80211_country_ie_triplet *) country_ie; | ||
895 | struct ieee80211_reg_rule *reg_rule = NULL; | ||
896 | struct ieee80211_freq_range *freq_range = NULL; | ||
897 | struct ieee80211_power_rule *power_rule = NULL; | ||
898 | |||
899 | /* | ||
900 | * Must parse if dot11RegulatoryClassesRequired is true, | ||
901 | * we don't support this yet | ||
902 | */ | ||
903 | if (triplet->ext.reg_extension_id >= | ||
904 | IEEE80211_COUNTRY_EXTENSION_ID) { | ||
905 | country_ie += 3; | ||
906 | country_ie_len -= 3; | ||
907 | continue; | ||
908 | } | ||
909 | |||
910 | if (triplet->chans.first_channel == 0) { | ||
911 | country_ie++; | ||
912 | country_ie_len--; | ||
913 | break; | ||
914 | } | ||
915 | |||
916 | reg_rule = &rd->reg_rules[i]; | ||
917 | freq_range = ®_rule->freq_range; | ||
918 | power_rule = ®_rule->power_rule; | ||
919 | |||
920 | reg_rule->flags = flags; | ||
921 | |||
922 | /* 2 GHz */ | ||
923 | if (band == IEEE80211_BAND_2GHZ) | ||
924 | end_channel = triplet->chans.first_channel + | ||
925 | triplet->chans.num_channels -1; | ||
926 | else | ||
927 | end_channel = triplet->chans.first_channel + | ||
928 | (4 * (triplet->chans.num_channels - 1)); | ||
929 | |||
930 | end_channel = max_subband_chan(band, | ||
931 | triplet->chans.first_channel, | ||
932 | end_channel, | ||
933 | triplet->chans.max_power, | ||
934 | &country_ie, | ||
935 | &country_ie_len); | ||
936 | |||
937 | /* | ||
938 | * The +10 is since the regulatory domain expects | ||
939 | * the actual band edge, not the center of freq for | ||
940 | * its start and end freqs, assuming 20 MHz bandwidth on | ||
941 | * the channels passed | ||
942 | */ | ||
943 | freq_range->start_freq_khz = | ||
944 | MHZ_TO_KHZ(ieee80211_channel_to_frequency( | ||
945 | triplet->chans.first_channel) - 10); | ||
946 | freq_range->end_freq_khz = | ||
947 | MHZ_TO_KHZ(ieee80211_channel_to_frequency( | ||
948 | end_channel) + 10); | ||
949 | |||
950 | /* | ||
951 | * These are large arbitrary values we use to intersect later. | ||
952 | * Increment this if we ever support >= 40 MHz channels | ||
953 | * in IEEE 802.11 | ||
954 | */ | ||
955 | freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40); | ||
956 | power_rule->max_antenna_gain = DBI_TO_MBI(100); | ||
957 | power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power); | ||
958 | |||
959 | i++; | ||
960 | |||
961 | if (country_ie_len >= 3) { | ||
962 | country_ie += 3; | ||
963 | country_ie_len -= 3; | ||
964 | } | ||
965 | |||
966 | BUG_ON(i > NL80211_MAX_SUPP_REG_RULES); | ||
967 | } | ||
968 | |||
969 | return rd; | ||
970 | } | ||
971 | |||
972 | |||
973 | /* | ||
974 | * Helper for regdom_intersect(), this does the real | 482 | * Helper for regdom_intersect(), this does the real |
975 | * mathematical intersection fun | 483 | * mathematical intersection fun |
976 | */ | 484 | */ |
@@ -1191,7 +699,6 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
1191 | 699 | ||
1192 | return -EINVAL; | 700 | return -EINVAL; |
1193 | } | 701 | } |
1194 | EXPORT_SYMBOL(freq_reg_info); | ||
1195 | 702 | ||
1196 | int freq_reg_info(struct wiphy *wiphy, | 703 | int freq_reg_info(struct wiphy *wiphy, |
1197 | u32 center_freq, | 704 | u32 center_freq, |
@@ -1205,6 +712,7 @@ int freq_reg_info(struct wiphy *wiphy, | |||
1205 | reg_rule, | 712 | reg_rule, |
1206 | NULL); | 713 | NULL); |
1207 | } | 714 | } |
715 | EXPORT_SYMBOL(freq_reg_info); | ||
1208 | 716 | ||
1209 | /* | 717 | /* |
1210 | * Note that right now we assume the desired channel bandwidth | 718 | * Note that right now we assume the desired channel bandwidth |
@@ -1243,41 +751,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
1243 | desired_bw_khz, | 751 | desired_bw_khz, |
1244 | ®_rule); | 752 | ®_rule); |
1245 | 753 | ||
1246 | if (r) { | 754 | if (r) |
1247 | /* | ||
1248 | * This means no regulatory rule was found in the country IE | ||
1249 | * with a frequency range on the center_freq's band, since | ||
1250 | * IEEE-802.11 allows for a country IE to have a subset of the | ||
1251 | * regulatory information provided in a country we ignore | ||
1252 | * disabling the channel unless at least one reg rule was | ||
1253 | * found on the center_freq's band. For details see this | ||
1254 | * clarification: | ||
1255 | * | ||
1256 | * http://tinyurl.com/11d-clarification | ||
1257 | */ | ||
1258 | if (r == -ERANGE && | ||
1259 | last_request->initiator == | ||
1260 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
1261 | REG_DBG_PRINT("cfg80211: Leaving channel %d MHz " | ||
1262 | "intact on %s - no rule found in band on " | ||
1263 | "Country IE\n", | ||
1264 | chan->center_freq, wiphy_name(wiphy)); | ||
1265 | } else { | ||
1266 | /* | ||
1267 | * In this case we know the country IE has at least one reg rule | ||
1268 | * for the band so we respect its band definitions | ||
1269 | */ | ||
1270 | if (last_request->initiator == | ||
1271 | NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
1272 | REG_DBG_PRINT("cfg80211: Disabling " | ||
1273 | "channel %d MHz on %s due to " | ||
1274 | "Country IE\n", | ||
1275 | chan->center_freq, wiphy_name(wiphy)); | ||
1276 | flags |= IEEE80211_CHAN_DISABLED; | ||
1277 | chan->flags = flags; | ||
1278 | } | ||
1279 | return; | 755 | return; |
1280 | } | ||
1281 | 756 | ||
1282 | power_rule = ®_rule->power_rule; | 757 | power_rule = ®_rule->power_rule; |
1283 | freq_range = ®_rule->freq_range; | 758 | freq_range = ®_rule->freq_range; |
@@ -2008,35 +1483,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
2008 | } | 1483 | } |
2009 | EXPORT_SYMBOL(regulatory_hint); | 1484 | EXPORT_SYMBOL(regulatory_hint); |
2010 | 1485 | ||
2011 | /* Caller must hold reg_mutex */ | ||
2012 | static bool reg_same_country_ie_hint(struct wiphy *wiphy, | ||
2013 | u32 country_ie_checksum) | ||
2014 | { | ||
2015 | struct wiphy *request_wiphy; | ||
2016 | |||
2017 | assert_reg_lock(); | ||
2018 | |||
2019 | if (unlikely(last_request->initiator != | ||
2020 | NL80211_REGDOM_SET_BY_COUNTRY_IE)) | ||
2021 | return false; | ||
2022 | |||
2023 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | ||
2024 | |||
2025 | if (!request_wiphy) | ||
2026 | return false; | ||
2027 | |||
2028 | if (likely(request_wiphy != wiphy)) | ||
2029 | return !country_ie_integrity_changes(country_ie_checksum); | ||
2030 | /* | ||
2031 | * We should not have let these through at this point, they | ||
2032 | * should have been picked up earlier by the first alpha2 check | ||
2033 | * on the device | ||
2034 | */ | ||
2035 | if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum))) | ||
2036 | return true; | ||
2037 | return false; | ||
2038 | } | ||
2039 | |||
2040 | /* | 1486 | /* |
2041 | * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and | 1487 | * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and |
2042 | * therefore cannot iterate over the rdev list here. | 1488 | * therefore cannot iterate over the rdev list here. |
@@ -2046,9 +1492,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
2046 | u8 *country_ie, | 1492 | u8 *country_ie, |
2047 | u8 country_ie_len) | 1493 | u8 country_ie_len) |
2048 | { | 1494 | { |
2049 | struct ieee80211_regdomain *rd = NULL; | ||
2050 | char alpha2[2]; | 1495 | char alpha2[2]; |
2051 | u32 checksum = 0; | ||
2052 | enum environment_cap env = ENVIRON_ANY; | 1496 | enum environment_cap env = ENVIRON_ANY; |
2053 | struct regulatory_request *request; | 1497 | struct regulatory_request *request; |
2054 | 1498 | ||
@@ -2064,14 +1508,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
2064 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) | 1508 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) |
2065 | goto out; | 1509 | goto out; |
2066 | 1510 | ||
2067 | /* | ||
2068 | * Pending country IE processing, this can happen after we | ||
2069 | * call CRDA and wait for a response if a beacon was received before | ||
2070 | * we were able to process the last regulatory_hint_11d() call | ||
2071 | */ | ||
2072 | if (country_ie_regdomain) | ||
2073 | goto out; | ||
2074 | |||
2075 | alpha2[0] = country_ie[0]; | 1511 | alpha2[0] = country_ie[0]; |
2076 | alpha2[1] = country_ie[1]; | 1512 | alpha2[1] = country_ie[1]; |
2077 | 1513 | ||
@@ -2090,39 +1526,14 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
2090 | wiphy_idx_valid(last_request->wiphy_idx))) | 1526 | wiphy_idx_valid(last_request->wiphy_idx))) |
2091 | goto out; | 1527 | goto out; |
2092 | 1528 | ||
2093 | rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum); | ||
2094 | if (!rd) { | ||
2095 | REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n"); | ||
2096 | goto out; | ||
2097 | } | ||
2098 | |||
2099 | /* | ||
2100 | * This will not happen right now but we leave it here for the | ||
2101 | * the future when we want to add suspend/resume support and having | ||
2102 | * the user move to another country after doing so, or having the user | ||
2103 | * move to another AP. Right now we just trust the first AP. | ||
2104 | * | ||
2105 | * If we hit this before we add this support we want to be informed of | ||
2106 | * it as it would indicate a mistake in the current design | ||
2107 | */ | ||
2108 | if (WARN_ON(reg_same_country_ie_hint(wiphy, checksum))) | ||
2109 | goto free_rd_out; | ||
2110 | |||
2111 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); | 1529 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); |
2112 | if (!request) | 1530 | if (!request) |
2113 | goto free_rd_out; | 1531 | goto out; |
2114 | |||
2115 | /* | ||
2116 | * We keep this around for when CRDA comes back with a response so | ||
2117 | * we can intersect with that | ||
2118 | */ | ||
2119 | country_ie_regdomain = rd; | ||
2120 | 1532 | ||
2121 | request->wiphy_idx = get_wiphy_idx(wiphy); | 1533 | request->wiphy_idx = get_wiphy_idx(wiphy); |
2122 | request->alpha2[0] = rd->alpha2[0]; | 1534 | request->alpha2[0] = alpha2[0]; |
2123 | request->alpha2[1] = rd->alpha2[1]; | 1535 | request->alpha2[1] = alpha2[1]; |
2124 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; | 1536 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; |
2125 | request->country_ie_checksum = checksum; | ||
2126 | request->country_ie_env = env; | 1537 | request->country_ie_env = env; |
2127 | 1538 | ||
2128 | mutex_unlock(®_mutex); | 1539 | mutex_unlock(®_mutex); |
@@ -2131,8 +1542,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
2131 | 1542 | ||
2132 | return; | 1543 | return; |
2133 | 1544 | ||
2134 | free_rd_out: | ||
2135 | kfree(rd); | ||
2136 | out: | 1545 | out: |
2137 | mutex_unlock(®_mutex); | 1546 | mutex_unlock(®_mutex); |
2138 | } | 1547 | } |
@@ -2383,33 +1792,6 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd) | |||
2383 | print_rd_rules(rd); | 1792 | print_rd_rules(rd); |
2384 | } | 1793 | } |
2385 | 1794 | ||
2386 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
2387 | static void reg_country_ie_process_debug( | ||
2388 | const struct ieee80211_regdomain *rd, | ||
2389 | const struct ieee80211_regdomain *country_ie_regdomain, | ||
2390 | const struct ieee80211_regdomain *intersected_rd) | ||
2391 | { | ||
2392 | printk(KERN_DEBUG "cfg80211: Received country IE:\n"); | ||
2393 | print_regdomain_info(country_ie_regdomain); | ||
2394 | printk(KERN_DEBUG "cfg80211: CRDA thinks this should applied:\n"); | ||
2395 | print_regdomain_info(rd); | ||
2396 | if (intersected_rd) { | ||
2397 | printk(KERN_DEBUG "cfg80211: We intersect both of these " | ||
2398 | "and get:\n"); | ||
2399 | print_regdomain_info(intersected_rd); | ||
2400 | return; | ||
2401 | } | ||
2402 | printk(KERN_DEBUG "cfg80211: Intersection between both failed\n"); | ||
2403 | } | ||
2404 | #else | ||
2405 | static inline void reg_country_ie_process_debug( | ||
2406 | const struct ieee80211_regdomain *rd, | ||
2407 | const struct ieee80211_regdomain *country_ie_regdomain, | ||
2408 | const struct ieee80211_regdomain *intersected_rd) | ||
2409 | { | ||
2410 | } | ||
2411 | #endif | ||
2412 | |||
2413 | /* Takes ownership of rd only if it doesn't fail */ | 1795 | /* Takes ownership of rd only if it doesn't fail */ |
2414 | static int __set_regdom(const struct ieee80211_regdomain *rd) | 1796 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
2415 | { | 1797 | { |
@@ -2521,34 +1903,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2521 | return 0; | 1903 | return 0; |
2522 | } | 1904 | } |
2523 | 1905 | ||
2524 | /* | ||
2525 | * Country IE requests are handled a bit differently, we intersect | ||
2526 | * the country IE rd with what CRDA believes that country should have | ||
2527 | */ | ||
2528 | |||
2529 | /* | ||
2530 | * Userspace could have sent two replies with only | ||
2531 | * one kernel request. By the second reply we would have | ||
2532 | * already processed and consumed the country_ie_regdomain. | ||
2533 | */ | ||
2534 | if (!country_ie_regdomain) | ||
2535 | return -EALREADY; | ||
2536 | BUG_ON(rd == country_ie_regdomain); | ||
2537 | |||
2538 | /* | ||
2539 | * Intersect what CRDA returned and our what we | ||
2540 | * had built from the Country IE received | ||
2541 | */ | ||
2542 | |||
2543 | intersected_rd = regdom_intersect(rd, country_ie_regdomain); | ||
2544 | |||
2545 | reg_country_ie_process_debug(rd, | ||
2546 | country_ie_regdomain, | ||
2547 | intersected_rd); | ||
2548 | |||
2549 | kfree(country_ie_regdomain); | ||
2550 | country_ie_regdomain = NULL; | ||
2551 | |||
2552 | if (!intersected_rd) | 1906 | if (!intersected_rd) |
2553 | return -EINVAL; | 1907 | return -EINVAL; |
2554 | 1908 | ||
@@ -2688,9 +2042,6 @@ void /* __init_or_exit */ regulatory_exit(void) | |||
2688 | 2042 | ||
2689 | reset_regdomains(); | 2043 | reset_regdomains(); |
2690 | 2044 | ||
2691 | kfree(country_ie_regdomain); | ||
2692 | country_ie_regdomain = NULL; | ||
2693 | |||
2694 | kfree(last_request); | 2045 | kfree(last_request); |
2695 | 2046 | ||
2696 | platform_device_unregister(reg_pdev); | 2047 | platform_device_unregister(reg_pdev); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 58401d246bda..5ca8c7180141 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -275,6 +275,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | |||
275 | { | 275 | { |
276 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); | 276 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); |
277 | struct cfg80211_internal_bss *bss, *res = NULL; | 277 | struct cfg80211_internal_bss *bss, *res = NULL; |
278 | unsigned long now = jiffies; | ||
278 | 279 | ||
279 | spin_lock_bh(&dev->bss_lock); | 280 | spin_lock_bh(&dev->bss_lock); |
280 | 281 | ||
@@ -283,6 +284,10 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | |||
283 | continue; | 284 | continue; |
284 | if (channel && bss->pub.channel != channel) | 285 | if (channel && bss->pub.channel != channel) |
285 | continue; | 286 | continue; |
287 | /* Don't get expired BSS structs */ | ||
288 | if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) && | ||
289 | !atomic_read(&bss->hold)) | ||
290 | continue; | ||
286 | if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { | 291 | if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { |
287 | res = bss; | 292 | res = bss; |
288 | kref_get(&res->ref); | 293 | kref_get(&res->ref); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 72222f0074db..a8c2d6b877ae 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -35,7 +35,7 @@ struct cfg80211_conn { | |||
35 | bool auto_auth, prev_bssid_valid; | 35 | bool auto_auth, prev_bssid_valid; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | bool cfg80211_is_all_idle(void) | 38 | static bool cfg80211_is_all_idle(void) |
39 | { | 39 | { |
40 | struct cfg80211_registered_device *rdev; | 40 | struct cfg80211_registered_device *rdev; |
41 | struct wireless_dev *wdev; | 41 | struct wireless_dev *wdev; |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 1ff1e9f49136..bb5e0a5ecfa1 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1471,6 +1471,7 @@ int cfg80211_wext_siwpmksa(struct net_device *dev, | |||
1471 | return -EOPNOTSUPP; | 1471 | return -EOPNOTSUPP; |
1472 | } | 1472 | } |
1473 | } | 1473 | } |
1474 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwpmksa); | ||
1474 | 1475 | ||
1475 | static const iw_handler cfg80211_handlers[] = { | 1476 | static const iw_handler cfg80211_handlers[] = { |
1476 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, | 1477 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, |