diff mbox series

wifi: mac80211: Add support to randomize TA of auth and deauth frames

Message ID 20230307102225.74883-1-johannes@sipsolutions.net (mailing list archive)
State Not Applicable
Delegated to: Johannes Berg
Headers show
Series wifi: mac80211: Add support to randomize TA of auth and deauth frames | expand

Commit Message

Johannes Berg March 7, 2023, 10:22 a.m. UTC
From: Veerendranath Jakkam <quic_vjakkam@quicinc.com>

Cache the TA of the authentication and deauthentication frames
temporarily till the response waiting time offchannel period complete
and indicate the temporary address to driver when driver supports
randomizing TA of auth and deauth frames. Driver should allow TX and RX
of the frames when the temporary address is TA and RA respectively.
Allow the authentication and deauthentication frames with cached
address as RA in RX path.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Link: https://lore.kernel.org/r/20230112012415.167556-3-quic_vjakkam@quicinc.com
[simplify, fix locking]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
So this is the patch I ended up with after some cleanups, but
then at the end I noticed you didn't unset the temp address
when the remain-on-channel expires, and wasn't sure exactly
how that should be handled, and you probably have the better
test setup right now too ...

johannes
---
 include/net/mac80211.h    | 12 ++++++++++++
 net/mac80211/main.c       |  3 ++-
 net/mac80211/offchannel.c | 38 ++++++++++++++++++++++++++++++++++++++
 net/mac80211/rx.c         | 18 ++++++++++++++----
 net/mac80211/util.c       |  7 ++++++-
 5 files changed, 72 insertions(+), 6 deletions(-)

Comments

Veerendranath Jakkam April 6, 2023, 1:17 p.m. UTC | #1
On 3/7/2023 3:52 PM, Johannes Berg wrote:
> ---
> So this is the patch I ended up with after some cleanups, but
> then at the end I noticed you didn't unset the temp address
> when the remain-on-channel expires, and wasn't sure exactly
> how that should be handled, and you probably have the better
> test setup right now too ...
>
> johannes
> ---


Apologies for the delayed response. Thanks for the cleaning up the patch.

Regarding the comment on clearing temp address, I think the temp address 
should get cleared with below changes added in 
ieee80211_roc_notify_destroy() when remain-on-channel expires. Please 
let me know if I am missing something.


> diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
> index d78c82d6b696..74d2b826916a 100644
> --- a/net/mac80211/offchannel.c
> +++ b/net/mac80211/offchannel.c
> @@ -187,6 +187,12 @@ static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
>   					 roc->mgmt_tx_cookie,
>   					 roc->chan, GFP_KERNEL);
>   
> +	if (!is_zero_ether_addr(roc->sdata->vif.cfg.temp_addr)) {
> +		eth_zero_addr(roc->sdata->vif.cfg.temp_addr);
> +		ieee80211_vif_cfg_change_notify(roc->sdata,
> +						BSS_CHANGED_TEMP_ADDR);
> +	}
> +
>   	list_del(&roc->list);
>   	kfree(roc);
>   }

--

veeru
Johannes Berg April 11, 2023, 10:15 a.m. UTC | #2
On Thu, 2023-04-06 at 18:47 +0530, Veerendranath Jakkam wrote:
> On 3/7/2023 3:52 PM, Johannes Berg wrote:
> > ---
> > So this is the patch I ended up with after some cleanups, but
> > then at the end I noticed you didn't unset the temp address
> > when the remain-on-channel expires, and wasn't sure exactly
> > how that should be handled, and you probably have the better
> > test setup right now too ...

> Apologies for the delayed response. Thanks for the cleaning up the patch.
> 
> Regarding the comment on clearing temp address, I think the temp address 
> should get cleared with below changes added in 
> ieee80211_roc_notify_destroy() when remain-on-channel expires. Please 
> let me know if I am missing something.
> 
> 
> > diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
> > index d78c82d6b696..74d2b826916a 100644
> > --- a/net/mac80211/offchannel.c
> > +++ b/net/mac80211/offchannel.c
> > @@ -187,6 +187,12 @@ static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
> >   					 roc->mgmt_tx_cookie,
> >   					 roc->chan, GFP_KERNEL);
> >   
> > +	if (!is_zero_ether_addr(roc->sdata->vif.cfg.temp_addr)) {
> > +		eth_zero_addr(roc->sdata->vif.cfg.temp_addr);
> > +		ieee80211_vif_cfg_change_notify(roc->sdata,
> > +						BSS_CHANGED_TEMP_ADDR);
> > +	}
> > +
> >   	list_del(&roc->list);
> >   	kfree(roc);
> >   }
> 

Huh, yeah, looks like I just missed that? Sorry about that.

Seeing that though, I remembered another thing - don't we have to adjust
the merging logic in ieee80211_start_roc_work() and maybe also
ieee80211_coalesce_hw_started_roc()?

