mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 22:53:55 +08:00
ath10k: support MAC address randomization in scan
The ath10k reports the random_mac_addr capability to upper layer based on the service bit firmware reported. Driver sets the spoofed flag in scan_ctrl_flag to firmware if upper layer has enabled this feature in scan request. Test with QCA6174 hw3.0 and firmware-6.bin_WLAN.RM.4.4.1-00102-QCARMSWP-1, but QCA9377 is also affected. Signed-off-by: Carl Huang <cjhuang@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
cea19a6ce8
commit
60e1d0fb29
@ -5717,6 +5717,12 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
|
||||
arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
|
||||
}
|
||||
|
||||
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
arg.scan_ctrl_flags |= WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ;
|
||||
ether_addr_copy(arg.mac_addr.addr, req->mac_addr);
|
||||
ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);
|
||||
}
|
||||
|
||||
if (req->n_channels) {
|
||||
arg.n_channels = req->n_channels;
|
||||
for (i = 0; i < arg.n_channels; i++)
|
||||
@ -8433,6 +8439,17 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
goto err_dfs_detector_exit;
|
||||
}
|
||||
|
||||
if (test_bit(WMI_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi.svc_map)) {
|
||||
ret = ath10k_wmi_scan_prob_req_oui(ar, ar->mac_addr);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to set prob req oui: %i\n", ret);
|
||||
goto err_dfs_detector_exit;
|
||||
}
|
||||
|
||||
ar->hw->wiphy->features |=
|
||||
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||
}
|
||||
|
||||
ar->hw->wiphy->cipher_suites = cipher_suites;
|
||||
|
||||
/* QCA988x and QCA6174 family chips do not support CCMP-256, GCMP-128
|
||||
|
@ -119,6 +119,8 @@ struct wmi_ops {
|
||||
u32 value);
|
||||
struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar,
|
||||
const struct wmi_scan_chan_list_arg *arg);
|
||||
struct sk_buff *(*gen_scan_prob_req_oui)(struct ath10k *ar,
|
||||
u32 prob_req_oui);
|
||||
struct sk_buff *(*gen_beacon_dma)(struct ath10k *ar, u32 vdev_id,
|
||||
const void *bcn, size_t bcn_len,
|
||||
u32 bcn_paddr, bool dtim_zero,
|
||||
@ -914,6 +916,26 @@ ath10k_wmi_scan_chan_list(struct ath10k *ar,
|
||||
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_scan_prob_req_oui(struct ath10k *ar, const u8 mac_addr[ETH_ALEN])
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u32 prob_req_oui;
|
||||
|
||||
prob_req_oui = (((u32)mac_addr[0]) << 16) |
|
||||
(((u32)mac_addr[1]) << 8) | mac_addr[2];
|
||||
|
||||
if (!ar->wmi.ops->gen_scan_prob_req_oui)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = ar->wmi.ops->gen_scan_prob_req_oui(ar, prob_req_oui);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
ar->wmi.cmd->scan_prob_req_oui_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_peer_assoc(struct ath10k *ar,
|
||||
const struct wmi_peer_assoc_complete_arg *arg)
|
||||
|
@ -1636,6 +1636,8 @@ ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
|
||||
cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
|
||||
cmd->ie_len = __cpu_to_le32(arg->ie_len);
|
||||
cmd->num_probes = __cpu_to_le32(3);
|
||||
ether_addr_copy(cmd->mac_addr.addr, arg->mac_addr.addr);
|
||||
ether_addr_copy(cmd->mac_mask.addr, arg->mac_mask.addr);
|
||||
|
||||
/* FIXME: There are some scan flag inconsistencies across firmwares,
|
||||
* e.g. WMI-TLV inverts the logic behind the following flag.
|
||||
@ -2482,6 +2484,27 @@ ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_scan_prob_req_oui(struct ath10k *ar, u32 prob_req_oui)
|
||||
{
|
||||
struct wmi_scan_prob_req_oui_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
tlv = (void *)skb->data;
|
||||
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_PROB_REQ_OUI_CMD);
|
||||
tlv->len = __cpu_to_le16(sizeof(*cmd));
|
||||
cmd = (void *)tlv->value;
|
||||
cmd->prob_req_oui = __cpu_to_le32(prob_req_oui);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan prob req oui\n");
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
|
||||
const void *bcn, size_t bcn_len,
|
||||
@ -3452,6 +3475,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = {
|
||||
.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
|
||||
.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
|
||||
.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
|
||||
.scan_prob_req_oui_cmdid = WMI_TLV_SCAN_PROB_REQ_OUI_CMDID,
|
||||
.pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
|
||||
.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
|
||||
.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
|
||||
@ -3820,6 +3844,7 @@ static const struct wmi_ops wmi_tlv_ops = {
|
||||
.gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
|
||||
.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
|
||||
.gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
|
||||
.gen_scan_prob_req_oui = ath10k_wmi_tlv_op_gen_scan_prob_req_oui,
|
||||
.gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
|
||||
.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
|
||||
.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
|
||||
|
@ -1706,6 +1706,15 @@ struct wmi_tlv_scan_chan_list_cmd {
|
||||
__le32 num_scan_chans;
|
||||
} __packed;
|
||||
|
||||
struct wmi_scan_prob_req_oui_cmd {
|
||||
/* OUI to be used in Probe Request frame when random MAC address is
|
||||
* requested part of scan parameters. This is applied to both FW internal
|
||||
* scans and host initiated scans. Host can request for random MAC address
|
||||
* with WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ flag.
|
||||
*/
|
||||
__le32 prob_req_oui;
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_start_scan_cmd {
|
||||
struct wmi_start_scan_common common;
|
||||
__le32 burst_duration_ms;
|
||||
@ -1714,6 +1723,8 @@ struct wmi_tlv_start_scan_cmd {
|
||||
__le32 num_ssids;
|
||||
__le32 ie_len;
|
||||
__le32 num_probes;
|
||||
struct wmi_mac_addr mac_addr;
|
||||
struct wmi_mac_addr mac_mask;
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_vdev_start_cmd {
|
||||
|
@ -42,6 +42,7 @@ static struct wmi_cmd_map wmi_cmd_map = {
|
||||
.stop_scan_cmdid = WMI_STOP_SCAN_CMDID,
|
||||
.scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID,
|
||||
.scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_CMDID,
|
||||
.scan_prob_req_oui_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_set_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID,
|
||||
.pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID,
|
||||
.pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID,
|
||||
@ -207,6 +208,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
|
||||
.stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID,
|
||||
.scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID,
|
||||
.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.scan_prob_req_oui_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_set_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID,
|
||||
.pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID,
|
||||
.pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_CMDID,
|
||||
@ -374,6 +376,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
|
||||
.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
|
||||
.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
|
||||
.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.scan_prob_req_oui_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
|
||||
.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
|
||||
.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
|
||||
@ -541,6 +544,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
|
||||
.stop_scan_cmdid = WMI_10_4_STOP_SCAN_CMDID,
|
||||
.scan_chan_list_cmdid = WMI_10_4_SCAN_CHAN_LIST_CMDID,
|
||||
.scan_sch_prio_tbl_cmdid = WMI_10_4_SCAN_SCH_PRIO_TBL_CMDID,
|
||||
.scan_prob_req_oui_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_set_regdomain_cmdid = WMI_10_4_PDEV_SET_REGDOMAIN_CMDID,
|
||||
.pdev_set_channel_cmdid = WMI_10_4_PDEV_SET_CHANNEL_CMDID,
|
||||
.pdev_set_param_cmdid = WMI_10_4_PDEV_SET_PARAM_CMDID,
|
||||
@ -1338,6 +1342,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
|
||||
.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
|
||||
.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
|
||||
.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.scan_prob_req_oui_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
|
||||
.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
|
||||
.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
|
||||
|
@ -791,6 +791,7 @@ struct wmi_cmd_map {
|
||||
u32 stop_scan_cmdid;
|
||||
u32 scan_chan_list_cmdid;
|
||||
u32 scan_sch_prio_tbl_cmdid;
|
||||
u32 scan_prob_req_oui_cmdid;
|
||||
u32 pdev_set_regdomain_cmdid;
|
||||
u32 pdev_set_channel_cmdid;
|
||||
u32 pdev_set_param_cmdid;
|
||||
@ -3168,6 +3169,8 @@ struct wmi_start_scan_arg {
|
||||
u16 channels[64];
|
||||
struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
|
||||
struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
|
||||
struct wmi_mac_addr mac_addr;
|
||||
struct wmi_mac_addr mac_mask;
|
||||
};
|
||||
|
||||
/* scan control flags */
|
||||
@ -3191,6 +3194,12 @@ struct wmi_start_scan_arg {
|
||||
*/
|
||||
#define WMI_SCAN_CONTINUE_ON_ERROR 0x80
|
||||
|
||||
/* Use random MAC address for TA for Probe Request frame and add
|
||||
* OUI specified by WMI_SCAN_PROB_REQ_OUI_CMDID to the Probe Request frame.
|
||||
* if OUI is not set by WMI_SCAN_PROB_REQ_OUI_CMDID then the flag is ignored.
|
||||
*/
|
||||
#define WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ 0x1000
|
||||
|
||||
/* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */
|
||||
#define WMI_SCAN_CLASS_MASK 0xFF000000
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user