diff mbox series

[08/11] mac80211: support non-inheritance element

Message ID 20190315153907.16192-9-luca@coelho.fi (mailing list archive)
State Accepted
Delegated to: Johannes Berg
Headers show
Series cfg80211/mac80211 patches from our internal tree 2019-03-15 | expand

Commit Message

Luca Coelho March 15, 2019, 3:39 p.m. UTC
From: Sara Sharon <sara.sharon@intel.com>

Subelement profile may specify element IDs it doesn't inherit
from the management frame. Support it.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
 net/mac80211/util.c | 134 +++++++++++++++++++++++++-------------------
 1 file changed, 77 insertions(+), 57 deletions(-)
diff mbox series

Patch

diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4c1655972565..08197afdb7b3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -894,10 +894,10 @@  EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 static u32
 _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 			    struct ieee802_11_elems *elems,
-			    u64 filter, u32 crc, u8 *transmitter_bssid,
-			    u8 *bss_bssid)
+			    u64 filter, u32 crc,
+			    const struct element *check_inherit)
 {
-	const struct element *elem, *sub;
+	const struct element *elem;
 	bool calc_crc = filter != 0;
 	DECLARE_BITMAP(seen_elems, 256);
 	const u8 *ie;
@@ -910,6 +910,11 @@  _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 		u8 elen = elem->datalen;
 		const u8 *pos = elem->data;
 
+		if (check_inherit &&
+		    !cfg80211_is_element_inherited(elem,
+						   check_inherit))
+			continue;
+
 		switch (id) {
 		case WLAN_EID_SSID:
 		case WLAN_EID_SUPP_RATES:
@@ -1208,57 +1213,6 @@  _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 			if (elen >= sizeof(*elems->max_idle_period_ie))
 				elems->max_idle_period_ie = (void *)pos;
 			break;
-		case WLAN_EID_MULTIPLE_BSSID:
-			if (!bss_bssid || !transmitter_bssid || elen < 4)
-				break;
-
-			elems->max_bssid_indicator = pos[0];
-
-			for_each_element(sub, pos + 1, elen - 1) {
-				u8 sub_len = sub->datalen;
-				u8 new_bssid[ETH_ALEN];
-				const u8 *index;
-
-				/*
-				 * we only expect the "non-transmitted BSSID
-				 * profile" subelement (subelement id 0)
-				 */
-				if (sub->id != 0 || sub->datalen < 4) {
-					/* not a valid BSS profile */
-					continue;
-				}
-
-				if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
-				    sub->data[1] != 2) {
-					/* The first element of the
-					 * Nontransmitted BSSID Profile is not
-					 * the Nontransmitted BSSID Capability
-					 * element.
-					 */
-					continue;
-				}
-
-				/* found a Nontransmitted BSSID Profile */
-				index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
-							 sub->data, sub_len);
-				if (!index || index[1] < 1 || index[2] == 0) {
-					/* Invalid MBSSID Index element */
-					continue;
-				}
-
-				cfg80211_gen_new_bssid(transmitter_bssid,
-						       pos[0],
-						       index[2],
-						       new_bssid);
-				if (ether_addr_equal(new_bssid, bss_bssid)) {
-					elems->nontransmitted_bssid_profile =
-						(void *)sub;
-					elems->bssid_index_len = index[1];
-					elems->bssid_index = (void *)&index[2];
-					break;
-				}
-			}
-			break;
 		case WLAN_EID_EXTENSION:
 			if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
 			    elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
@@ -1300,25 +1254,91 @@  _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)
+{
+	const struct element *elem, *sub;
+
+	if (!bss_bssid || !transmitter_bssid)
+		return;
+
+	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
+		if (elem->datalen < 2)
+			continue;
+
+		for_each_element(sub, elem->data + 1, elem->datalen - 1) {
+			u8 new_bssid[ETH_ALEN];
+			const u8 *index;
+
+			if (sub->id != 0 || sub->datalen < 4) {
+				/* not a valid BSS profile */
+				continue;
+			}
+
+			if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
+			    sub->data[1] != 2) {
+				/* The first element of the
+				 * Nontransmitted BSSID Profile is not
+				 * the Nontransmitted BSSID Capability
+				 * element.
+				 */
+				continue;
+			}
+
+			/* found a Nontransmitted BSSID Profile */
+			index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
+						 sub->data, sub->datalen);
+			if (!index || index[1] < 1 || index[2] == 0) {
+				/* Invalid MBSSID Index element */
+				continue;
+			}
+
+			cfg80211_gen_new_bssid(transmitter_bssid,
+					       elem->data[0],
+					       index[2],
+					       new_bssid);
+			if (ether_addr_equal(new_bssid, bss_bssid)) {
+				elems->nontransmitted_bssid_profile =
+					elem->data;
+				elems->bssid_index_len = index[1];
+				elems->bssid_index = (void *)&index[2];
+				break;
+			}
+		}
+	}
+}
+
 u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 			       struct ieee802_11_elems *elems,
 			       u64 filter, u32 crc, u8 *transmitter_bssid,
 			       u8 *bss_bssid)
 {
+	const struct element *non_inherit = NULL;
+
 	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)
+		non_inherit =
+			cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
+					       &elems->nontransmitted_bssid_profile[2],
+					       elems->nontransmitted_bssid_profile[1]);
+
 	crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
-					  crc, transmitter_bssid, bss_bssid);
+					  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],
-					    action, elems, 0, 0,
-					    transmitter_bssid, bss_bssid);
+					    action, elems, 0, 0, NULL);
 	}
 
 	if (elems->tim && !elems->parse_error) {