aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-10-27 07:03:19 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-11-04 07:18:21 -0500
commit8ed2874715c17f27bb7b9bacbcfa41bc88a64476 (patch)
treec284ccc7f2fc1e420ffa2d9a1949adf5f43e182a /net
parent239281f803e2efdb77d906ef296086b6917e5d71 (diff)
mac80211: handle RIC data element in reassociation request
When the RIC data element (RDE) is included in the IEs coming from userspace for an association request, its handling is currently broken as any IEs that are contained within it would be split off from it and inserted again after all the IEs that mac80211 generates (e.g. HT, VHT.) To fix this, treat the RIC element specially, and stop after it only when we find something that doesn't actually belong to it. This assumes userspace is actually correctly building it, directly after the fast BSS transition IE and before all the others like extended capabilities. This leaves as a potential problem the case where userspace is building the following IEs: [RDE] [vendor resource description] [vendor non-resource IE] In this case, we'd erroneously consider all three IEs to be part of the RIC data together, and not split them between the two vendor IEs. Unfortunately, it isn't easily possible to distinguish vendor IEs, so this isn't easy to fix. Luckily, this case is rare as normally wpa_supplicant will include an extended capabilities IE in the IEs, and that certainly will break the two vendor IEs apart correctly. Reviewed-by: Eliad Peller <eliad@wizery.com> Reviewed-by: Beni Lev <beni.lev@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/mlme.c27
-rw-r--r--net/mac80211/util.c26
3 files changed, 50 insertions, 7 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fbd6bee9c959..a51c993ece73 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1903,6 +1903,10 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
1903void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); 1903void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
1904void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata); 1904void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
1905 1905
1906size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
1907 const u8 *ids, int n_ids,
1908 const u8 *after_ric, int n_after_ric,
1909 size_t offset);
1906size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); 1910size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
1907u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1911u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1908 u16 cap); 1912 u16 cap);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c078cd344ca4..213a420704a6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -775,11 +775,30 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
775 WLAN_EID_QOS_CAPA, 775 WLAN_EID_QOS_CAPA,
776 WLAN_EID_RRM_ENABLED_CAPABILITIES, 776 WLAN_EID_RRM_ENABLED_CAPABILITIES,
777 WLAN_EID_MOBILITY_DOMAIN, 777 WLAN_EID_MOBILITY_DOMAIN,
778 WLAN_EID_FAST_BSS_TRANSITION, /* reassoc only */
779 WLAN_EID_RIC_DATA, /* reassoc only */
778 WLAN_EID_SUPPORTED_REGULATORY_CLASSES, 780 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
779 }; 781 };
780 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, 782 static const u8 after_ric[] = {
781 before_ht, ARRAY_SIZE(before_ht), 783 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
782 offset); 784 WLAN_EID_HT_CAPABILITY,
785 WLAN_EID_BSS_COEX_2040,
786 WLAN_EID_EXT_CAPABILITY,
787 WLAN_EID_QOS_TRAFFIC_CAPA,
788 WLAN_EID_TIM_BCAST_REQ,
789 WLAN_EID_INTERWORKING,
790 /* 60GHz doesn't happen right now */
791 WLAN_EID_VHT_CAPABILITY,
792 WLAN_EID_OPMODE_NOTIF,
793 };
794
795 noffset = ieee80211_ie_split_ric(assoc_data->ie,
796 assoc_data->ie_len,
797 before_ht,
798 ARRAY_SIZE(before_ht),
799 after_ric,
800 ARRAY_SIZE(after_ric),
801 offset);
783 pos = skb_put(skb, noffset - offset); 802 pos = skb_put(skb, noffset - offset);
784 memcpy(pos, assoc_data->ie + offset, noffset - offset); 803 memcpy(pos, assoc_data->ie + offset, noffset - offset);
785 offset = noffset; 804 offset = noffset;
@@ -813,6 +832,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
813 WLAN_EID_TIM_BCAST_REQ, 832 WLAN_EID_TIM_BCAST_REQ,
814 WLAN_EID_INTERWORKING, 833 WLAN_EID_INTERWORKING,
815 }; 834 };
835
836 /* RIC already taken above, so no need to handle here anymore */
816 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, 837 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
817 before_vht, ARRAY_SIZE(before_vht), 838 before_vht, ARRAY_SIZE(before_vht),
818 offset); 839 offset);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 91e16b4d4e3c..5f7b0e935b65 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2101,16 +2101,34 @@ static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
2101 return false; 2101 return false;
2102} 2102}
2103 2103
2104size_t ieee80211_ie_split(const u8 *ies, size_t ielen, 2104size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
2105 const u8 *ids, int n_ids, size_t offset) 2105 const u8 *ids, int n_ids,
2106 const u8 *after_ric, int n_after_ric,
2107 size_t offset)
2106{ 2108{
2107 size_t pos = offset; 2109 size_t pos = offset;
2108 2110
2109 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) 2111 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
2110 pos += 2 + ies[pos + 1]; 2112 if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
2113 pos += 2 + ies[pos + 1];
2114
2115 while (pos < ielen &&
2116 !ieee80211_id_in_list(after_ric, n_after_ric,
2117 ies[pos]))
2118 pos += 2 + ies[pos + 1];
2119 } else {
2120 pos += 2 + ies[pos + 1];
2121 }
2122 }
2111 2123
2112 return pos; 2124 return pos;
2113} 2125}
2126
2127size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
2128 const u8 *ids, int n_ids, size_t offset)
2129{
2130 return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
2131}
2114EXPORT_SYMBOL(ieee80211_ie_split); 2132EXPORT_SYMBOL(ieee80211_ie_split);
2115 2133
2116size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) 2134size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)