aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-07-15 14:57:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-20 16:44:35 -0400
commit4f366c5dabcb936dd5754a35188bd699181fe1ce (patch)
tree1a35b5e9936554634fb36f3adb1bcbffef4a5375 /net
parent53e9b1de6840d9047f768878adcbd1d116f72aca (diff)
wireless: only use alpha2 regulatory information from country IE
The meaning and/or usage of the country IE is somewhat poorly defined. In practice, this means that regulatory rulesets in a country IE are often incomplete and might be untrustworthy. This removes the code associated with interpreting those rulesets while preserving respect for country "alpha2" codes also contained in the country IE. Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/reg.c625
1 files changed, 12 insertions, 613 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 1ac2bdd46ecf..678d0bd433f0 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -67,17 +67,9 @@ static struct platform_device *reg_pdev;
67const struct ieee80211_regdomain *cfg80211_regdomain; 67const 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 */
74static 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 */
83static DEFINE_MUTEX(reg_mutex); 75static 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 */
287static 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
297static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, 270static 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 */
518static 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 */
584static 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 */
713static 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 = &reg_rule->freq_range;
918 power_rule = &reg_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}
1194EXPORT_SYMBOL(freq_reg_info);
1195 702
1196int freq_reg_info(struct wiphy *wiphy, 703int 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}
715EXPORT_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 &reg_rule); 752 &reg_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 = &reg_rule->power_rule; 757 power_rule = &reg_rule->power_rule;
1283 freq_range = &reg_rule->freq_range; 758 freq_range = &reg_rule->freq_range;
@@ -2010,7 +1485,7 @@ EXPORT_SYMBOL(regulatory_hint);
2010 1485
2011/* Caller must hold reg_mutex */ 1486/* Caller must hold reg_mutex */
2012static bool reg_same_country_ie_hint(struct wiphy *wiphy, 1487static bool reg_same_country_ie_hint(struct wiphy *wiphy,
2013 u32 country_ie_checksum) 1488 char *alpha2, enum environment_cap env)
2014{ 1489{
2015 struct wiphy *request_wiphy; 1490 struct wiphy *request_wiphy;
2016 1491
@@ -2026,13 +1501,17 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
2026 return false; 1501 return false;
2027 1502
2028 if (likely(request_wiphy != wiphy)) 1503 if (likely(request_wiphy != wiphy))
2029 return !country_ie_integrity_changes(country_ie_checksum); 1504 return (last_request->alpha2[0] == alpha2[0] &&
1505 last_request->alpha2[1] == alpha2[1] &&
1506 last_request->country_ie_env == env);
2030 /* 1507 /*
2031 * We should not have let these through at this point, they 1508 * We should not have let these through at this point, they
2032 * should have been picked up earlier by the first alpha2 check 1509 * should have been picked up earlier by the first alpha2 check
2033 * on the device 1510 * on the device
2034 */ 1511 */
2035 if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum))) 1512 if (WARN_ON((last_request->alpha2[0] == alpha2[0] &&
1513 last_request->alpha2[1] == alpha2[1] &&
1514 last_request->country_ie_env == env )))
2036 return true; 1515 return true;
2037 return false; 1516 return false;
2038} 1517}
@@ -2048,7 +1527,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
2048{ 1527{
2049 struct ieee80211_regdomain *rd = NULL; 1528 struct ieee80211_regdomain *rd = NULL;
2050 char alpha2[2]; 1529 char alpha2[2];
2051 u32 checksum = 0;
2052 enum environment_cap env = ENVIRON_ANY; 1530 enum environment_cap env = ENVIRON_ANY;
2053 struct regulatory_request *request; 1531 struct regulatory_request *request;
2054 1532
@@ -2064,14 +1542,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
2064 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 1542 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
2065 goto out; 1543 goto out;
2066 1544
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]; 1545 alpha2[0] = country_ie[0];
2076 alpha2[1] = country_ie[1]; 1546 alpha2[1] = country_ie[1];
2077 1547
@@ -2090,12 +1560,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
2090 wiphy_idx_valid(last_request->wiphy_idx))) 1560 wiphy_idx_valid(last_request->wiphy_idx)))
2091 goto out; 1561 goto out;
2092 1562
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 /* 1563 /*
2100 * This will not happen right now but we leave it here for the 1564 * 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 1565 * the future when we want to add suspend/resume support and having
@@ -2105,24 +1569,17 @@ void regulatory_hint_11d(struct wiphy *wiphy,
2105 * If we hit this before we add this support we want to be informed of 1569 * 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 1570 * it as it would indicate a mistake in the current design
2107 */ 1571 */
2108 if (WARN_ON(reg_same_country_ie_hint(wiphy, checksum))) 1572 if (WARN_ON(reg_same_country_ie_hint(wiphy, alpha2, env)))
2109 goto free_rd_out; 1573 goto free_rd_out;
2110 1574
2111 request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); 1575 request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
2112 if (!request) 1576 if (!request)
2113 goto free_rd_out; 1577 goto free_rd_out;
2114 1578
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
2121 request->wiphy_idx = get_wiphy_idx(wiphy); 1579 request->wiphy_idx = get_wiphy_idx(wiphy);
2122 request->alpha2[0] = rd->alpha2[0]; 1580 request->alpha2[0] = alpha2[0];
2123 request->alpha2[1] = rd->alpha2[1]; 1581 request->alpha2[1] = alpha2[1];
2124 request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; 1582 request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
2125 request->country_ie_checksum = checksum;
2126 request->country_ie_env = env; 1583 request->country_ie_env = env;
2127 1584
2128 mutex_unlock(&reg_mutex); 1585 mutex_unlock(&reg_mutex);
@@ -2383,33 +1840,6 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
2383 print_rd_rules(rd); 1840 print_rd_rules(rd);
2384} 1841}
2385 1842
2386#ifdef CONFIG_CFG80211_REG_DEBUG
2387static 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
2405static 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 */ 1843/* Takes ownership of rd only if it doesn't fail */
2414static int __set_regdom(const struct ieee80211_regdomain *rd) 1844static int __set_regdom(const struct ieee80211_regdomain *rd)
2415{ 1845{
@@ -2521,34 +1951,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2521 return 0; 1951 return 0;
2522 } 1952 }
2523 1953
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) 1954 if (!intersected_rd)
2553 return -EINVAL; 1955 return -EINVAL;
2554 1956
@@ -2688,9 +2090,6 @@ void /* __init_or_exit */ regulatory_exit(void)
2688 2090
2689 reset_regdomains(); 2091 reset_regdomains();
2690 2092
2691 kfree(country_ie_regdomain);
2692 country_ie_regdomain = NULL;
2693
2694 kfree(last_request); 2093 kfree(last_request);
2695 2094
2696 platform_device_unregister(reg_pdev); 2095 platform_device_unregister(reg_pdev);