Merge "wlan: Mask unsupported rsn caps in host" into wlan-driver.lnx.1.0
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index be208ae..a52093c 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -2119,6 +2119,29 @@
}
#endif
+#define JOINT_MULTI_BAND_RSNA 0x01
+#define PEER_KEY_ENABLED 0x02
+#define AMSDU_CAPABLE 0x04
+#define AMSDU_REQUIRED 0x08
+#define PBAC 0x10
+#define EXT_KEY_ID 0x20
+#define OCVC 0x40
+#define RESERVED 0x80
+
+/**
+ * wlan_hdd_mask_unsupported_rsn_caps() - Mask unsupported RSN CAPs in RSN IE
+ * @pBuf: pointer to rsn_ie
+ * @ielen: rsn_ie len
+ *
+ * This function is used to point rsn cap element in rsn IE and mask the rsn
+ * caps bits which driver doesn't support.
+ *
+ * Return: None
+ */
+void
+wlan_hdd_mask_unsupported_rsn_caps(tANI_U8 *pBuf, tANI_S16 ielen);
+
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
#define nla_parse(a, b, c, d, e) nla_parse(a, b, c, d, e, NULL)
#define cfg80211_sched_scan_results(a) cfg80211_sched_scan_results(a, 0)
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 31ef7d3..97b1b97 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -16777,6 +16777,102 @@
return 0;
}
+static void framesntohs(v_U16_t *pOut,
+ v_U8_t *pIn,
+ unsigned char fMsb)
+{
+# if defined ( DOT11F_LITTLE_ENDIAN_HOST )
+ if ( !fMsb )
+ {
+ vos_mem_copy(( v_U16_t* )pOut, pIn, 2);
+ }
+ else
+ {
+ *pOut = ( v_U16_t )( *pIn << 8 ) | *( pIn + 1 );
+ }
+# else
+ if ( !fMsb )
+ {
+ *pOut = ( v_U16_t )( *pIn | ( *( pIn + 1 ) << 8 ) );
+ }
+ else
+ {
+ vos_mem_copy(( v_U16_t* )pOut, pIn, 2);
+ }
+# endif
+}
+
+void
+wlan_hdd_mask_unsupported_rsn_caps(tANI_U8 *pBuf, tANI_S16 ielen)
+{
+ u16 pwise_cipher_suite_count, akm_suite_cnt, mask = 0;
+ u8 *rsn_cap;
+
+ if (unlikely(ielen < 2)) {
+ return;
+ }
+
+ pBuf += 2;
+ ielen -= (tANI_U8)2;
+
+ if (unlikely(ielen < 4)) {
+ return;
+ }
+
+ pBuf += 4;
+ ielen -= (tANI_U8)4;
+
+ if (unlikely(ielen < 2)) {
+ return;
+ }
+
+ framesntohs(&pwise_cipher_suite_count, pBuf, 0);
+ pBuf += 2;
+ ielen -= (tANI_U8)2;
+
+ if (unlikely(ielen < pwise_cipher_suite_count * 4)) {
+ return;
+ }
+
+ if (!pwise_cipher_suite_count ||
+ pwise_cipher_suite_count > 4){
+ return;
+ }
+
+ pBuf += (pwise_cipher_suite_count * 4);
+ ielen -= (pwise_cipher_suite_count * 4);
+
+ if (unlikely(ielen < 2)) {
+ return;
+ }
+
+ framesntohs(&akm_suite_cnt, pBuf, 0);
+ pBuf += 2;
+ ielen -= (tANI_U8)2;
+
+ if (unlikely(ielen < akm_suite_cnt * 4)) {
+ return;
+ }
+
+ if (!akm_suite_cnt ||
+ akm_suite_cnt > 4){
+ return;
+ }
+
+ pBuf += (akm_suite_cnt * 4);
+ ielen -= (akm_suite_cnt * 4);
+
+ if (unlikely(ielen < 2)) {
+ return;
+ }
+
+ rsn_cap = pBuf;
+ mask = ~(JOINT_MULTI_BAND_RSNA | PEER_KEY_ENABLED | AMSDU_CAPABLE |
+ AMSDU_REQUIRED | PBAC | EXT_KEY_ID | OCVC | RESERVED);
+ rsn_cap[1] &= mask;
+
+ return;
+}
/*
* FUNCTION: wlan_hdd_cfg80211_set_ie
@@ -17089,6 +17185,8 @@
memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
+ wlan_hdd_mask_unsupported_rsn_caps(pWextState->WPARSNIE + 2,
+ eLen);
break;
/* Appending extended capabilities with Interworking or
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 1bb4e18..82d7336 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -2367,6 +2367,8 @@
memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2));
pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
pWextState->roamProfile.nRSNReqIELength = eLen + 2;
+ wlan_hdd_mask_unsupported_rsn_caps(pWextState->WPARSNIE + 2,
+ eLen);
break;
default: