summaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2019-03-15 11:39:06 -0400
committerJohannes Berg <johannes.berg@intel.com>2019-04-26 07:02:11 -0400
commit5023b14cf4df4d22e1a80738167f3438c9e62e5f (patch)
tree11ceff2719773e48952818ba9c393cdd186a8220 /net/mac80211/util.c
parentfe806e4992c9047affd263bcc13b2c047029a726 (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.c56
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
1257static void ieee802_11_find_bssid_profile(const u8 *start, size_t len, 1257static 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
1313u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, 1325u32 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