Commit 60e1d0fb authored by Carl Huang's avatar Carl Huang Committed by Kalle Valo

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: default avatarCarl Huang <cjhuang@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent cea19a6c
...@@ -5717,6 +5717,12 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, ...@@ -5717,6 +5717,12 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; 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) { if (req->n_channels) {
arg.n_channels = req->n_channels; arg.n_channels = req->n_channels;
for (i = 0; i < arg.n_channels; i++) for (i = 0; i < arg.n_channels; i++)
...@@ -8433,6 +8439,17 @@ int ath10k_mac_register(struct ath10k *ar) ...@@ -8433,6 +8439,17 @@ int ath10k_mac_register(struct ath10k *ar)
goto err_dfs_detector_exit; 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; ar->hw->wiphy->cipher_suites = cipher_suites;
/* QCA988x and QCA6174 family chips do not support CCMP-256, GCMP-128 /* QCA988x and QCA6174 family chips do not support CCMP-256, GCMP-128
......
...@@ -119,6 +119,8 @@ struct wmi_ops { ...@@ -119,6 +119,8 @@ struct wmi_ops {
u32 value); u32 value);
struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar, struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg); 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, struct sk_buff *(*gen_beacon_dma)(struct ath10k *ar, u32 vdev_id,
const void *bcn, size_t bcn_len, const void *bcn, size_t bcn_len,
u32 bcn_paddr, bool dtim_zero, u32 bcn_paddr, bool dtim_zero,
...@@ -914,6 +916,26 @@ ath10k_wmi_scan_chan_list(struct ath10k *ar, ...@@ -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); 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 static inline int
ath10k_wmi_peer_assoc(struct ath10k *ar, ath10k_wmi_peer_assoc(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg) const struct wmi_peer_assoc_complete_arg *arg)
......
...@@ -1636,6 +1636,8 @@ ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar, ...@@ -1636,6 +1636,8 @@ ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
cmd->num_bssids = __cpu_to_le32(arg->n_bssids); cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
cmd->ie_len = __cpu_to_le32(arg->ie_len); cmd->ie_len = __cpu_to_le32(arg->ie_len);
cmd->num_probes = __cpu_to_le32(3); 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, /* FIXME: There are some scan flag inconsistencies across firmwares,
* e.g. WMI-TLV inverts the logic behind the following flag. * 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, ...@@ -2482,6 +2484,27 @@ ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
return skb; 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 * static struct sk_buff *
ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
const void *bcn, size_t bcn_len, const void *bcn, size_t bcn_len,
...@@ -3452,6 +3475,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = { ...@@ -3452,6 +3475,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = {
.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID, .stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID, .scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_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_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID, .pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID, .pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
...@@ -3820,6 +3844,7 @@ static const struct wmi_ops wmi_tlv_ops = { ...@@ -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_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_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_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_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm, .gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats, .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
......
...@@ -1706,6 +1706,15 @@ struct wmi_tlv_scan_chan_list_cmd { ...@@ -1706,6 +1706,15 @@ struct wmi_tlv_scan_chan_list_cmd {
__le32 num_scan_chans; __le32 num_scan_chans;
} __packed; } __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_tlv_start_scan_cmd {
struct wmi_start_scan_common common; struct wmi_start_scan_common common;
__le32 burst_duration_ms; __le32 burst_duration_ms;
...@@ -1714,6 +1723,8 @@ struct wmi_tlv_start_scan_cmd { ...@@ -1714,6 +1723,8 @@ struct wmi_tlv_start_scan_cmd {
__le32 num_ssids; __le32 num_ssids;
__le32 ie_len; __le32 ie_len;
__le32 num_probes; __le32 num_probes;
struct wmi_mac_addr mac_addr;
struct wmi_mac_addr mac_mask;
} __packed; } __packed;
struct wmi_tlv_vdev_start_cmd { struct wmi_tlv_vdev_start_cmd {
......
...@@ -42,6 +42,7 @@ static struct wmi_cmd_map wmi_cmd_map = { ...@@ -42,6 +42,7 @@ static struct wmi_cmd_map wmi_cmd_map = {
.stop_scan_cmdid = WMI_STOP_SCAN_CMDID, .stop_scan_cmdid = WMI_STOP_SCAN_CMDID,
.scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID, .scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID,
.scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_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_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID,
.pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID, .pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID,
.pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID, .pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID,
...@@ -207,6 +208,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { ...@@ -207,6 +208,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
.stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID, .stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID,
.scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID, .scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID,
.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, .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_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID,
.pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID, .pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID,
.pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_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 = { ...@@ -374,6 +376,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID, .stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID, .scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, .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_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID, .pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_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 = { ...@@ -541,6 +544,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
.stop_scan_cmdid = WMI_10_4_STOP_SCAN_CMDID, .stop_scan_cmdid = WMI_10_4_STOP_SCAN_CMDID,
.scan_chan_list_cmdid = WMI_10_4_SCAN_CHAN_LIST_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_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_regdomain_cmdid = WMI_10_4_PDEV_SET_REGDOMAIN_CMDID,
.pdev_set_channel_cmdid = WMI_10_4_PDEV_SET_CHANNEL_CMDID, .pdev_set_channel_cmdid = WMI_10_4_PDEV_SET_CHANNEL_CMDID,
.pdev_set_param_cmdid = WMI_10_4_PDEV_SET_PARAM_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 = { ...@@ -1338,6 +1342,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID, .stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID, .scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, .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_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID, .pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID, .pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
......
...@@ -791,6 +791,7 @@ struct wmi_cmd_map { ...@@ -791,6 +791,7 @@ struct wmi_cmd_map {
u32 stop_scan_cmdid; u32 stop_scan_cmdid;
u32 scan_chan_list_cmdid; u32 scan_chan_list_cmdid;
u32 scan_sch_prio_tbl_cmdid; u32 scan_sch_prio_tbl_cmdid;
u32 scan_prob_req_oui_cmdid;
u32 pdev_set_regdomain_cmdid; u32 pdev_set_regdomain_cmdid;
u32 pdev_set_channel_cmdid; u32 pdev_set_channel_cmdid;
u32 pdev_set_param_cmdid; u32 pdev_set_param_cmdid;
...@@ -3168,6 +3169,8 @@ struct wmi_start_scan_arg { ...@@ -3168,6 +3169,8 @@ struct wmi_start_scan_arg {
u16 channels[64]; u16 channels[64];
struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID]; struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID]; 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 */ /* scan control flags */
...@@ -3191,6 +3194,12 @@ struct wmi_start_scan_arg { ...@@ -3191,6 +3194,12 @@ struct wmi_start_scan_arg {
*/ */
#define WMI_SCAN_CONTINUE_ON_ERROR 0x80 #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 */ /* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */
#define WMI_SCAN_CLASS_MASK 0xFF000000 #define WMI_SCAN_CLASS_MASK 0xFF000000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment