mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 01:08:13 -04:00
wifi: cfg80211: Add MAC address filter to remain_on_channel
Currently the remain_on_channel operation does not support filtering incoming frames by destination MAC address. This prevents use cases such as PASN authentication in the responder side that need to receive frames addressed to a specific MAC during the off-channel period. Add an rx_addr parameter to the remain_on_channel operation callback and propagate it through the call chain from nl80211 to driver implementations. Introduce the extended feature NL80211_EXT_FEATURE_ROC_ADDR_FILTER as a capability gate so that cfg80211 rejects the request if the driver does not advertise support for address filtering. Extract the address from the NL80211_ATTR_MAC attribute when provided in the netlink message and update the tracing infrastructure to include the address in remain_on_channel trace events. The rx_addr parameter is optional and can be NULL, maintaining backward compatibility with existing drivers. Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com> Link: https://patch.msgid.link/20260420090856.2152905-3-peddolla.reddy@oss.qualcomm.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
bef9d5e378
commit
4dbd182904
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -3033,7 +3034,7 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration,
|
||||
u64 *cookie)
|
||||
u64 *cookie, const u8 *rx_addr)
|
||||
{
|
||||
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
|
||||
struct ath6kl *ar = ath6kl_priv(vif->ndev);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
@@ -1734,7 +1735,7 @@ static int wil_remain_on_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration,
|
||||
u64 *cookie)
|
||||
u64 *cookie, const u8 *rx_addr)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
int rc;
|
||||
|
||||
@@ -970,10 +970,12 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
|
||||
* @channel: channel to stay on.
|
||||
* @duration: time in ms to remain on channel.
|
||||
* @cookie: cookie.
|
||||
* @rx_addr: Address to match against the destination of received frames
|
||||
*/
|
||||
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int duration, u64 *cookie)
|
||||
unsigned int duration, u64 *cookie,
|
||||
const u8 *rx_addr)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||
|
||||
@@ -157,7 +157,8 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int duration, u64 *cookie);
|
||||
unsigned int duration, u64 *cookie,
|
||||
const u8 *rx_addr);
|
||||
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
|
||||
@@ -304,7 +304,8 @@ static int
|
||||
mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration, u64 *cookie)
|
||||
unsigned int duration, u64 *cookie,
|
||||
const u8 *rx_addr)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
|
||||
int ret;
|
||||
|
||||
@@ -1100,7 +1100,8 @@ static void wilc_wfi_remain_on_channel_expired(struct wilc_vif *vif, u64 cookie)
|
||||
static int remain_on_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration, u64 *cookie)
|
||||
unsigned int duration, u64 *cookie,
|
||||
const u8 *rx_addr)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wilc_vif *vif = netdev_priv(wdev->netdev);
|
||||
|
||||
@@ -5270,7 +5270,7 @@ struct cfg80211_ops {
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration,
|
||||
u64 *cookie);
|
||||
u64 *cookie, const u8 *rx_addr);
|
||||
int (*cancel_remain_on_channel)(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
u64 cookie);
|
||||
|
||||
@@ -729,7 +729,9 @@
|
||||
* to remain on the channel. This command is also used as an event to
|
||||
* notify when the requested duration starts (it may take a while for the
|
||||
* driver to schedule this time due to other concurrent needs for the
|
||||
* radio).
|
||||
* radio). An optional attribute %NL80211_ATTR_MAC can be used to filter
|
||||
* incoming frames during remain-on-channel, such that frames
|
||||
* addressed to the specified destination MAC are reported.
|
||||
* When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
|
||||
* that will be included with any events pertaining to this request;
|
||||
* the cookie is also used to cancel the request.
|
||||
@@ -7040,6 +7042,12 @@ enum nl80211_feature_flags {
|
||||
* (NL80211_CMD_AUTHENTICATE) in non-AP STA mode, as specified in
|
||||
* "IEEE P802.11bi/D4.0, 12.16.5".
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_ROC_ADDR_FILTER: Driver supports MAC address
|
||||
* filtering during remain-on-channel. When %NL80211_ATTR_MAC is
|
||||
* provided with %NL80211_CMD_REMAIN_ON_CHANNEL, the driver will
|
||||
* forward frames with a matching MAC address to userspace during
|
||||
* the off-channel period.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@@ -7119,6 +7127,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_EPPKE,
|
||||
NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION,
|
||||
NL80211_EXT_FEATURE_IEEE8021X_AUTH,
|
||||
NL80211_EXT_FEATURE_ROC_ADDR_FILTER,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
||||
@@ -2097,7 +2097,8 @@ void ieee80211_roc_purge(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration, u64 *cookie);
|
||||
unsigned int duration, u64 *cookie,
|
||||
const u8 *rx_addr);
|
||||
int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev, u64 cookie);
|
||||
int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
|
||||
@@ -706,7 +706,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
||||
|
||||
int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration, u64 *cookie)
|
||||
unsigned int duration, u64 *cookie,
|
||||
const u8 *rx_addr)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
@@ -14133,6 +14133,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||
unsigned int link_id = nl80211_link_id(info->attrs);
|
||||
struct wireless_dev *wdev = info->user_ptr[1];
|
||||
struct cfg80211_chan_def chandef;
|
||||
const u8 *rx_addr = NULL;
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
u64 cookie;
|
||||
@@ -14145,6 +14146,14 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||
|
||||
duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MAC])
|
||||
rx_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
if (rx_addr &&
|
||||
!wiphy_ext_feature_isset(wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_ROC_ADDR_FILTER))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!rdev->ops->remain_on_channel ||
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
|
||||
return -EOPNOTSUPP;
|
||||
@@ -14192,7 +14201,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
|
||||
duration, &cookie);
|
||||
duration, &cookie, rx_addr);
|
||||
|
||||
if (err)
|
||||
goto free_msg;
|
||||
|
||||
@@ -736,12 +736,13 @@ static inline int
|
||||
rdev_remain_on_channel(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration, u64 *cookie)
|
||||
unsigned int duration, u64 *cookie, const u8 *rx_addr)
|
||||
{
|
||||
int ret;
|
||||
trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration);
|
||||
trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration,
|
||||
rx_addr);
|
||||
ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
|
||||
duration, cookie);
|
||||
duration, cookie, rx_addr);
|
||||
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2155,22 +2155,26 @@ DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa,
|
||||
TRACE_EVENT(rdev_remain_on_channel,
|
||||
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *chan,
|
||||
unsigned int duration),
|
||||
TP_ARGS(wiphy, wdev, chan, duration),
|
||||
unsigned int duration, const u8 *rx_addr),
|
||||
TP_ARGS(wiphy, wdev, chan, duration, rx_addr),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
WDEV_ENTRY
|
||||
CHAN_ENTRY
|
||||
__field(unsigned int, duration)
|
||||
MAC_ENTRY(rx_addr)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
WDEV_ASSIGN;
|
||||
CHAN_ASSIGN(chan);
|
||||
__entry->duration = duration;
|
||||
MAC_ASSIGN(rx_addr, rx_addr);
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", duration: %u",
|
||||
WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration)
|
||||
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT
|
||||
", duration: %u, %pM",
|
||||
WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration,
|
||||
__entry->rx_addr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_return_int_cookie,
|
||||
|
||||
Reference in New Issue
Block a user