aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-08-28 12:36:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-09-24 15:54:27 -0400
commit8dcb20038ade81f9a87c024e7f12ec74f0e95f33 (patch)
treefe970ab661be7ec61165bdcb5db2c4422a1822fd
parent29ad2facd47f8e37eab8b156e2c384fa181c8b4a (diff)
mac80211: Filter ProbeReq SuppRates based on TX rate mask
If the TX rate set has been masked, the removed rates can also be removed from the Supported Rates and Extended Supported Rates IEs in Probe Request frames. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/scan.c2
-rw-r--r--net/mac80211/util.c37
3 files changed, 24 insertions, 17 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9346a6b0f400..3641563d90f8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1256,7 +1256,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1256 const u8 *key, u8 key_len, u8 key_idx); 1256 const u8 *key, u8 key_len, u8 key_idx);
1257int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 1257int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1258 const u8 *ie, size_t ie_len, 1258 const u8 *ie, size_t ie_len,
1259 enum ieee80211_band band); 1259 enum ieee80211_band band, u32 rate_mask);
1260void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1260void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1261 const u8 *ssid, size_t ssid_len, 1261 const u8 *ssid, size_t ssid_len,
1262 const u8 *ie, size_t ie_len); 1262 const u8 *ie, size_t ie_len);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index d60389ba9b95..1623e9d2086e 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -242,7 +242,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
242 local->hw_scan_req->n_channels = n_chans; 242 local->hw_scan_req->n_channels = n_chans;
243 243
244 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, 244 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
245 req->ie, req->ie_len, band); 245 req->ie, req->ie_len, band, (u32) -1);
246 local->hw_scan_req->ie_len = ielen; 246 local->hw_scan_req->ie_len = ielen;
247 247
248 return true; 248 return true;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 737f4267c335..bfd19d76667a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -895,26 +895,33 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
895 895
896int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 896int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
897 const u8 *ie, size_t ie_len, 897 const u8 *ie, size_t ie_len,
898 enum ieee80211_band band) 898 enum ieee80211_band band, u32 rate_mask)
899{ 899{
900 struct ieee80211_supported_band *sband; 900 struct ieee80211_supported_band *sband;
901 u8 *pos; 901 u8 *pos;
902 size_t offset = 0, noffset; 902 size_t offset = 0, noffset;
903 int supp_rates_len, i; 903 int supp_rates_len, i;
904 u8 rates[32];
905 int num_rates;
906 int ext_rates_len;
904 907
905 sband = local->hw.wiphy->bands[band]; 908 sband = local->hw.wiphy->bands[band];
906 909
907 pos = buffer; 910 pos = buffer;
908 911
909 supp_rates_len = min_t(int, sband->n_bitrates, 8); 912 num_rates = 0;
913 for (i = 0; i < sband->n_bitrates; i++) {
914 if ((BIT(i) & rate_mask) == 0)
915 continue; /* skip rate */
916 rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5);
917 }
918
919 supp_rates_len = min_t(int, num_rates, 8);
910 920
911 *pos++ = WLAN_EID_SUPP_RATES; 921 *pos++ = WLAN_EID_SUPP_RATES;
912 *pos++ = supp_rates_len; 922 *pos++ = supp_rates_len;
913 923 memcpy(pos, rates, supp_rates_len);
914 for (i = 0; i < supp_rates_len; i++) { 924 pos += supp_rates_len;
915 int rate = sband->bitrates[i].bitrate;
916 *pos++ = (u8) (rate / 5);
917 }
918 925
919 /* insert "request information" if in custom IEs */ 926 /* insert "request information" if in custom IEs */
920 if (ie && ie_len) { 927 if (ie && ie_len) {
@@ -932,14 +939,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
932 offset = noffset; 939 offset = noffset;
933 } 940 }
934 941
935 if (sband->n_bitrates > i) { 942 ext_rates_len = num_rates - supp_rates_len;
943 if (ext_rates_len > 0) {
936 *pos++ = WLAN_EID_EXT_SUPP_RATES; 944 *pos++ = WLAN_EID_EXT_SUPP_RATES;
937 *pos++ = sband->n_bitrates - i; 945 *pos++ = ext_rates_len;
938 946 memcpy(pos, rates + supp_rates_len, ext_rates_len);
939 for (; i < sband->n_bitrates; i++) { 947 pos += ext_rates_len;
940 int rate = sband->bitrates[i].bitrate;
941 *pos++ = (u8) (rate / 5);
942 }
943 } 948 }
944 949
945 /* insert custom IEs that go before HT */ 950 /* insert custom IEs that go before HT */
@@ -1018,7 +1023,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1018 } 1023 }
1019 1024
1020 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, 1025 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
1021 local->hw.conf.channel->band); 1026 local->hw.conf.channel->band,
1027 sdata->rc_rateidx_mask
1028 [local->hw.conf.channel->band]);
1022 1029
1023 skb = ieee80211_probereq_get(&local->hw, &sdata->vif, 1030 skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
1024 ssid, ssid_len, 1031 ssid, ssid_len,