diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-12-23 07:15:38 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-12-28 16:54:58 -0500 |
commit | 8e664fb3fd2b04e3ac5fad7f046000ba54e0e275 (patch) | |
tree | cf811ffed7d7643b72608a5eebd25baffd57fcb3 /net/mac80211/work.c | |
parent | 77c8144ad3ee7fae834e13cb7e83f5b7c8c5329e (diff) |
mac80211: split up and insert custom IEs correctly
Currently, we insert all user-specified IEs before the HT
IE for association, and after the HT IE for probe requests.
For association, that's correct only if the user-specified
IEs are RSN only, incorrect in all other cases including
WPA. Change this to split apart the user-specified IEs in
two places for association: before the HT IE (e.g. RSN),
after the HT IE (generally empty right now I think?) and
after WMM (all other vendor-specific IEs). For probes,
split the IEs in different places to be correct according
to the spec.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r-- | net/mac80211/work.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index c03c22d5bca3..affdd10b67ad 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -204,6 +204,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
204 | struct ieee80211_mgmt *mgmt; | 204 | struct ieee80211_mgmt *mgmt; |
205 | u8 *pos; | 205 | u8 *pos; |
206 | const u8 *ies; | 206 | const u8 *ies; |
207 | size_t offset = 0, noffset; | ||
207 | int i, len, count, rates_len, supp_rates_len; | 208 | int i, len, count, rates_len, supp_rates_len; |
208 | u16 capab; | 209 | u16 capab; |
209 | struct ieee80211_supported_band *sband; | 210 | struct ieee80211_supported_band *sband; |
@@ -337,14 +338,26 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
337 | } | 338 | } |
338 | } | 339 | } |
339 | 340 | ||
340 | /* | 341 | /* if present, add any custom IEs that go before HT */ |
341 | * XXX: These IEs could contain (vendor-specified) | ||
342 | * IEs that belong after HT -- the buffer may | ||
343 | * need to be split up. | ||
344 | */ | ||
345 | if (wk->ie_len && wk->ie) { | 342 | if (wk->ie_len && wk->ie) { |
346 | pos = skb_put(skb, wk->ie_len); | 343 | static const u8 before_ht[] = { |
347 | memcpy(pos, wk->ie, wk->ie_len); | 344 | WLAN_EID_SSID, |
345 | WLAN_EID_SUPP_RATES, | ||
346 | WLAN_EID_EXT_SUPP_RATES, | ||
347 | WLAN_EID_PWR_CAPABILITY, | ||
348 | WLAN_EID_SUPPORTED_CHANNELS, | ||
349 | WLAN_EID_RSN, | ||
350 | WLAN_EID_QOS_CAPA, | ||
351 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
352 | WLAN_EID_MOBILITY_DOMAIN, | ||
353 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
354 | }; | ||
355 | noffset = ieee80211_ie_split(wk->ie, wk->ie_len, | ||
356 | before_ht, ARRAY_SIZE(before_ht), | ||
357 | offset); | ||
358 | pos = skb_put(skb, noffset - offset); | ||
359 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
360 | offset = noffset; | ||
348 | } | 361 | } |
349 | 362 | ||
350 | if (wk->assoc.use_11n && wk->assoc.wmm_used && | 363 | if (wk->assoc.use_11n && wk->assoc.wmm_used && |
@@ -352,6 +365,15 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
352 | ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, | 365 | ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, |
353 | sband, wk->chan, wk->assoc.smps); | 366 | sband, wk->chan, wk->assoc.smps); |
354 | 367 | ||
368 | /* if present, add any custom non-vendor IEs that go after HT */ | ||
369 | if (wk->ie_len && wk->ie) { | ||
370 | noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len, | ||
371 | offset); | ||
372 | pos = skb_put(skb, noffset - offset); | ||
373 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
374 | offset = noffset; | ||
375 | } | ||
376 | |||
355 | if (wk->assoc.wmm_used && local->hw.queues >= 4) { | 377 | if (wk->assoc.wmm_used && local->hw.queues >= 4) { |
356 | pos = skb_put(skb, 9); | 378 | pos = skb_put(skb, 9); |
357 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | 379 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; |
@@ -365,6 +387,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
365 | *pos++ = 0; | 387 | *pos++ = 0; |
366 | } | 388 | } |
367 | 389 | ||
390 | /* add any remaining custom (i.e. vendor specific here) IEs */ | ||
391 | if (wk->ie_len && wk->ie) { | ||
392 | noffset = wk->ie_len; | ||
393 | pos = skb_put(skb, noffset - offset); | ||
394 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
395 | } | ||
396 | |||
368 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 397 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
369 | ieee80211_tx_skb(sdata, skb); | 398 | ieee80211_tx_skb(sdata, skb); |
370 | } | 399 | } |