diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ibss.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c94a695d8488..c236079ed38a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -63,19 +63,18 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
64 | const u8 *bssid, const int beacon_int, | 64 | const u8 *bssid, const int beacon_int, |
65 | struct ieee80211_channel *chan, | 65 | struct ieee80211_channel *chan, |
66 | const size_t supp_rates_len, | 66 | const u32 basic_rates, |
67 | const u8 *supp_rates, | ||
68 | const u16 capability, u64 tsf) | 67 | const u16 capability, u64 tsf) |
69 | { | 68 | { |
70 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 69 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
71 | struct ieee80211_local *local = sdata->local; | 70 | struct ieee80211_local *local = sdata->local; |
72 | int rates, i, j; | 71 | int rates, i; |
73 | struct sk_buff *skb; | 72 | struct sk_buff *skb; |
74 | struct ieee80211_mgmt *mgmt; | 73 | struct ieee80211_mgmt *mgmt; |
75 | u8 *pos; | 74 | u8 *pos; |
76 | struct ieee80211_supported_band *sband; | 75 | struct ieee80211_supported_band *sband; |
77 | u32 bss_change; | 76 | u32 bss_change; |
78 | 77 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | |
79 | 78 | ||
80 | /* Reset own TSF to allow time synchronization work. */ | 79 | /* Reset own TSF to allow time synchronization work. */ |
81 | drv_reset_tsf(local); | 80 | drv_reset_tsf(local); |
@@ -101,6 +100,16 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
101 | 100 | ||
102 | sband = local->hw.wiphy->bands[chan->band]; | 101 | sband = local->hw.wiphy->bands[chan->band]; |
103 | 102 | ||
103 | /* build supported rates array */ | ||
104 | pos = supp_rates; | ||
105 | for (i = 0; i < sband->n_bitrates; i++) { | ||
106 | int rate = sband->bitrates[i].bitrate; | ||
107 | u8 basic = 0; | ||
108 | if (basic_rates & BIT(i)) | ||
109 | basic = 0x80; | ||
110 | *pos++ = basic | (u8) (rate / 5); | ||
111 | } | ||
112 | |||
104 | /* Build IBSS probe response */ | 113 | /* Build IBSS probe response */ |
105 | mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 114 | mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
106 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 115 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
@@ -118,7 +127,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
118 | *pos++ = ifibss->ssid_len; | 127 | *pos++ = ifibss->ssid_len; |
119 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); | 128 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
120 | 129 | ||
121 | rates = supp_rates_len; | 130 | rates = sband->n_bitrates; |
122 | if (rates > 8) | 131 | if (rates > 8) |
123 | rates = 8; | 132 | rates = 8; |
124 | pos = skb_put(skb, 2 + rates); | 133 | pos = skb_put(skb, 2 + rates); |
@@ -140,8 +149,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
140 | *pos++ = 0; | 149 | *pos++ = 0; |
141 | *pos++ = 0; | 150 | *pos++ = 0; |
142 | 151 | ||
143 | if (supp_rates_len > 8) { | 152 | if (sband->n_bitrates > 8) { |
144 | rates = supp_rates_len - 8; | 153 | rates = sband->n_bitrates - 8; |
145 | pos = skb_put(skb, 2 + rates); | 154 | pos = skb_put(skb, 2 + rates); |
146 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 155 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
147 | *pos++ = rates; | 156 | *pos++ = rates; |
@@ -162,15 +171,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
162 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 171 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
163 | ieee80211_bss_info_change_notify(sdata, bss_change); | 172 | ieee80211_bss_info_change_notify(sdata, bss_change); |
164 | 173 | ||
165 | rates = 0; | 174 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); |
166 | for (i = 0; i < supp_rates_len; i++) { | ||
167 | int bitrate = (supp_rates[i] & 0x7f) * 5; | ||
168 | for (j = 0; j < sband->n_bitrates; j++) | ||
169 | if (sband->bitrates[j].bitrate == bitrate) | ||
170 | rates |= BIT(j); | ||
171 | } | ||
172 | |||
173 | ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); | ||
174 | 175 | ||
175 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; | 176 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; |
176 | mod_timer(&ifibss->timer, | 177 | mod_timer(&ifibss->timer, |
@@ -184,15 +185,35 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
184 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 185 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
185 | struct ieee80211_bss *bss) | 186 | struct ieee80211_bss *bss) |
186 | { | 187 | { |
188 | struct ieee80211_supported_band *sband; | ||
189 | u32 basic_rates; | ||
190 | int i, j; | ||
187 | u16 beacon_int = bss->cbss.beacon_interval; | 191 | u16 beacon_int = bss->cbss.beacon_interval; |
188 | 192 | ||
189 | if (beacon_int < 10) | 193 | if (beacon_int < 10) |
190 | beacon_int = 10; | 194 | beacon_int = 10; |
191 | 195 | ||
196 | sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band]; | ||
197 | |||
198 | basic_rates = 0; | ||
199 | |||
200 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
201 | int rate = (bss->supp_rates[i] & 0x7f) * 5; | ||
202 | bool is_basic = !!(bss->supp_rates[i] & 0x80); | ||
203 | |||
204 | for (j = 0; j < sband->n_bitrates; j++) { | ||
205 | if (sband->bitrates[j].bitrate == rate) { | ||
206 | if (is_basic) | ||
207 | basic_rates |= BIT(j); | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
192 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, | 213 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, |
193 | beacon_int, | 214 | beacon_int, |
194 | bss->cbss.channel, | 215 | bss->cbss.channel, |
195 | bss->supp_rates_len, bss->supp_rates, | 216 | basic_rates, |
196 | bss->cbss.capability, | 217 | bss->cbss.capability, |
197 | bss->cbss.tsf); | 218 | bss->cbss.tsf); |
198 | } | 219 | } |
@@ -449,9 +470,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
449 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 470 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
450 | struct ieee80211_local *local = sdata->local; | 471 | struct ieee80211_local *local = sdata->local; |
451 | struct ieee80211_supported_band *sband; | 472 | struct ieee80211_supported_band *sband; |
452 | u8 *pos; | ||
453 | u8 bssid[ETH_ALEN]; | 473 | u8 bssid[ETH_ALEN]; |
454 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | ||
455 | u16 capability; | 474 | u16 capability; |
456 | int i; | 475 | int i; |
457 | 476 | ||
@@ -480,15 +499,9 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
480 | else | 499 | else |
481 | sdata->drop_unencrypted = 0; | 500 | sdata->drop_unencrypted = 0; |
482 | 501 | ||
483 | pos = supp_rates; | ||
484 | for (i = 0; i < sband->n_bitrates; i++) { | ||
485 | int rate = sband->bitrates[i].bitrate; | ||
486 | *pos++ = (u8) (rate / 5); | ||
487 | } | ||
488 | |||
489 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, | 502 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, |
490 | ifibss->channel, sband->n_bitrates, | 503 | ifibss->channel, 3, /* first two are basic */ |
491 | supp_rates, capability, 0); | 504 | capability, 0); |
492 | } | 505 | } |
493 | 506 | ||
494 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | 507 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) |