Search Linux Wireless

[PATCH 10/11] mac80211: support profile split between elements

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Sara Sharon <sara.sharon@xxxxxxxxx>

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@xxxxxxxxx>
Signed-off-by: Luca Coelho <luciano.coelho@xxxxxxxxx>
---
 net/mac80211/ieee80211_i.h |  1 -
 net/mac80211/util.c        | 56 +++++++++++++++++++++++++-------------
 2 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e170f986d226..c5708f8a7401 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1505,7 +1505,6 @@ struct ieee802_11_elems {
 	const struct ieee80211_bss_max_idle_period_ie *max_idle_period_ie;
 	const struct ieee80211_multiple_bssid_configuration *mbssid_config_ie;
 	const struct ieee80211_bssid_index *bssid_index;
-	const u8 *nontransmitted_bssid_profile;
 	u8 max_bssid_indicator;
 	u8 dtim_count;
 	u8 dtim_period;
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,
 	return crc;
 }
 
-static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
-					  struct ieee802_11_elems *elems,
-					  u8 *transmitter_bssid,
-					  u8 *bss_bssid)
+static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
+					    struct ieee802_11_elems *elems,
+					    u8 *transmitter_bssid,
+					    u8 *bss_bssid,
+					    u8 **nontransmitted_profile)
 {
 	const struct element *elem, *sub;
+	size_t profile_len = 0;
+	bool found = false;
 
 	if (!bss_bssid || !transmitter_bssid)
-		return;
+		return profile_len;
 
 	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
 		if (elem->datalen < 2)
@@ -1287,9 +1290,17 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
 				continue;
 			}
 
+			memset(*nontransmitted_profile, 0, len);
+			profile_len = cfg80211_merge_profile(start, len,
+							     elem,
+							     sub,
+							     nontransmitted_profile,
+							     len);
+
 			/* found a Nontransmitted BSSID Profile */
 			index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
-						 sub->data, sub->datalen);
+						 *nontransmitted_profile,
+						 profile_len);
 			if (!index || index[1] < 1 || index[2] == 0) {
 				/* Invalid MBSSID Index element */
 				continue;
@@ -1300,14 +1311,15 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
 					       index[2],
 					       new_bssid);
 			if (ether_addr_equal(new_bssid, bss_bssid)) {
-				elems->nontransmitted_bssid_profile =
-					elem->data;
+				found = true;
 				elems->bssid_index_len = index[1];
 				elems->bssid_index = (void *)&index[2];
 				break;
 			}
 		}
 	}
+
+	return found ? profile_len : 0;
 }
 
 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,
 			       u8 *bss_bssid)
 {
 	const struct element *non_inherit = NULL;
+	u8 *nontransmitted_profile;
+	int nontransmitted_profile_len = 0;
 
 	memset(elems, 0, sizeof(*elems));
 	elems->ie_start = start;
 	elems->total_len = len;
 
-	ieee802_11_find_bssid_profile(start, len, elems, transmitter_bssid,
-				      bss_bssid);
-
-	if (elems->nontransmitted_bssid_profile)
+	nontransmitted_profile = kmalloc(len, GFP_ATOMIC);
+	if (nontransmitted_profile) {
+		nontransmitted_profile_len =
+			ieee802_11_find_bssid_profile(start, len, elems,
+						      transmitter_bssid,
+						      bss_bssid,
+						      &nontransmitted_profile);
 		non_inherit =
 			cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
-					       &elems->nontransmitted_bssid_profile[2],
-					       elems->nontransmitted_bssid_profile[1]);
+					       nontransmitted_profile,
+					       nontransmitted_profile_len);
+	}
 
 	crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
 					  crc, non_inherit);
 
 	/* Override with nontransmitted profile, if found */
-	if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
-		const u8 *profile = elems->nontransmitted_bssid_profile;
-
-		_ieee802_11_parse_elems_crc(&profile[2], profile[1],
+	if (nontransmitted_profile_len)
+		_ieee802_11_parse_elems_crc(nontransmitted_profile,
+					    nontransmitted_profile_len,
 					    action, elems, 0, 0, NULL);
-	}
 
 	if (elems->tim && !elems->parse_error) {
 		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,
 	    offsetofend(struct ieee80211_bssid_index, dtim_count))
 		elems->dtim_count = elems->bssid_index->dtim_count;
 
+	kfree(nontransmitted_profile);
+
 	return crc;
 }
 
-- 
2.20.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux