diff options
author | Arik Nemtsov <arik@wizery.com> | 2014-07-17 18:14:20 +0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-07-21 14:14:03 +0400 |
commit | f09a87d274942bf619f5081ac6e9e9441f3eabc4 (patch) | |
tree | 8a915219ece5b1beb37d25fb399aa45e2a7acd00 | |
parent | 46792a2dfcc7e000e6927088fbf06a135aaaa3eb (diff) | |
download | linux-f09a87d274942bf619f5081ac6e9e9441f3eabc4.tar.xz |
mac80211: split extra TDLS IEs in setup frames
When building TDLS setup frames, use the IE order mandates in the
specification, splitting extra IEs coming from usermode.
Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/tdls.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index b61448acc438..8d6c9285752f 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -78,25 +78,91 @@ static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, memcpy(lnkid->resp_sta, peer, ETH_ALEN); } +static void +ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, const u8 *peer, + u8 action_code, const u8 *extra_ies, + size_t extra_ies_len) +{ + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + size_t offset = 0, noffset; + u8 *pos; + + ieee80211_add_srates_ie(sdata, skb, false, band); + ieee80211_add_ext_srates_ie(sdata, skb, false, band); + + /* add any custom IEs that go before Extended Capabilities */ + if (extra_ies_len) { + static const u8 before_ext_cap[] = { + WLAN_EID_SUPP_RATES, + WLAN_EID_COUNTRY, + WLAN_EID_EXT_SUPP_RATES, + WLAN_EID_SUPPORTED_CHANNELS, + WLAN_EID_RSN, + }; + noffset = ieee80211_ie_split(extra_ies, extra_ies_len, + before_ext_cap, + ARRAY_SIZE(before_ext_cap), + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, extra_ies + offset, noffset - offset); + offset = noffset; + } + + ieee80211_tdls_add_ext_capab(skb); + + /* add any custom IEs that go before HT capabilities */ + if (extra_ies_len) { + static const u8 before_ht_cap[] = { + WLAN_EID_SUPP_RATES, + WLAN_EID_COUNTRY, + WLAN_EID_EXT_SUPP_RATES, + WLAN_EID_SUPPORTED_CHANNELS, + WLAN_EID_RSN, + WLAN_EID_EXT_CAPABILITY, + WLAN_EID_QOS_CAPA, + WLAN_EID_FAST_BSS_TRANSITION, + WLAN_EID_TIMEOUT_INTERVAL, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES, + }; + noffset = ieee80211_ie_split(extra_ies, extra_ies_len, + before_ht_cap, + ARRAY_SIZE(before_ht_cap), + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, extra_ies + offset, noffset - offset); + offset = noffset; + } + + /* add any remaining IEs */ + if (extra_ies_len) { + noffset = extra_ies_len; + pos = skb_put(skb, noffset - offset); + memcpy(pos, extra_ies + offset, noffset - offset); + } +} + static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, const u8 *peer, u8 action_code, bool initiator, const u8 *extra_ies, size_t extra_ies_len) { const u8 *init_addr, *rsp_addr; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); switch (action_code) { case WLAN_TDLS_SETUP_REQUEST: case WLAN_TDLS_SETUP_RESPONSE: case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - ieee80211_add_srates_ie(sdata, skb, false, band); - ieee80211_add_ext_srates_ie(sdata, skb, false, band); - ieee80211_tdls_add_ext_capab(skb); + ieee80211_tdls_add_setup_start_ies(sdata, skb, peer, + action_code, extra_ies, + extra_ies_len); break; case WLAN_TDLS_SETUP_CONFIRM: case WLAN_TDLS_TEARDOWN: case WLAN_TDLS_DISCOVERY_REQUEST: + if (extra_ies_len) + memcpy(skb_put(skb, extra_ies_len), extra_ies, + extra_ies_len); break; } @@ -108,9 +174,6 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata, rsp_addr = sdata->vif.addr; } - if (extra_ies_len) - memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); - ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr, sdata->u.mgd.bssid); } |