diff options
author | Sara Sharon <sara.sharon@intel.com> | 2019-03-15 11:39:06 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2019-04-26 07:02:11 -0400 |
commit | 5023b14cf4df4d22e1a80738167f3438c9e62e5f (patch) | |
tree | 11ceff2719773e48952818ba9c393cdd186a8220 /net/mac80211/util.c | |
parent | fe806e4992c9047affd263bcc13b2c047029a726 (diff) |
mac80211: support profile split between elements
Since an element is limited to 255 octets, a profile may be split
split to several elements. Support the split as defined in the 11ax
draft 3.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 08197afdb7b3..99dd58454592 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1254,15 +1254,18 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
1254 | return crc; | 1254 | return crc; |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | static void ieee802_11_find_bssid_profile(const u8 *start, size_t len, | 1257 | static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, |
1258 | struct ieee802_11_elems *elems, | 1258 | struct ieee802_11_elems *elems, |
1259 | u8 *transmitter_bssid, | 1259 | u8 *transmitter_bssid, |
1260 | u8 *bss_bssid) | 1260 | u8 *bss_bssid, |
1261 | u8 **nontransmitted_profile) | ||
1261 | { | 1262 | { |
1262 | const struct element *elem, *sub; | 1263 | const struct element *elem, *sub; |
1264 | size_t profile_len = 0; | ||
1265 | bool found = false; | ||
1263 | 1266 | ||
1264 | if (!bss_bssid || !transmitter_bssid) | 1267 | if (!bss_bssid || !transmitter_bssid) |
1265 | return; | 1268 | return profile_len; |
1266 | 1269 | ||
1267 | for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) { | 1270 | for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) { |
1268 | if (elem->datalen < 2) | 1271 | if (elem->datalen < 2) |
@@ -1287,9 +1290,17 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len, | |||
1287 | continue; | 1290 | continue; |
1288 | } | 1291 | } |
1289 | 1292 | ||
1293 | memset(*nontransmitted_profile, 0, len); | ||
1294 | profile_len = cfg80211_merge_profile(start, len, | ||
1295 | elem, | ||
1296 | sub, | ||
1297 | nontransmitted_profile, | ||
1298 | len); | ||
1299 | |||
1290 | /* found a Nontransmitted BSSID Profile */ | 1300 | /* found a Nontransmitted BSSID Profile */ |
1291 | index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, | 1301 | index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, |
1292 | sub->data, sub->datalen); | 1302 | *nontransmitted_profile, |
1303 | profile_len); | ||
1293 | if (!index || index[1] < 1 || index[2] == 0) { | 1304 | if (!index || index[1] < 1 || index[2] == 0) { |
1294 | /* Invalid MBSSID Index element */ | 1305 | /* Invalid MBSSID Index element */ |
1295 | continue; | 1306 | continue; |
@@ -1300,14 +1311,15 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len, | |||
1300 | index[2], | 1311 | index[2], |
1301 | new_bssid); | 1312 | new_bssid); |
1302 | if (ether_addr_equal(new_bssid, bss_bssid)) { | 1313 | if (ether_addr_equal(new_bssid, bss_bssid)) { |
1303 | elems->nontransmitted_bssid_profile = | 1314 | found = true; |
1304 | elem->data; | ||
1305 | elems->bssid_index_len = index[1]; | 1315 | elems->bssid_index_len = index[1]; |
1306 | elems->bssid_index = (void *)&index[2]; | 1316 | elems->bssid_index = (void *)&index[2]; |
1307 | break; | 1317 | break; |
1308 | } | 1318 | } |
1309 | } | 1319 | } |
1310 | } | 1320 | } |
1321 | |||
1322 | return found ? profile_len : 0; | ||
1311 | } | 1323 | } |
1312 | 1324 | ||
1313 | u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | 1325 | u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, |
@@ -1316,30 +1328,34 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
1316 | u8 *bss_bssid) | 1328 | u8 *bss_bssid) |
1317 | { | 1329 | { |
1318 | const struct element *non_inherit = NULL; | 1330 | const struct element *non_inherit = NULL; |
1331 | u8 *nontransmitted_profile; | ||
1332 | int nontransmitted_profile_len = 0; | ||
1319 | 1333 | ||
1320 | memset(elems, 0, sizeof(*elems)); | 1334 | memset(elems, 0, sizeof(*elems)); |
1321 | elems->ie_start = start; | 1335 | elems->ie_start = start; |
1322 | elems->total_len = len; | 1336 | elems->total_len = len; |
1323 | 1337 | ||
1324 | ieee802_11_find_bssid_profile(start, len, elems, transmitter_bssid, | 1338 | nontransmitted_profile = kmalloc(len, GFP_ATOMIC); |
1325 | bss_bssid); | 1339 | if (nontransmitted_profile) { |
1326 | 1340 | nontransmitted_profile_len = | |
1327 | if (elems->nontransmitted_bssid_profile) | 1341 | ieee802_11_find_bssid_profile(start, len, elems, |
1342 | transmitter_bssid, | ||
1343 | bss_bssid, | ||
1344 | &nontransmitted_profile); | ||
1328 | non_inherit = | 1345 | non_inherit = |
1329 | cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, | 1346 | cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, |
1330 | &elems->nontransmitted_bssid_profile[2], | 1347 | nontransmitted_profile, |
1331 | elems->nontransmitted_bssid_profile[1]); | 1348 | nontransmitted_profile_len); |
1349 | } | ||
1332 | 1350 | ||
1333 | crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter, | 1351 | crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter, |
1334 | crc, non_inherit); | 1352 | crc, non_inherit); |
1335 | 1353 | ||
1336 | /* Override with nontransmitted profile, if found */ | 1354 | /* Override with nontransmitted profile, if found */ |
1337 | if (transmitter_bssid && elems->nontransmitted_bssid_profile) { | 1355 | if (nontransmitted_profile_len) |
1338 | const u8 *profile = elems->nontransmitted_bssid_profile; | 1356 | _ieee802_11_parse_elems_crc(nontransmitted_profile, |
1339 | 1357 | nontransmitted_profile_len, | |
1340 | _ieee802_11_parse_elems_crc(&profile[2], profile[1], | ||
1341 | action, elems, 0, 0, NULL); | 1358 | action, elems, 0, 0, NULL); |
1342 | } | ||
1343 | 1359 | ||
1344 | if (elems->tim && !elems->parse_error) { | 1360 | if (elems->tim && !elems->parse_error) { |
1345 | const struct ieee80211_tim_ie *tim_ie = elems->tim; | 1361 | const struct ieee80211_tim_ie *tim_ie = elems->tim; |
@@ -1359,6 +1375,8 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
1359 | offsetofend(struct ieee80211_bssid_index, dtim_count)) | 1375 | offsetofend(struct ieee80211_bssid_index, dtim_count)) |
1360 | elems->dtim_count = elems->bssid_index->dtim_count; | 1376 | elems->dtim_count = elems->bssid_index->dtim_count; |
1361 | 1377 | ||
1378 | kfree(nontransmitted_profile); | ||
1379 | |||
1362 | return crc; | 1380 | return crc; |
1363 | } | 1381 | } |
1364 | 1382 | ||