johannes
Veerendranath Jakkam May 22, 2023, 10:29 a.m. UTC | #3
On 4/11/2023 3:45 PM, Johannes Berg wrote:
>
> Huh, yeah, looks like I just missed that? Sorry about that.
>
> Seeing that though, I remembered another thing - don't we have to adjust
> the merging logic in ieee80211_start_roc_work() and maybe also
> ieee80211_coalesce_hw_started_roc()?
>
> johannes


All the cases(HW/SW RoCs, merged/combined RoCs) handled in 
ieee80211_start_roc_work() and ieee80211_coalesce_hw_started_roc() 
should end up calling ieee80211_handle_roc_started(), hence kept the 
temp_address configuration logic in ieee80211_handle_roc_started(). 
Please let me know if I am missing something?

--

veeru
Veerendranath Jakkam July 20, 2023, 7:03 a.m. UTC | #4
On 3/7/2023 3:52 PM, Johannes Berg wrote:
> ---
> So this is the patch I ended up with after some cleanups, but
> then at the end I noticed you didn't unset the temp address
> when the remain-on-channel expires, and wasn't sure exactly
> how that should be handled, and you probably have the better
> test setup right now too ...
>
> johannes
> ---

Hi Johannes,

I verified this patch using below "mac80211_hwsim" and hostap patches. 
It is working fine.

https://patchwork.kernel.org/project/linux-wireless/patch/20230112012415.167556-4-quic_vjakkam@quicinc.com/

https://patchwork.ozlabs.org/project/hostap/list/?series=335502&state=* 
<https://patchwork.ozlabs.org/project/hostap/list/?series=335502&state=*> 
- hostap HWSIM test changes

---

veeru
diff mbox series

Patch

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f12edca660ba..d6ff3bd1dd72 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -341,6 +341,8 @@  struct ieee80211_vif_chanctx_switch {
  * @BSS_CHANGED_UNSOL_BCAST_PROBE_RESP: Unsolicited broadcast probe response
  *	status changed.
  * @BSS_CHANGED_EHT_PUNCTURING: The channel puncturing bitmap changed.
+ * @BSS_CHANGED_TEMP_ADDR: Temporary self address allowed for authentication and
+ *	deauthentication frames is changed.
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -376,6 +378,7 @@  enum ieee80211_bss_change {
 	BSS_CHANGED_FILS_DISCOVERY      = 1<<30,
 	BSS_CHANGED_UNSOL_BCAST_PROBE_RESP = 1<<31,
 	BSS_CHANGED_EHT_PUNCTURING	= BIT_ULL(32),
+	BSS_CHANGED_TEMP_ADDR		= BIT_ULL(33),
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -1805,6 +1808,14 @@  enum ieee80211_offload_flags {
  *	your driver/device needs to do.
  * @ap_addr: AP MLD address, or BSSID for non-MLO connections
  *	(station mode only)
+ * @temp_addr: Temporary self address allowed for the authentication and
+ *	deauthentication frames till the response waiting time offchannel period
+ *	complete. Driver should allow TX and RX of the frames with the temporary
+ *	address as TA and RA respectively when it is non zero. This will be set
+ *	to zero address when no temporary self address is active.
+ *	Change in the value of this will be indicated with
+ *	%BSS_CHANGED_TEMP_ADDR. This will be used only when driver supports
+ *	%NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA.
  */
 struct ieee80211_vif_cfg {
 	/* association related data */
@@ -1820,6 +1831,7 @@  struct ieee80211_vif_cfg {
 	bool s1g;
 	bool idle;
 	u8 ap_addr[ETH_ALEN] __aligned(2);
+	u8 temp_addr[ETH_ALEN] __aligned(2);
 };
 
 /**
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 846528850612..238cbf05d08d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -205,7 +205,8 @@  int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 				   BSS_CHANGED_PS |\
 				   BSS_CHANGED_IBSS |\
 				   BSS_CHANGED_ARP_FILTER |\
-				   BSS_CHANGED_SSID)
+				   BSS_CHANGED_SSID |\
+				   BSS_CHANGED_TEMP_ADDR)
 
 void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 				      u64 changed)
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index d78c82d6b696..74d2b826916a 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -187,6 +187,12 @@  static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
 					 roc->mgmt_tx_cookie,
 					 roc->chan, GFP_KERNEL);
 
+	if (!is_zero_ether_addr(roc->sdata->vif.cfg.temp_addr)) {
+		eth_zero_addr(roc->sdata->vif.cfg.temp_addr);
+		ieee80211_vif_cfg_change_notify(roc->sdata,
+						BSS_CHANGED_TEMP_ADDR);
+	}
+
 	list_del(&roc->list);
 	kfree(roc);
 }
@@ -234,6 +240,36 @@  static bool ieee80211_recalc_sw_work(struct ieee80211_local *local,
 	return true;
 }
 
+static void ieee80211_config_temp_addr(struct ieee80211_sub_if_data *sdata,
+				       const struct ieee80211_hdr *hdr)
+{
+	unsigned int link;
+
+	if (!wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+			NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA))
+		return;
+
+	if (ether_addr_equal(sdata->vif.cfg.temp_addr, hdr->addr2))
+		return;
+
+	rcu_read_lock();
+	for (link = 0; link < ARRAY_SIZE(sdata->vif.link_conf); link++) {
+		struct ieee80211_bss_conf *link_conf;
+
+		link_conf = rcu_dereference(sdata->vif.link_conf[link]);
+		if (!link_conf)
+			continue;
+		if (ether_addr_equal(link_conf->addr, hdr->addr2)) {
+			rcu_read_unlock();
+			return;
+		}
+	}
+	rcu_read_unlock();
+
+	memcpy(sdata->vif.cfg.temp_addr, hdr->addr2, ETH_ALEN);
+	ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_TEMP_ADDR);
+}
+
 static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc,
 					 unsigned long start_time)
 {
@@ -245,6 +281,8 @@  static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc,
 
 	if (roc->mgmt_tx_cookie) {
 		if (!WARN_ON(!roc->frame)) {
+			ieee80211_config_temp_addr(roc->sdata,
+						   (void *) roc->frame->data);
 			ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7,
 						  roc->chan->band);
 			roc->frame = NULL;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 0255c5745e1c..fb2c54367046 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4255,6 +4255,12 @@  static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 	u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
 	bool multicast = is_multicast_ether_addr(hdr->addr1) ||
 			 ieee80211_is_s1g_beacon(hdr->frame_control);
+	bool skip_addr1_check = false;
+
+	if ((ieee80211_is_auth(hdr->frame_control) ||
+	     ieee80211_is_deauth(hdr->frame_control)) &&
+	    ether_addr_equal(sdata->vif.cfg.temp_addr, hdr->addr1))
+		skip_addr1_check = true;
 
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_STATION:
@@ -4265,6 +4271,8 @@  static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 			return false;
 		if (multicast)
 			return true;
+		if (skip_addr1_check)
+			return true;
 		return ieee80211_is_our_addr(sdata, hdr->addr1, &rx->link_id);
 	case NL80211_IFTYPE_ADHOC:
 		if (!bssid)
@@ -4277,7 +4285,7 @@  static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 			return true;
 		if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid))
 			return false;
-		if (!multicast &&
+		if (!multicast && !skip_addr1_check &&
 		    !ether_addr_equal(sdata->vif.addr, hdr->addr1))
 			return false;
 		if (!rx->sta) {
@@ -4297,7 +4305,7 @@  static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 			return false;
 		if (!is_broadcast_ether_addr(bssid))
 			return false;
-		if (!multicast &&
+		if (!multicast && !skip_addr1_check &&
 		    !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))
 			return false;
 		if (!rx->sta) {
@@ -4315,10 +4323,12 @@  static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 			return false;
 		if (multicast)
 			return true;
+		if (skip_addr1_check)
+			return true;
 		return ether_addr_equal(sdata->vif.addr, hdr->addr1);
 	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_AP:
-		if (!bssid)
+		if (!bssid && !skip_addr1_check)
 			return ieee80211_is_our_addr(sdata, hdr->addr1,
 						     &rx->link_id);
 
@@ -4330,7 +4340,7 @@  static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 			 * and location updates. Note that mac80211
 			 * itself never looks at these frames.
 			 */
-			if (!multicast &&
+			if (!multicast && !skip_addr1_check &&
 			    !ieee80211_is_our_addr(sdata, hdr->addr1,
 						   &rx->link_id))
 				return false;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1a28fe5cb614..017bfb0e5387 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2614,7 +2614,7 @@  int ieee80211_reconfig(struct ieee80211_local *local)
 	/* Finally also reconfigure all the BSS information */
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		unsigned int link_id;
-		u32 changed;
+		u64 changed;
 
 		if (!ieee80211_sdata_running(sdata))
 			continue;
@@ -2663,6 +2663,11 @@  int ieee80211_reconfig(struct ieee80211_local *local)
 			  BSS_CHANGED_TXPOWER |
 			  BSS_CHANGED_MCAST_RATE;
 
+		if (!is_zero_ether_addr(sdata->vif.cfg.temp_addr)) {
+			eth_zero_addr(sdata->vif.cfg.temp_addr);
+			changed |= BSS_CHANGED_TEMP_ADDR;
+		}
+
 		if (sdata->vif.bss_conf.mu_mimo_owner)
 			changed |= BSS_CHANGED_MU_GROUPS;