diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index c26a553ea82a..eb50e7ed8c36 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -59,6 +59,16 @@ struct wlan_disconnect_info { bool from_ap; }; +/** + * struct sae_auth_retry - SAE auth retry Information + * @sae_auth_max_retry: Max number of sae auth retries + * @sae_auth: SAE auth frame information + */ +struct sae_auth_retry { + uint8_t sae_auth_max_retry; + struct wlan_ies sae_auth; +}; + /** * struct peer_mlme_priv_obj - peer MLME component object * @last_pn_valid if last PN is valid @@ -147,6 +157,7 @@ struct wlan_mlme_roam { * @vdev_stop_type: vdev stop type request * @roam_off_state: Roam offload state * @bigtk_vdev_support: BIGTK feature support for this vdev (SAP) + * @sae_auth_retry: SAE auth retry information */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -165,6 +176,7 @@ struct mlme_legacy_priv { uint32_t vdev_stop_type; struct wlan_mlme_roam mlme_roam; bool bigtk_vdev_support; + struct sae_auth_retry sae_retry; }; /** @@ -270,6 +282,22 @@ struct wlan_mlme_psoc_ext_obj *mlme_get_psoc_ext_obj_fl(struct wlan_objmgr_psoc const char *func, uint32_t line); +/** + * mlme_get_sae_auth_retry() - Get sae_auth_retry pointer + * @vdev: vdev pointer + * + * Return: Pointer to struct sae_auth_retry or NULL + */ +struct sae_auth_retry *mlme_get_sae_auth_retry(struct wlan_objmgr_vdev *vdev); + +/** + * mlme_free_sae_auth_retry() - Free the SAE auth info + * @vdev: vdev pointer + * + * Return: None + */ +void mlme_free_sae_auth_retry(struct wlan_objmgr_vdev *vdev); + /** * mlme_set_self_disconnect_ies() - Set diconnect IEs configured from userspace * @vdev: vdev pointer diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index 6969d77a2f5e..93b2fecc7b2a 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -2253,6 +2253,36 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc) return status; } +struct sae_auth_retry *mlme_get_sae_auth_retry(struct wlan_objmgr_vdev *vdev) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return NULL; + } + + return &mlme_priv->sae_retry; +} + +void mlme_free_sae_auth_retry(struct wlan_objmgr_vdev *vdev) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return; + } + + mlme_priv->sae_retry.sae_auth_max_retry = 0; + if (mlme_priv->sae_retry.sae_auth.data) + qdf_mem_free(mlme_priv->sae_retry.sae_auth.data); + mlme_priv->sae_retry.sae_auth.data = NULL; + mlme_priv->sae_retry.sae_auth.len = 0; +} + void mlme_set_self_disconnect_ies(struct wlan_objmgr_vdev *vdev, struct wlan_ies *ie) { diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index e6a6e34d2791..d8552b77afb0 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -973,6 +973,7 @@ QDF_STATUS vdevmgr_mlme_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme) mlme_free_self_disconnect_ies(vdev_mlme->vdev); mlme_free_peer_disconnect_ies(vdev_mlme->vdev); + mlme_free_sae_auth_retry(vdev_mlme->vdev); qdf_mem_free(vdev_mlme->ext_vdev_ptr); vdev_mlme->ext_vdev_ptr = NULL; diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c index 68c443b5b361..dd45f3b2da70 100644 --- a/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -338,6 +338,22 @@ static void lim_external_auth_add_pre_auth_node(struct mac_context *mac_ctx, lim_add_pre_auth_node(mac_ctx, auth_node); } +void lim_sae_auth_cleanup_retry(struct mac_context *mac_ctx, + uint8_t vdev_id) +{ + struct pe_session *pe_session; + + pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); + if (!pe_session) { + pe_err("session not found for given vdev_id %d", vdev_id); + return; + } + + pe_debug("sae auth cleanup for vdev_id %d", vdev_id); + lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER); + mlme_free_sae_auth_retry(pe_session->vdev); +} + /** * lim_process_sae_auth_frame()-Process SAE authentication frame * @mac_ctx: MAC context @@ -353,6 +369,7 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx, uint32_t frame_len; uint8_t *body_ptr; enum rxmgmt_flags rx_flags = RXMGMT_FLAG_NONE; + struct sae_auth_retry *sae_retry; mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); @@ -389,6 +406,12 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx, } } + sae_retry = mlme_get_sae_auth_retry(pe_session->vdev); + if (LIM_IS_STA_ROLE(pe_session) && sae_retry && + sae_retry->sae_auth.data) + lim_sae_auth_cleanup_retry(mac_ctx, + pe_session->vdev_id); + lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType, (uint8_t *)mac_hdr, frame_len + sizeof(tSirMacMgmtHdr), diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 5d22c8f8aba8..5a57511a3dc7 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1627,6 +1627,36 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct } } +static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx, + struct pe_session *session_entry) +{ + struct sae_auth_retry *sae_retry; + + sae_retry = mlme_get_sae_auth_retry(session_entry->vdev); + if (!(sae_retry && sae_retry->sae_auth.data)) { + pe_debug("sae auth frame is not buffered vdev id %d", + session_entry->vdev_id); + return; + } + + pe_debug("retry sae auth for seq num %d vdev id %d", + mac_ctx->mgmtSeqNum, session_entry->vdev_id); + lim_send_frame(mac_ctx, session_entry->vdev_id, + sae_retry->sae_auth.data, sae_retry->sae_auth.len); + + sae_retry->sae_auth_max_retry--; + /* Activate Auth Retry timer if max_retries are not done */ + if (!sae_retry->sae_auth_max_retry || (tx_timer_activate( + &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) != + TX_SUCCESS)) + goto free_and_deactivate_timer; + + return; + +free_and_deactivate_timer: + lim_sae_auth_cleanup_retry(mac_ctx, session_entry->vdev_id); +} + /** * lim_process_auth_retry_timer()- function to Retry Auth when auth timeout * occurs @@ -1639,15 +1669,19 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx) struct pe_session *session_entry; tAniAuthType auth_type; tLimTimers *lim_timers = &mac_ctx->lim.lim_timers; - uint16_t vdev_id = + uint16_t pe_session_id = lim_timers->g_lim_periodic_auth_retry_timer.sessionId; - session_entry = pe_find_session_by_session_id(mac_ctx, vdev_id); + session_entry = pe_find_session_by_session_id(mac_ctx, pe_session_id); if (!session_entry) { - pe_err("session does not exist for vdev_id: %d", vdev_id); + pe_err("session does not exist for pe_session_id: %d", + pe_session_id); return; } + /** For WPA3 SAE gLimAuthFailureTimer is not running hence + * we don't enter in below "if" block in case of wpa3 sae + */ if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer) && (session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) && (LIM_AUTH_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) { @@ -1684,12 +1718,14 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx) /* Activate Auth Retry timer */ if (tx_timer_activate (&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) - != TX_SUCCESS) { + != TX_SUCCESS) pe_err("could not activate Auth Retry failure timer"); - return; - } + + return; } - return; + + /* Auth retry time out for wpa3 sae */ + lim_handle_sae_auth_timeout(mac_ctx, session_entry); } /*** lim_process_auth_retry_timer() ***/ void lim_process_auth_failure_timeout(struct mac_context *mac_ctx) diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 6e0d802264b6..1afa113d07eb 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -5294,28 +5294,28 @@ error_delba: return qdf_status; } +#define WLAN_SAE_AUTH_TIMEOUT 1000 +#define WLAN_SAE_AUTH_RETRY 1 + /** * lim_tx_mgmt_frame() - Transmits Auth mgmt frame * @mac_ctx Pointer to Global MAC structure - * @mb_msg: Received message info + * @vdev_id: vdev id * @msg_len: Received message length * @packet: Packet to be transmitted * @frame: Received frame * * Return: None */ -static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, - struct sir_mgmt_msg *mb_msg, uint32_t msg_len, - void *packet, uint8_t *frame) +static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, uint8_t vdev_id, + uint32_t msg_len, void *packet, uint8_t *frame) { - tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data; + tpSirMacFrameCtl fc = (tpSirMacFrameCtl)frame; QDF_STATUS qdf_status; - uint8_t vdev_id = 0; struct pe_session *session; uint16_t auth_ack_status; enum rateid min_rid = RATEID_DEFAULT; - vdev_id = mb_msg->vdev_id; session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); if (!session) { cds_packet_free((void *)packet); @@ -5349,35 +5349,99 @@ static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, } } -void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx, - struct scheduler_msg *msg) +static void +lim_handle_sae_auth_retry(struct mac_context *mac_ctx, uint8_t vdev_id, + uint8_t *frame, uint32_t frame_len) +{ + struct pe_session *session; + struct sae_auth_retry *sae_retry; + + session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); + if (!session) { + pe_err("session not found for given vdev_id %d", + vdev_id); + return; + } + + sae_retry = mlme_get_sae_auth_retry(session->vdev); + if (!sae_retry) { + pe_err("sae retry pointer is NULL for vdev_id %d", + vdev_id); + return; + } + + if (sae_retry->sae_auth.data) + lim_sae_auth_cleanup_retry(mac_ctx, vdev_id); + + sae_retry->sae_auth.data = qdf_mem_malloc(frame_len); + if (!sae_retry->sae_auth.data) { + pe_err("failed to alloc memory for sae auth"); + return; + } + + pe_debug("SAE auth frame queued vdev_id %d seq_num %d", + vdev_id, mac_ctx->mgmtSeqNum); + qdf_mem_copy(sae_retry->sae_auth.data, frame, frame_len); + mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId = + session->peSessionId; + sae_retry->sae_auth.len = frame_len; + sae_retry->sae_auth_max_retry = WLAN_SAE_AUTH_RETRY; + + tx_timer_change( + &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer, + SYS_MS_TO_TICKS(WLAN_SAE_AUTH_TIMEOUT), 0); + /* Activate Auth Retry timer */ + if (tx_timer_activate( + &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) != + TX_SUCCESS) { + pe_err("failed to start periodic auth retry timer"); + lim_sae_auth_cleanup_retry(mac_ctx, vdev_id); + } +} + +void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf, + uint16_t buf_len) { - struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr; - uint32_t msg_len; - tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data; - uint8_t vdev_id; QDF_STATUS qdf_status; uint8_t *frame; void *packet; - tpSirMacMgmtHdr mac_hdr; + tpSirMacFrameCtl fc = (tpSirMacFrameCtl)buf; + tpSirMacMgmtHdr mac_hdr = (tpSirMacMgmtHdr)buf; - msg_len = mb_msg->msg_len - sizeof(*mb_msg); pe_debug("sending fc->type: %d fc->subType: %d", - fc->type, fc->subType); - - vdev_id = mb_msg->vdev_id; - mac_hdr = (tpSirMacMgmtHdr)mb_msg->data; + fc->type, fc->subType); lim_add_mgmt_seq_num(mac_ctx, mac_hdr); - - qdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame, - (void **)&packet); + qdf_status = cds_packet_alloc(buf_len, (void **)&frame, + (void **)&packet); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { pe_err("call to bufAlloc failed for AUTH frame"); return; } - qdf_mem_copy(frame, mb_msg->data, msg_len); - - lim_tx_mgmt_frame(mac_ctx, mb_msg, msg_len, packet, frame); + qdf_mem_copy(frame, buf, buf_len); + lim_tx_mgmt_frame(mac_ctx, vdev_id, buf_len, packet, frame); +} + +void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx, + struct scheduler_msg *msg) +{ + struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr; + uint32_t msg_len; + tpSirMacFrameCtl fc = (tpSirMacFrameCtl)mb_msg->data; + uint8_t vdev_id; + uint16_t auth_algo; + + msg_len = mb_msg->msg_len - sizeof(*mb_msg); + vdev_id = mb_msg->vdev_id; + + if (fc->subType == SIR_MAC_MGMT_AUTH) { + auth_algo = *(uint16_t *)(mb_msg->data + + sizeof(tSirMacMgmtHdr)); + if (auth_algo == eSIR_AUTH_TYPE_SAE) + lim_handle_sae_auth_retry(mac_ctx, vdev_id, + mb_msg->data, msg_len); + } + + lim_send_frame(mac_ctx, vdev_id, mb_msg->data, msg_len); } diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 453eff536ec5..03473d4e8475 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -803,6 +803,7 @@ void pe_delete_session(struct mac_context *mac_ctx, struct pe_session *session) QDF_MAC_ADDR_ARRAY(session->bssId)); lim_reset_bcn_probe_filter(mac_ctx, session); + lim_sae_auth_cleanup_retry(mac_ctx, session->vdev_id); /* Restore default failure timeout */ if (session->defaultAuthFailureTimeout) { diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 8f11393f5919..d83eb496cd3c 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -420,6 +420,17 @@ bool lim_fill_lim_assoc_ind_params( tpDphHashNode sta_ds, struct pe_session *session_entry); +/** + * lim_sae_auth_cleanup_retry() - API to cleanup sae auth frmae stored + * and deactivate the timer + * @mac_ctx: Pointer to mac context + * @vdev_id: vdev id + * + * Return: none + */ +void lim_sae_auth_cleanup_retry(struct mac_context *mac_ctx, + uint8_t vdev_id); + /** * lim_fill_sme_assoc_ind_params() - Initialize association indication * @mac_ctx: Pointer to Global MAC structure @@ -1220,6 +1231,18 @@ void lim_process_auth_failure_timeout(struct mac_context *mac_ctx); void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx, uint32_t msg_type); +/** + * lim_send_frame() - API to send frame + * @mac_ctx Pointer to Global MAC structure + * @vdev_id: vdev id + * @buf: Pointer to SAE auth retry frame + * @buf_len: length of frame + * + * Return: None + */ +void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf, + uint16_t buf_len); + /** * lim_send_mgmt_frame_tx() - Sends mgmt frame * @mac_ctx Pointer to Global MAC structure