mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 16:46:15 -04:00
qcacld-3.0: Send disconnect IEs received in deauth/disassoc to kernel
AP may send IEs in deauth/disassoc frames as part of disconnection. Extract the same and forward to kernel through cfg80211_disconnected(). Change-Id: I4ef339dcd1ecff64d6bed1de35621ecce5d8030a CRs-Fixed: 2481912
This commit is contained in:
parent
e2ee09491a
commit
d4e8725828
13 changed files with 193 additions and 15 deletions
|
|
@ -88,6 +88,8 @@ enum vdev_assoc_type {
|
|||
* @roam_invoke_params: Roam invoke params
|
||||
* @self_disconnect_ies: Disconnect IEs to be sent in deauth/disassoc frames
|
||||
* originated from driver
|
||||
* @peer_disconnect_ies: Disconnect IEs received in deauth/disassoc frames
|
||||
* from peer
|
||||
*/
|
||||
struct mlme_legacy_priv {
|
||||
bool chan_switch_in_progress;
|
||||
|
|
@ -101,6 +103,7 @@ struct mlme_legacy_priv {
|
|||
uint8_t sta_dynamic_oce_value;
|
||||
struct mlme_roam_after_data_stall roam_invoke_params;
|
||||
struct wlan_ies self_disconnect_ies;
|
||||
struct wlan_ies peer_disconnect_ies;
|
||||
};
|
||||
|
||||
#ifndef CRYPTO_SET_KEY_CONVERGED
|
||||
|
|
@ -308,4 +311,30 @@ void mlme_free_self_disconnect_ies(struct wlan_objmgr_vdev *vdev);
|
|||
* Return: Returns a pointer to the self disconnect IEs present in vdev object
|
||||
*/
|
||||
struct wlan_ies *mlme_get_self_disconnect_ies(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
/**
|
||||
* mlme_set_peer_disconnect_ies() - Cache disconnect IEs received from peer
|
||||
* @vdev: vdev pointer
|
||||
* @ie: pointer for disconnect IEs
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void mlme_set_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_ies *ie);
|
||||
|
||||
/**
|
||||
* mlme_free_peer_disconnect_ies() - Free the peer diconnect IEs
|
||||
* @vdev: vdev pointer
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void mlme_free_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
/**
|
||||
* mlme_get_peer_disconnect_ies() - Get diconnect IEs from vdev object
|
||||
* @vdev: vdev pointer
|
||||
*
|
||||
* Return: Returns a pointer to the peer disconnect IEs present in vdev object
|
||||
*/
|
||||
struct wlan_ies *mlme_get_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2435,3 +2435,76 @@ struct wlan_ies *mlme_get_self_disconnect_ies(struct wlan_objmgr_vdev *vdev)
|
|||
|
||||
return &mlme_priv->self_disconnect_ies;
|
||||
}
|
||||
|
||||
void mlme_set_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_ies *ie)
|
||||
{
|
||||
struct vdev_mlme_obj *vdev_mlme;
|
||||
struct mlme_legacy_priv *mlme_priv;
|
||||
|
||||
if (!ie || !ie->len || !ie->data) {
|
||||
mlme_legacy_debug("disocnnect IEs are NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
|
||||
if (!vdev_mlme) {
|
||||
mlme_legacy_err("vdev component object is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
mlme_priv = vdev_mlme->ext_vdev_ptr;
|
||||
|
||||
if (mlme_priv->peer_disconnect_ies.data) {
|
||||
qdf_mem_free(mlme_priv->peer_disconnect_ies.data);
|
||||
mlme_priv->peer_disconnect_ies.len = 0;
|
||||
}
|
||||
|
||||
mlme_priv->peer_disconnect_ies.data = qdf_mem_malloc(ie->len);
|
||||
if (!mlme_priv->peer_disconnect_ies.data)
|
||||
return;
|
||||
|
||||
qdf_mem_copy(mlme_priv->peer_disconnect_ies.data, ie->data, ie->len);
|
||||
mlme_priv->peer_disconnect_ies.len = ie->len;
|
||||
|
||||
mlme_legacy_debug("peer disconnect IEs");
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_DEBUG,
|
||||
mlme_priv->peer_disconnect_ies.data,
|
||||
mlme_priv->peer_disconnect_ies.len);
|
||||
}
|
||||
|
||||
void mlme_free_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct vdev_mlme_obj *vdev_mlme;
|
||||
struct mlme_legacy_priv *mlme_priv;
|
||||
|
||||
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
|
||||
if (!vdev_mlme) {
|
||||
mlme_legacy_err("vdev component object is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
mlme_priv = vdev_mlme->ext_vdev_ptr;
|
||||
|
||||
if (mlme_priv->peer_disconnect_ies.data) {
|
||||
qdf_mem_free(mlme_priv->peer_disconnect_ies.data);
|
||||
mlme_priv->peer_disconnect_ies.data = NULL;
|
||||
mlme_priv->peer_disconnect_ies.len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct wlan_ies *mlme_get_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct vdev_mlme_obj *vdev_mlme;
|
||||
struct mlme_legacy_priv *mlme_priv;
|
||||
|
||||
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
|
||||
if (!vdev_mlme) {
|
||||
mlme_legacy_err("vdev component object is NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mlme_priv = vdev_mlme->ext_vdev_ptr;
|
||||
|
||||
return &mlme_priv->peer_disconnect_ies;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -828,6 +828,7 @@ QDF_STATUS vdevmgr_mlme_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme)
|
|||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
mlme_free_self_disconnect_ies(vdev_mlme->vdev);
|
||||
mlme_free_peer_disconnect_ies(vdev_mlme->vdev);
|
||||
qdf_mem_free(vdev_mlme->ext_vdev_ptr);
|
||||
vdev_mlme->ext_vdev_ptr = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -1709,6 +1709,7 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
|
|||
uint8_t sta_id;
|
||||
bool sendDisconInd = true;
|
||||
mac_handle_t mac_handle;
|
||||
struct wlan_ies disconnect_ies = {0};
|
||||
|
||||
if (!dev) {
|
||||
hdd_err("net_dev is released return");
|
||||
|
|
@ -1771,6 +1772,12 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
|
|||
* by kernel
|
||||
*/
|
||||
if (sendDisconInd) {
|
||||
if (roam_info && roam_info->disconnect_ies) {
|
||||
disconnect_ies.data =
|
||||
roam_info->disconnect_ies->data;
|
||||
disconnect_ies.len =
|
||||
roam_info->disconnect_ies->len;
|
||||
}
|
||||
/*
|
||||
* To avoid wpa_supplicant sending "HANGED" CMD
|
||||
* to ICS UI.
|
||||
|
|
@ -1782,12 +1789,15 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
|
|||
roam_info->rxRssi);
|
||||
wlan_hdd_cfg80211_indicate_disconnect(
|
||||
dev, false,
|
||||
roam_info->reasonCode);
|
||||
roam_info->reasonCode,
|
||||
disconnect_ies.data,
|
||||
disconnect_ies.len);
|
||||
} else {
|
||||
wlan_hdd_cfg80211_indicate_disconnect(
|
||||
dev, false,
|
||||
WLAN_REASON_UNSPECIFIED
|
||||
);
|
||||
WLAN_REASON_UNSPECIFIED,
|
||||
disconnect_ies.data,
|
||||
disconnect_ies.len);
|
||||
}
|
||||
|
||||
hdd_debug("sent disconnected event to nl80211, reason code %d",
|
||||
|
|
|
|||
|
|
@ -18638,7 +18638,7 @@ disconnected:
|
|||
*/
|
||||
hdd_debug("Send disconnected event to userspace");
|
||||
wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true,
|
||||
WLAN_REASON_UNSPECIFIED);
|
||||
WLAN_REASON_UNSPECIFIED, NULL, 0);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -445,20 +445,26 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter);
|
|||
|
||||
#if defined(CFG80211_DISCONNECTED_V2) || \
|
||||
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
|
||||
static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev,
|
||||
bool locally_generated,
|
||||
int reason)
|
||||
static inline void
|
||||
wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev,
|
||||
bool locally_generated,
|
||||
int reason,
|
||||
uint8_t *disconnect_ies,
|
||||
uint16_t disconnect_ies_len)
|
||||
{
|
||||
cfg80211_disconnected(dev, reason, NULL, 0,
|
||||
locally_generated, GFP_KERNEL);
|
||||
cfg80211_disconnected(dev, reason, disconnect_ies, disconnect_ies_len,
|
||||
locally_generated, GFP_KERNEL);
|
||||
}
|
||||
#else
|
||||
static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev,
|
||||
bool locally_generated,
|
||||
int reason)
|
||||
static inline void
|
||||
wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev,
|
||||
bool locally_generated,
|
||||
int reason,
|
||||
uint8_t *disconnect_ies,
|
||||
uint16_t disconnect_ies_len)
|
||||
{
|
||||
cfg80211_disconnected(dev, reason, NULL, 0,
|
||||
GFP_KERNEL);
|
||||
cfg80211_disconnected(dev, reason, disconnect_ies, disconnect_ies_len,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -6750,7 +6750,8 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx)
|
|||
/* indicate disconnected event to nl80211 */
|
||||
wlan_hdd_cfg80211_indicate_disconnect(
|
||||
adapter->dev, false,
|
||||
WLAN_REASON_UNSPECIFIED);
|
||||
WLAN_REASON_UNSPECIFIED,
|
||||
NULL, 0);
|
||||
} else if (eConnectionState_Connecting == conn_state) {
|
||||
/*
|
||||
* Indicate connect failure to supplicant if we
|
||||
|
|
|
|||
|
|
@ -4827,3 +4827,28 @@ void lim_send_sme_tsm_ie_ind(struct mac_context *mac,
|
|||
lim_sys_process_mmh_msg_api(mac, &msg);
|
||||
}
|
||||
#endif /* FEATURE_WLAN_ESE */
|
||||
|
||||
void lim_extract_ies_from_deauth_disassoc(struct pe_session *session,
|
||||
uint8_t *deauth_disassoc_frame,
|
||||
uint16_t deauth_disassoc_frame_len)
|
||||
{
|
||||
uint16_t reason_code, ie_offset;
|
||||
struct wlan_ies ie;
|
||||
|
||||
if (!session) {
|
||||
pe_err("NULL session");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the offset of IEs */
|
||||
ie_offset = sizeof(struct wlan_frame_hdr) + sizeof(reason_code);
|
||||
|
||||
if (!deauth_disassoc_frame || deauth_disassoc_frame_len <= ie_offset)
|
||||
return;
|
||||
|
||||
ie.data = deauth_disassoc_frame + ie_offset;
|
||||
ie.len = deauth_disassoc_frame_len - ie_offset;
|
||||
|
||||
mlme_set_peer_disconnect_ies(session->vdev, &ie);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -281,4 +281,21 @@ QDF_STATUS lim_populate_vht_mcs_set(struct mac_context *mac_ctx,
|
|||
struct pe_session *session_entry,
|
||||
uint8_t nss);
|
||||
|
||||
/**
|
||||
* lim_extract_ies_from_deauth_disassoc() - Extract IEs from deauth/disassoc
|
||||
*
|
||||
* @session: PE session entry
|
||||
* @deauth_disassoc_frame: A pointer to the deauth/disconnect frame buffer
|
||||
* received from WMA.
|
||||
* @deauth_disassoc_frame_leni: Length of the deauth/disconnect frame.
|
||||
*
|
||||
* This function receives deauth/disassoc frame from header. It extracts
|
||||
* the IEs(tagged params) from the frame and caches in vdev object.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void
|
||||
lim_extract_ies_from_deauth_disassoc(struct pe_session *session,
|
||||
uint8_t *deauth_disassoc_frame,
|
||||
uint16_t deauth_disassoc_frame_len);
|
||||
#endif /* __LIM_ASSOC_UTILS_H */
|
||||
|
|
|
|||
|
|
@ -314,6 +314,8 @@ lim_process_deauth_frame(struct mac_context *mac, uint8_t *pRxPacketInfo,
|
|||
}
|
||||
}
|
||||
|
||||
lim_extract_ies_from_deauth_disassoc(pe_session, (uint8_t *)pHdr,
|
||||
WMA_GET_RX_MPDU_LEN(pRxPacketInfo));
|
||||
lim_perform_deauth(mac, pe_session, reasonCode, pHdr->sa,
|
||||
frame_rssi);
|
||||
|
||||
|
|
|
|||
|
|
@ -310,6 +310,8 @@ lim_process_disassoc_frame(struct mac_context *mac, uint8_t *pRxPacketInfo,
|
|||
|
||||
} /* if (sta->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) */
|
||||
|
||||
lim_extract_ies_from_deauth_disassoc(pe_session, (uint8_t *)pHdr,
|
||||
WMA_GET_RX_MPDU_LEN(pRxPacketInfo));
|
||||
lim_perform_disassoc(mac, frame_rssi, reasonCode,
|
||||
pe_session, pHdr->sa);
|
||||
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,7 @@ struct csr_roam_info {
|
|||
#endif
|
||||
struct assoc_ind *owe_pending_assoc_ind;
|
||||
uint16_t roam_reason;
|
||||
struct wlan_ies *disconnect_ies;
|
||||
};
|
||||
|
||||
typedef struct sSirSmeAssocIndToUpperLayerCnf {
|
||||
|
|
|
|||
|
|
@ -9733,6 +9733,7 @@ csr_roam_send_disconnect_done_indication(struct mac_context *mac_ctx,
|
|||
(struct sir_sme_discon_done_ind *)(msg_ptr);
|
||||
struct csr_roam_info *roam_info;
|
||||
struct csr_roam_session *session;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
|
||||
roam_info = qdf_mem_malloc(sizeof(*roam_info));
|
||||
if (!roam_info)
|
||||
|
|
@ -9751,10 +9752,20 @@ csr_roam_send_disconnect_done_indication(struct mac_context *mac_ctx,
|
|||
roam_info->rx_rate = mac_ctx->peer_rxrate;
|
||||
roam_info->disassoc_reason = discon_ind->reason_code;
|
||||
roam_info->rx_mc_bc_cnt = mac_ctx->rx_mc_bc_cnt;
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
|
||||
discon_ind->session_id,
|
||||
WLAN_LEGACY_SME_ID);
|
||||
if (vdev)
|
||||
roam_info->disconnect_ies =
|
||||
mlme_get_peer_disconnect_ies(vdev);
|
||||
|
||||
csr_roam_call_callback(mac_ctx, discon_ind->session_id,
|
||||
roam_info, 0, eCSR_ROAM_LOSTLINK,
|
||||
eCSR_ROAM_RESULT_DISASSOC_IND);
|
||||
if (vdev) {
|
||||
mlme_free_peer_disconnect_ies(vdev);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
|
||||
}
|
||||
session = CSR_GET_SESSION(mac_ctx, discon_ind->session_id);
|
||||
if (session &&
|
||||
!CSR_IS_INFRA_AP(&session->connectedProfile))
|
||||
|
|
|
|||
Loading…
Reference in a new issue