diff mbox series

[13/22] cfg80211: handle Association Response from S1G STA

Message ID 20200827223304.16155-14-thomas@adapt-ip.com (mailing list archive)
State Superseded
Delegated to: Johannes Berg
Headers show
Series add initial S1G support | expand

Commit Message

Thomas Pedersen Aug. 27, 2020, 10:32 p.m. UTC
The sending STA type is implicit based on beacon or probe
response content. If sending STA was an S1G STA, adjust
the Information Element location accordingly.

Signed-off-by: Thomas Pedersen <thomas@adapt-ip.com>
---
 include/linux/ieee80211.h |  5 +++++
 net/wireless/mlme.c       | 20 ++++++++++++++++++++
 2 files changed, 25 insertions(+)
diff mbox series

Patch

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index fe70cd99dec7..9307b60cef97 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1100,6 +1100,11 @@  struct ieee80211_mgmt {
 			/* followed by Supported rates */
 			u8 variable[0];
 		} __packed assoc_resp, reassoc_resp;
+		struct {
+			__le16 capab_info;
+			__le16 status_code;
+			u8 variable[0];
+		} __packed s1g_assoc_resp, s1g_reassoc_resp;
 		struct {
 			__le16 capab_info;
 			__le16 listen_interval;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index a6c61a2e6569..b5275fe93531 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -30,6 +30,8 @@  void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 	struct cfg80211_connect_resp_params cr;
+	const struct cfg80211_bss_ies *ies;
+	const u8 *s1g;
 
 	memset(&cr, 0, sizeof(cr));
 	cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -42,6 +44,24 @@  void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
 		len - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
 	cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED;
 
+	/* Detect whether this was an S1G Association Response and adjust IE
+	 * location accordingly.
+	 */
+	rcu_read_lock();
+	ies = rcu_dereference(bss->ies);
+	if (WARN_ON(!ies)) {
+		rcu_read_unlock();
+		return;
+	}
+	s1g = cfg80211_find_ie(WLAN_EID_S1G_CAPABILITIES, ies->data, ies->len);
+	if (s1g) {
+		cr.resp_ie = (u8 *)&mgmt->u.s1g_assoc_resp.variable;
+		cr.resp_ie_len =
+			len - offsetof(struct ieee80211_mgmt,
+				       u.s1g_assoc_resp.variable);
+	}
+	rcu_read_unlock();
+
 	trace_cfg80211_send_rx_assoc(dev, bss);
 
 	/*