mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-26 02:09:38 +01:00
band: validate channel/freq conversions with E-4
IWD's channel/frequency conversions use simple math to convert and have very minimal checks to ensure the input is valid. This can lead to some channels/frequencies being calculated which are not in IWD's E-4 table, specifically in the 5GHz band. This is especially noticable using mac80211_hwsim which includes some obscure high 5ghz frequencies which are not part of the 802.11 spec. To fix this calculate the frequency or channel then iterate E-4 operating classes to check that the value actually matches a class.
This commit is contained in:
parent
cfdfe9c54c
commit
553052a337
79
src/band.c
79
src/band.c
@ -1283,6 +1283,8 @@ int band_freq_to_ht_chandef(uint32_t freq, const struct band_freq_attrs *attr,
|
|||||||
|
|
||||||
uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
||||||
{
|
{
|
||||||
|
unsigned int i;
|
||||||
|
enum band_freq band = 0;
|
||||||
uint32_t channel = 0;
|
uint32_t channel = 0;
|
||||||
|
|
||||||
if (freq >= 2412 && freq <= 2484) {
|
if (freq >= 2412 && freq <= 2484) {
|
||||||
@ -1297,10 +1299,8 @@ uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
|||||||
channel /= 5;
|
channel /= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_band)
|
band = BAND_FREQ_2_4_GHZ;
|
||||||
*out_band = BAND_FREQ_2_4_GHZ;
|
goto check_e4;
|
||||||
|
|
||||||
return channel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freq >= 5005 && freq < 5900) {
|
if (freq >= 5005 && freq < 5900) {
|
||||||
@ -1309,10 +1309,9 @@ uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
|||||||
|
|
||||||
channel = (freq - 5000) / 5;
|
channel = (freq - 5000) / 5;
|
||||||
|
|
||||||
if (out_band)
|
band = BAND_FREQ_5_GHZ;
|
||||||
*out_band = BAND_FREQ_5_GHZ;
|
|
||||||
|
|
||||||
return channel;
|
goto check_e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freq >= 4905 && freq < 5000) {
|
if (freq >= 4905 && freq < 5000) {
|
||||||
@ -1321,10 +1320,9 @@ uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
|||||||
|
|
||||||
channel = (freq - 4000) / 5;
|
channel = (freq - 4000) / 5;
|
||||||
|
|
||||||
if (out_band)
|
band = BAND_FREQ_5_GHZ;
|
||||||
*out_band = BAND_FREQ_5_GHZ;
|
|
||||||
|
|
||||||
return channel;
|
goto check_e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freq > 5950 && freq <= 7115) {
|
if (freq > 5950 && freq <= 7115) {
|
||||||
@ -1333,17 +1331,31 @@ uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
|||||||
|
|
||||||
channel = (freq - 5950) / 5;
|
channel = (freq - 5950) / 5;
|
||||||
|
|
||||||
if (out_band)
|
band = BAND_FREQ_6_GHZ;
|
||||||
*out_band = BAND_FREQ_6_GHZ;
|
|
||||||
|
|
||||||
return channel;
|
goto check_e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freq == 5935) {
|
if (freq == 5935) {
|
||||||
if (out_band)
|
band = BAND_FREQ_6_GHZ;
|
||||||
*out_band = BAND_FREQ_6_GHZ;
|
channel = 2;
|
||||||
|
}
|
||||||
|
|
||||||
return 2;
|
if (!band || !channel)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
check_e4:
|
||||||
|
for (i = 0; i < L_ARRAY_SIZE(e4_operating_classes); i++) {
|
||||||
|
const struct operating_class_info *info =
|
||||||
|
&e4_operating_classes[i];
|
||||||
|
|
||||||
|
if (e4_has_frequency(info, freq) == 0 ||
|
||||||
|
e4_has_ccfi(info, freq) == 0) {
|
||||||
|
if (out_band)
|
||||||
|
*out_band = band;
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1351,26 +1363,33 @@ uint8_t band_freq_to_channel(uint32_t freq, enum band_freq *out_band)
|
|||||||
|
|
||||||
uint32_t band_channel_to_freq(uint8_t channel, enum band_freq band)
|
uint32_t band_channel_to_freq(uint8_t channel, enum band_freq band)
|
||||||
{
|
{
|
||||||
|
unsigned int i;
|
||||||
|
uint32_t freq = 0;
|
||||||
|
|
||||||
if (band == BAND_FREQ_2_4_GHZ) {
|
if (band == BAND_FREQ_2_4_GHZ) {
|
||||||
if (channel >= 1 && channel <= 13)
|
if (channel >= 1 && channel <= 13)
|
||||||
return 2407 + 5 * channel;
|
freq = 2407 + 5 * channel;
|
||||||
|
else if (channel == 14)
|
||||||
|
freq = 2484;
|
||||||
|
|
||||||
if (channel == 14)
|
goto check_e4;
|
||||||
return 2484;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (band == BAND_FREQ_5_GHZ) {
|
if (band == BAND_FREQ_5_GHZ) {
|
||||||
if (channel >= 1 && channel <= 179)
|
if (channel >= 1 && channel <= 179)
|
||||||
return 5000 + 5 * channel;
|
freq = 5000 + 5 * channel;
|
||||||
|
else if (channel >= 181 && channel <= 199)
|
||||||
|
freq = 4000 + 5 * channel;
|
||||||
|
|
||||||
if (channel >= 181 && channel <= 199)
|
goto check_e4;
|
||||||
return 4000 + 5 * channel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (band == BAND_FREQ_6_GHZ) {
|
if (band == BAND_FREQ_6_GHZ) {
|
||||||
/* operating class 136 */
|
/* operating class 136 */
|
||||||
if (channel == 2)
|
if (channel == 2) {
|
||||||
return 5935;
|
freq = 5935;
|
||||||
|
goto check_e4;
|
||||||
|
}
|
||||||
|
|
||||||
/* Channels increment by 4, starting with 1 */
|
/* Channels increment by 4, starting with 1 */
|
||||||
if (channel % 4 != 1)
|
if (channel % 4 != 1)
|
||||||
@ -1380,7 +1399,17 @@ uint32_t band_channel_to_freq(uint8_t channel, enum band_freq band)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* operating classes 131, 132, 133, 134, 135 */
|
/* operating classes 131, 132, 133, 134, 135 */
|
||||||
return 5950 + 5 * channel;
|
freq = 5950 + 5 * channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_e4:
|
||||||
|
for (i = 0; i < L_ARRAY_SIZE(e4_operating_classes); i++) {
|
||||||
|
const struct operating_class_info *info =
|
||||||
|
&e4_operating_classes[i];
|
||||||
|
|
||||||
|
if (e4_has_frequency(info, freq) == 0 ||
|
||||||
|
e4_has_ccfi(info, freq) == 0)
|
||||||
|
return freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user