diff options
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r-- | net/wireless/scan.c | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d36c3eb7b931..d0e7472dd9fd 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -1058,13 +1058,23 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, | |||
1058 | return NULL; | 1058 | return NULL; |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | /* | ||
1062 | * Update RX channel information based on the available frame payload | ||
1063 | * information. This is mainly for the 2.4 GHz band where frames can be received | ||
1064 | * from neighboring channels and the Beacon frames use the DSSS Parameter Set | ||
1065 | * element to indicate the current (transmitting) channel, but this might also | ||
1066 | * be needed on other bands if RX frequency does not match with the actual | ||
1067 | * operating channel of a BSS. | ||
1068 | */ | ||
1061 | static struct ieee80211_channel * | 1069 | static struct ieee80211_channel * |
1062 | cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | 1070 | cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, |
1063 | struct ieee80211_channel *channel) | 1071 | struct ieee80211_channel *channel, |
1072 | enum nl80211_bss_scan_width scan_width) | ||
1064 | { | 1073 | { |
1065 | const u8 *tmp; | 1074 | const u8 *tmp; |
1066 | u32 freq; | 1075 | u32 freq; |
1067 | int channel_number = -1; | 1076 | int channel_number = -1; |
1077 | struct ieee80211_channel *alt_channel; | ||
1068 | 1078 | ||
1069 | tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen); | 1079 | tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen); |
1070 | if (tmp && tmp[1] == 1) { | 1080 | if (tmp && tmp[1] == 1) { |
@@ -1078,16 +1088,45 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | |||
1078 | } | 1088 | } |
1079 | } | 1089 | } |
1080 | 1090 | ||
1081 | if (channel_number < 0) | 1091 | if (channel_number < 0) { |
1092 | /* No channel information in frame payload */ | ||
1082 | return channel; | 1093 | return channel; |
1094 | } | ||
1083 | 1095 | ||
1084 | freq = ieee80211_channel_to_frequency(channel_number, channel->band); | 1096 | freq = ieee80211_channel_to_frequency(channel_number, channel->band); |
1085 | channel = ieee80211_get_channel(wiphy, freq); | 1097 | alt_channel = ieee80211_get_channel(wiphy, freq); |
1086 | if (!channel) | 1098 | if (!alt_channel) { |
1087 | return NULL; | 1099 | if (channel->band == NL80211_BAND_2GHZ) { |
1088 | if (channel->flags & IEEE80211_CHAN_DISABLED) | 1100 | /* |
1101 | * Better not allow unexpected channels when that could | ||
1102 | * be going beyond the 1-11 range (e.g., discovering | ||
1103 | * BSS on channel 12 when radio is configured for | ||
1104 | * channel 11. | ||
1105 | */ | ||
1106 | return NULL; | ||
1107 | } | ||
1108 | |||
1109 | /* No match for the payload channel number - ignore it */ | ||
1110 | return channel; | ||
1111 | } | ||
1112 | |||
1113 | if (scan_width == NL80211_BSS_CHAN_WIDTH_10 || | ||
1114 | scan_width == NL80211_BSS_CHAN_WIDTH_5) { | ||
1115 | /* | ||
1116 | * Ignore channel number in 5 and 10 MHz channels where there | ||
1117 | * may not be an n:1 or 1:n mapping between frequencies and | ||
1118 | * channel numbers. | ||
1119 | */ | ||
1120 | return channel; | ||
1121 | } | ||
1122 | |||
1123 | /* | ||
1124 | * Use the channel determined through the payload channel number | ||
1125 | * instead of the RX channel reported by the driver. | ||
1126 | */ | ||
1127 | if (alt_channel->flags & IEEE80211_CHAN_DISABLED) | ||
1089 | return NULL; | 1128 | return NULL; |
1090 | return channel; | 1129 | return alt_channel; |
1091 | } | 1130 | } |
1092 | 1131 | ||
1093 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 1132 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
@@ -1112,7 +1151,8 @@ cfg80211_inform_bss_data(struct wiphy *wiphy, | |||
1112 | (data->signal < 0 || data->signal > 100))) | 1151 | (data->signal < 0 || data->signal > 100))) |
1113 | return NULL; | 1152 | return NULL; |
1114 | 1153 | ||
1115 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan); | 1154 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan, |
1155 | data->scan_width); | ||
1116 | if (!channel) | 1156 | if (!channel) |
1117 | return NULL; | 1157 | return NULL; |
1118 | 1158 | ||
@@ -1210,7 +1250,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, | |||
1210 | return NULL; | 1250 | return NULL; |
1211 | 1251 | ||
1212 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, | 1252 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, |
1213 | ielen, data->chan); | 1253 | ielen, data->chan, data->scan_width); |
1214 | if (!channel) | 1254 | if (!channel) |
1215 | return NULL; | 1255 | return NULL; |
1216 | 1256 | ||