aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c74
1 files changed, 54 insertions, 20 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index f3b77f7b8e3d..5f8071de7950 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -485,6 +485,34 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
485} 485}
486 486
487/* 487/*
488 * This is a work around for sanity checking ieee80211_channel_to_frequency()'s
489 * work. ieee80211_channel_to_frequency() can for example currently provide a
490 * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be
491 * an AP providing channel 8 on a country IE triplet when it sent this on the
492 * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz
493 * channel.
494 *
495 * This can be removed once ieee80211_channel_to_frequency() takes in a band.
496 */
497static bool chan_in_band(int chan, enum ieee80211_band band)
498{
499 int center_freq = ieee80211_channel_to_frequency(chan);
500
501 switch (band) {
502 case IEEE80211_BAND_2GHZ:
503 if (center_freq <= 2484)
504 return true;
505 return false;
506 case IEEE80211_BAND_5GHZ:
507 if (center_freq >= 5005)
508 return true;
509 return false;
510 default:
511 return false;
512 }
513}
514
515/*
488 * Some APs may send a country IE triplet for each channel they 516 * Some APs may send a country IE triplet for each channel they
489 * support and while this is completely overkill and silly we still 517 * support and while this is completely overkill and silly we still
490 * need to support it. We avoid making a single rule for each channel 518 * need to support it. We avoid making a single rule for each channel
@@ -532,7 +560,8 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
532 * Returns 0 if the IE has been found to be invalid in the middle 560 * Returns 0 if the IE has been found to be invalid in the middle
533 * somewhere. 561 * somewhere.
534 */ 562 */
535static int max_subband_chan(int orig_cur_chan, 563static int max_subband_chan(enum ieee80211_band band,
564 int orig_cur_chan,
536 int orig_end_channel, 565 int orig_end_channel,
537 s8 orig_max_power, 566 s8 orig_max_power,
538 u8 **country_ie, 567 u8 **country_ie,
@@ -541,7 +570,6 @@ static int max_subband_chan(int orig_cur_chan,
541 u8 *triplets_start = *country_ie; 570 u8 *triplets_start = *country_ie;
542 u8 len_at_triplet = *country_ie_len; 571 u8 len_at_triplet = *country_ie_len;
543 int end_subband_chan = orig_end_channel; 572 int end_subband_chan = orig_end_channel;
544 enum ieee80211_band band;
545 573
546 /* 574 /*
547 * We'll deal with padding for the caller unless 575 * We'll deal with padding for the caller unless
@@ -557,17 +585,14 @@ static int max_subband_chan(int orig_cur_chan,
557 *country_ie += 3; 585 *country_ie += 3;
558 *country_ie_len -= 3; 586 *country_ie_len -= 3;
559 587
560 if (orig_cur_chan <= 14) 588 if (!chan_in_band(orig_cur_chan, band))
561 band = IEEE80211_BAND_2GHZ; 589 return 0;
562 else
563 band = IEEE80211_BAND_5GHZ;
564 590
565 while (*country_ie_len >= 3) { 591 while (*country_ie_len >= 3) {
566 int end_channel = 0; 592 int end_channel = 0;
567 struct ieee80211_country_ie_triplet *triplet = 593 struct ieee80211_country_ie_triplet *triplet =
568 (struct ieee80211_country_ie_triplet *) *country_ie; 594 (struct ieee80211_country_ie_triplet *) *country_ie;
569 int cur_channel = 0, next_expected_chan; 595 int cur_channel = 0, next_expected_chan;
570 enum ieee80211_band next_band = IEEE80211_BAND_2GHZ;
571 596
572 /* means last triplet is completely unrelated to this one */ 597 /* means last triplet is completely unrelated to this one */
573 if (triplet->ext.reg_extension_id >= 598 if (triplet->ext.reg_extension_id >=
@@ -592,6 +617,9 @@ static int max_subband_chan(int orig_cur_chan,
592 if (triplet->chans.first_channel <= end_subband_chan) 617 if (triplet->chans.first_channel <= end_subband_chan)
593 return 0; 618 return 0;
594 619
620 if (!chan_in_band(triplet->chans.first_channel, band))
621 return 0;
622
595 /* 2 GHz */ 623 /* 2 GHz */
596 if (triplet->chans.first_channel <= 14) { 624 if (triplet->chans.first_channel <= 14) {
597 end_channel = triplet->chans.first_channel + 625 end_channel = triplet->chans.first_channel +
@@ -600,14 +628,10 @@ static int max_subband_chan(int orig_cur_chan,
600 else { 628 else {
601 end_channel = triplet->chans.first_channel + 629 end_channel = triplet->chans.first_channel +
602 (4 * (triplet->chans.num_channels - 1)); 630 (4 * (triplet->chans.num_channels - 1));
603 next_band = IEEE80211_BAND_5GHZ;
604 } 631 }
605 632
606 if (band != next_band) { 633 if (!chan_in_band(end_channel, band))
607 *country_ie -= 3; 634 return 0;
608 *country_ie_len += 3;
609 break;
610 }
611 635
612 if (orig_max_power != triplet->chans.max_power) { 636 if (orig_max_power != triplet->chans.max_power) {
613 *country_ie -= 3; 637 *country_ie -= 3;
@@ -666,6 +690,7 @@ static int max_subband_chan(int orig_cur_chan,
666 * with our userspace regulatory agent to get lower bounds. 690 * with our userspace regulatory agent to get lower bounds.
667 */ 691 */
668static struct ieee80211_regdomain *country_ie_2_rd( 692static struct ieee80211_regdomain *country_ie_2_rd(
693 enum ieee80211_band band,
669 u8 *country_ie, 694 u8 *country_ie,
670 u8 country_ie_len, 695 u8 country_ie_len,
671 u32 *checksum) 696 u32 *checksum)
@@ -743,8 +768,11 @@ static struct ieee80211_regdomain *country_ie_2_rd(
743 if (triplet->chans.num_channels == 0) 768 if (triplet->chans.num_channels == 0)
744 return NULL; 769 return NULL;
745 770
771 if (!chan_in_band(triplet->chans.first_channel, band))
772 return NULL;
773
746 /* 2 GHz */ 774 /* 2 GHz */
747 if (triplet->chans.first_channel <= 14) 775 if (band == IEEE80211_BAND_2GHZ)
748 end_channel = triplet->chans.first_channel + 776 end_channel = triplet->chans.first_channel +
749 triplet->chans.num_channels - 1; 777 triplet->chans.num_channels - 1;
750 else 778 else
@@ -767,7 +795,8 @@ static struct ieee80211_regdomain *country_ie_2_rd(
767 * or for whatever reason sends triplets with multiple channels 795 * or for whatever reason sends triplets with multiple channels
768 * separated when in fact they should be together. 796 * separated when in fact they should be together.
769 */ 797 */
770 end_channel = max_subband_chan(cur_channel, 798 end_channel = max_subband_chan(band,
799 cur_channel,
771 end_channel, 800 end_channel,
772 triplet->chans.max_power, 801 triplet->chans.max_power,
773 &country_ie, 802 &country_ie,
@@ -775,6 +804,9 @@ static struct ieee80211_regdomain *country_ie_2_rd(
775 if (!end_channel) 804 if (!end_channel)
776 return NULL; 805 return NULL;
777 806
807 if (!chan_in_band(end_channel, band))
808 return NULL;
809
778 cur_sub_max_channel = end_channel; 810 cur_sub_max_channel = end_channel;
779 811
780 /* Basic sanity check */ 812 /* Basic sanity check */
@@ -867,14 +899,15 @@ static struct ieee80211_regdomain *country_ie_2_rd(
867 reg_rule->flags = flags; 899 reg_rule->flags = flags;
868 900
869 /* 2 GHz */ 901 /* 2 GHz */
870 if (triplet->chans.first_channel <= 14) 902 if (band == IEEE80211_BAND_2GHZ)
871 end_channel = triplet->chans.first_channel + 903 end_channel = triplet->chans.first_channel +
872 triplet->chans.num_channels -1; 904 triplet->chans.num_channels -1;
873 else 905 else
874 end_channel = triplet->chans.first_channel + 906 end_channel = triplet->chans.first_channel +
875 (4 * (triplet->chans.num_channels - 1)); 907 (4 * (triplet->chans.num_channels - 1));
876 908
877 end_channel = max_subband_chan(triplet->chans.first_channel, 909 end_channel = max_subband_chan(band,
910 triplet->chans.first_channel,
878 end_channel, 911 end_channel,
879 triplet->chans.max_power, 912 triplet->chans.max_power,
880 &country_ie, 913 &country_ie,
@@ -1981,8 +2014,9 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
1981 * therefore cannot iterate over the rdev list here. 2014 * therefore cannot iterate over the rdev list here.
1982 */ 2015 */
1983void regulatory_hint_11d(struct wiphy *wiphy, 2016void regulatory_hint_11d(struct wiphy *wiphy,
1984 u8 *country_ie, 2017 enum ieee80211_band band,
1985 u8 country_ie_len) 2018 u8 *country_ie,
2019 u8 country_ie_len)
1986{ 2020{
1987 struct ieee80211_regdomain *rd = NULL; 2021 struct ieee80211_regdomain *rd = NULL;
1988 char alpha2[2]; 2022 char alpha2[2];
@@ -2028,7 +2062,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
2028 wiphy_idx_valid(last_request->wiphy_idx))) 2062 wiphy_idx_valid(last_request->wiphy_idx)))
2029 goto out; 2063 goto out;
2030 2064
2031 rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); 2065 rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum);
2032 if (!rd) { 2066 if (!rd) {
2033 REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n"); 2067 REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n");
2034 goto out; 2068 goto out;