ath6kl: Fix 4-way handshake failure in AP and P2P GO mode
RSN capability field of RSN IE which is generated (which is what really advertised in beacon/probe response) differs from the one generated in wpa_supplicant. This inconsistency in rsn IE results in 4-way handshake failure. To fix this, configure rsn capability used in wpa_supplicant in firmware using a new wmi command, WMI_SET_IE_CMDID. There is a bit (ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE) in fw_capabilities to advertise this support to driver. Signed-off-by: Subramania Sharma <sharmat@qca.qualcomm.com> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
df90b36940
commit
d97c121bb2
4 changed files with 107 additions and 0 deletions
|
@ -2548,6 +2548,52 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
|
||||
u8 *rsn_capab)
|
||||
{
|
||||
const u8 *rsn_ie;
|
||||
size_t rsn_ie_len;
|
||||
u16 cnt;
|
||||
|
||||
if (!beacon->tail)
|
||||
return -EINVAL;
|
||||
|
||||
rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, beacon->tail, beacon->tail_len);
|
||||
if (!rsn_ie)
|
||||
return -EINVAL;
|
||||
|
||||
rsn_ie_len = *(rsn_ie + 1);
|
||||
/* skip element id and length */
|
||||
rsn_ie += 2;
|
||||
|
||||
/* skip version, group cipher */
|
||||
if (rsn_ie_len < 6)
|
||||
return -EINVAL;
|
||||
rsn_ie += 6;
|
||||
rsn_ie_len -= 6;
|
||||
|
||||
/* skip pairwise cipher suite */
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
cnt = *((u16 *) rsn_ie);
|
||||
rsn_ie += (2 + cnt * 4);
|
||||
rsn_ie_len -= (2 + cnt * 4);
|
||||
|
||||
/* skip akm suite */
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
cnt = *((u16 *) rsn_ie);
|
||||
rsn_ie += (2 + cnt * 4);
|
||||
rsn_ie_len -= (2 + cnt * 4);
|
||||
|
||||
if (rsn_ie_len < 2)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(rsn_capab, rsn_ie, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_ap_settings *info)
|
||||
{
|
||||
|
@ -2560,6 +2606,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
struct wmi_connect_cmd p;
|
||||
int res;
|
||||
int i, ret;
|
||||
u16 rsn_capab = 0;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
|
||||
|
||||
|
@ -2700,6 +2747,23 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
vif->next_ch_type != NL80211_CHAN_NO_HT))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* Get the PTKSA replay counter in the RSN IE. Supplicant
|
||||
* will use the RSN IE in M3 message and firmware has to
|
||||
* advertise the same in beacon/probe response. Send
|
||||
* the complete RSN IE capability field to firmware
|
||||
*/
|
||||
if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *) &rsn_capab) &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
|
||||
ar->fw_capabilities)) {
|
||||
res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
WLAN_EID_RSN, WMI_RSN_IE_CAPB,
|
||||
(const u8 *) &rsn_capab,
|
||||
sizeof(rsn_capab));
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
|
|
@ -97,6 +97,9 @@ enum ath6kl_fw_capability {
|
|||
*/
|
||||
ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
|
||||
|
||||
/* Firmware has support to override rsn cap of rsn ie */
|
||||
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
|
||||
|
||||
/* this needs to be last */
|
||||
ATH6KL_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
|
|
@ -3221,6 +3221,29 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
|
|||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field,
|
||||
const u8 *ie_info, u8 ie_len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_set_ie_cmd *p;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "set_ie_cmd: ie_id=%u ie_ie_field=%u ie_len=%u\n",
|
||||
ie_id, ie_field, ie_len);
|
||||
p = (struct wmi_set_ie_cmd *) skb->data;
|
||||
p->ie_id = ie_id;
|
||||
p->ie_field = ie_field;
|
||||
p->ie_len = ie_len;
|
||||
if (ie_info && ie_len > 0)
|
||||
memcpy(p->ie_info, ie_info, ie_len);
|
||||
|
||||
return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IE_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
|
|
@ -426,6 +426,7 @@ enum wmi_cmd_id {
|
|||
WMI_SET_FRAMERATES_CMDID,
|
||||
WMI_SET_AP_PS_CMDID,
|
||||
WMI_SET_QOS_SUPP_CMDID,
|
||||
WMI_SET_IE_CMDID,
|
||||
|
||||
/* WMI_THIN_RESERVED_... mark the start and end
|
||||
* values for WMI_THIN_RESERVED command IDs. These
|
||||
|
@ -632,6 +633,11 @@ enum wmi_mgmt_frame_type {
|
|||
WMI_NUM_MGMT_FRAME
|
||||
};
|
||||
|
||||
enum wmi_ie_field_type {
|
||||
WMI_RSN_IE_CAPB = 0x1,
|
||||
WMI_IE_FULL = 0xFF, /* indicats full IE */
|
||||
};
|
||||
|
||||
/* WMI_CONNECT_CMDID */
|
||||
enum network_type {
|
||||
INFRA_NETWORK = 0x01,
|
||||
|
@ -1926,6 +1932,14 @@ struct wmi_set_appie_cmd {
|
|||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_set_ie_cmd {
|
||||
u8 ie_id;
|
||||
u8 ie_field; /* enum wmi_ie_field_type */
|
||||
u8 ie_len;
|
||||
u8 reserved;
|
||||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
/* Notify the WSC registration status to the target */
|
||||
#define WSC_REG_ACTIVE 1
|
||||
#define WSC_REG_INACTIVE 0
|
||||
|
@ -2536,6 +2550,9 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx,
|
|||
int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
|
||||
const u8 *ie, u8 ie_len);
|
||||
|
||||
int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field,
|
||||
const u8 *ie_info, u8 ie_len);
|
||||
|
||||
/* P2P */
|
||||
int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue