Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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
+22 −0
Original line number Diff line number Diff line
@@ -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)
+25 −0
Original line number Diff line number Diff line
@@ -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,
+11 −0
Original line number Diff line number Diff line
@@ -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 {
+5 −0
Original line number Diff line number Diff line
@@ -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,
Loading