diff options
author | Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | 2012-04-09 19:21:20 +0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-04-09 19:33:07 +0400 |
commit | d97c121bb23d32ef631c553d2656f8ccf8349507 (patch) | |
tree | 5ed670bed75b13c29a41fca6eeef255e46f6d569 /drivers/net/wireless/ath/ath6kl/cfg80211.c | |
parent | df90b36940019a879d08bc5e8a20daa0c9fe0122 (diff) | |
download | linux-d97c121bb23d32ef631c553d2656f8ccf8349507.tar.xz |
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>
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/cfg80211.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 900993017d09..86d388f57708 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -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; |