1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "cds_api.h"
21 #include "wni_cfg.h"
22 #include "ani_global.h"
23 #include "sir_api.h"
24 #include "sir_params.h"
25 #include "cfg_ucfg_api.h"
26 #include "sch_api.h"
27 #include "utils_api.h"
28 #include "lim_utils.h"
29 #include "lim_assoc_utils.h"
30 #include "lim_prop_exts_utils.h"
31 #include "lim_security_utils.h"
32 #include "lim_send_messages.h"
33 #include "lim_send_messages.h"
34 #include "lim_session_utils.h"
35 #include <lim_ft.h>
36 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
37 #include "host_diag_core_log.h"
38 #endif
39 #include "wma_if.h"
40 #include "wma.h"
41 #include "wlan_reg_services_api.h"
42 #include "lim_process_fils.h"
43 #include "wlan_mlme_public_struct.h"
44 #include "../../core/src/vdev_mgr_ops.h"
45 #include "wlan_pmo_ucfg_api.h"
46 #include "wlan_cp_stats_utils_api.h"
47 #include "wlan_objmgr_vdev_obj.h"
48 #include <wlan_cm_api.h>
49 #include <lim_mlo.h>
50 #include "wlan_mlo_mgr_peer.h"
51 #include <son_api.h>
52 #include "wifi_pos_pasn_api.h"
53 #include "rrm_api.h"
54 #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
55 
56 static void lim_process_mlm_auth_req(struct mac_context *, uint32_t *);
57 static void lim_process_mlm_assoc_req(struct mac_context *, uint32_t *);
58 static void lim_process_mlm_disassoc_req(struct mac_context *, uint32_t *);
59 
60 /* MLM Timeout event handler templates */
61 static void lim_process_auth_rsp_timeout(struct mac_context *, uint32_t);
62 static void lim_process_periodic_join_probe_req_timer(struct mac_context *);
63 static void lim_process_auth_retry_timer(struct mac_context *);
64 
lim_fill_status_code(uint8_t frame_type,enum tx_ack_status ack_status,enum wlan_status_code * proto_status_code)65 static void lim_fill_status_code(uint8_t frame_type,
66 				 enum tx_ack_status ack_status,
67 				 enum wlan_status_code *proto_status_code)
68 {
69 	if (frame_type == SIR_MAC_MGMT_AUTH) {
70 		switch (ack_status) {
71 		case LIM_TX_FAILED:
72 			*proto_status_code = STATUS_AUTH_TX_FAIL;
73 			break;
74 		case LIM_ACK_RCD_FAILURE:
75 		case LIM_ACK_NOT_RCD:
76 			*proto_status_code = STATUS_AUTH_NO_ACK_RECEIVED;
77 			break;
78 		case LIM_ACK_RCD_SUCCESS:
79 			*proto_status_code = STATUS_AUTH_NO_RESP_RECEIVED;
80 			break;
81 		default:
82 			*proto_status_code = STATUS_UNSPECIFIED_FAILURE;
83 		}
84 	} else if (frame_type == SIR_MAC_MGMT_ASSOC_RSP) {
85 		switch (ack_status) {
86 		case LIM_TX_FAILED:
87 			*proto_status_code = STATUS_ASSOC_TX_FAIL;
88 			break;
89 		case LIM_ACK_RCD_FAILURE:
90 		case LIM_ACK_NOT_RCD:
91 			*proto_status_code = STATUS_ASSOC_NO_ACK_RECEIVED;
92 			break;
93 		case LIM_ACK_RCD_SUCCESS:
94 			*proto_status_code = STATUS_ASSOC_NO_RESP_RECEIVED;
95 			break;
96 		default:
97 			*proto_status_code = STATUS_UNSPECIFIED_FAILURE;
98 		}
99 	}
100 }
101 
lim_process_rrm_sta_stats_rsp_timeout(struct mac_context * mac)102 void lim_process_rrm_sta_stats_rsp_timeout(struct mac_context *mac)
103 {
104 	struct pe_session *session;
105 	tSirMacRadioMeasureReport rrm_report;
106 	QDF_STATUS status;
107 	uint8_t index;
108 	tpRRMReq pcurrent_req = NULL;
109 	tRrmRetStatus rrm_status;
110 
111 	session = pe_find_session_by_session_id(mac,
112 		mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId);
113 	if (!session) {
114 		pe_err("Session does not exist for given session id %d",
115 		       mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId);
116 		rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
117 		return;
118 	}
119 
120 	pe_warn("STA STATS RSP timeout vdev_id %d", session->vdev_id);
121 	index = mac->rrm.rrmPEContext.rrm_sta_stats.index;
122 	pcurrent_req = mac->rrm.rrmPEContext.pCurrentReq[index];
123 	if (!pcurrent_req) {
124 		pe_err("Current request is NULL for index %d", index);
125 		qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
126 			     sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
127 		return;
128 	}
129 
130 	if (!mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count) {
131 		pe_err("response not received for previous req");
132 		rrm_status = eRRM_INCAPABLE;
133 		goto err;
134 	}
135 
136 	rrm_report = mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
137 	switch (rrm_report.report.statistics_report.group_id) {
138 	/*
139 	 * For Counter stats and Mac stats some stats will be received
140 	 * via FW and some via DP. So, same handling is required for both
141 	 * cases.
142 	 */
143 	case STA_STAT_GROUP_ID_COUNTER_STATS:
144 	case STA_STAT_GROUP_ID_MAC_STATS:
145 		status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
146 		if (QDF_IS_STATUS_ERROR(status))
147 			pe_err("failed to deregister callback %d", status);
148 
149 		status =
150 			rrm_send_sta_stats_req(
151 				mac, session,
152 				mac->rrm.rrmPEContext.rrm_sta_stats.peer);
153 		if (QDF_IS_STATUS_ERROR(status)) {
154 			pe_err("fail to send stats req");
155 			rrm_status = eRRM_FAILURE;
156 			goto err;
157 		}
158 		break;
159 	case STA_STAT_GROUP_ID_DELAY_STATS:
160 		/* TOdo: fetch from scan ie */
161 		break;
162 	}
163 	return;
164 err:
165 	rrm_process_rrm_sta_stats_request_failure(
166 		mac, session, mac->rrm.rrmPEContext.rrm_sta_stats.peer,
167 		rrm_status, mac->rrm.rrmPEContext.rrm_sta_stats.index);
168 	rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
169 }
170 
lim_process_sae_auth_timeout(struct mac_context * mac_ctx)171 void lim_process_sae_auth_timeout(struct mac_context *mac_ctx)
172 {
173 	struct pe_session *session;
174 	enum wlan_status_code proto_status_code;
175 
176 	session = pe_find_session_by_session_id(mac_ctx,
177 			mac_ctx->lim.lim_timers.sae_auth_timer.sessionId);
178 	if (!session) {
179 		pe_err("Session does not exist for given session id");
180 		return;
181 	}
182 
183 	pe_warn("SAE auth timeout sessionid %d mlmstate %X SmeState %X",
184 		session->peSessionId, session->limMlmState,
185 		session->limSmeState);
186 
187 	switch (session->limMlmState) {
188 	case eLIM_MLM_WT_SAE_AUTH_STATE:
189 		lim_fill_status_code(SIR_MAC_MGMT_AUTH,
190 				     mac_ctx->auth_ack_status,
191 				     &proto_status_code);
192 		/*
193 		 * SAE authentication is not completed. Restore from
194 		 * auth state.
195 		 */
196 		if ((session->opmode == QDF_STA_MODE) ||
197 		    (session->opmode == QDF_P2P_CLIENT_MODE))
198 			lim_restore_from_auth_state(mac_ctx,
199 				eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
200 				proto_status_code, session);
201 		break;
202 	default:
203 		/* SAE authentication is timed out in unexpected state */
204 		pe_err("received unexpected SAE auth timeout in state %X",
205 			session->limMlmState);
206 		lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
207 		break;
208 	}
209 }
210 
211 /**
212  * lim_process_mlm_req_messages() - process mlm request messages
213  * @mac_ctx: global MAC context
214  * @msg: mlm request message
215  *
216  * This function is called by lim_post_mlm_message(). This
217  * function handles MLM primitives invoked by SME.
218  * Depending on the message type, corresponding function will be
219  * called.
220  * ASSUMPTIONS:
221  * 1. Upon receiving Beacon in WT_JOIN_STATE, MLM module invokes
222  *    APIs exposed by Beacon Processing module for setting parameters
223  *    at MAC hardware.
224  * 2. If attempt to Reassociate with an AP fails, link with current
225  *    AP is restored back.
226  *
227  * Return: None
228  */
lim_process_mlm_req_messages(struct mac_context * mac_ctx,struct scheduler_msg * msg)229 void lim_process_mlm_req_messages(struct mac_context *mac_ctx,
230 				  struct scheduler_msg *msg)
231 {
232 	switch (msg->type) {
233 	case LIM_MLM_AUTH_REQ:
234 		lim_process_mlm_auth_req(mac_ctx, msg->bodyptr);
235 		break;
236 	case LIM_MLM_ASSOC_REQ:
237 		lim_process_mlm_assoc_req(mac_ctx, msg->bodyptr);
238 		break;
239 	case LIM_MLM_DISASSOC_REQ:
240 		lim_process_mlm_disassoc_req(mac_ctx, msg->bodyptr);
241 		break;
242 	case SIR_LIM_JOIN_FAIL_TIMEOUT:
243 		lim_process_join_failure_timeout(mac_ctx);
244 		break;
245 	case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT:
246 		lim_process_periodic_join_probe_req_timer(mac_ctx);
247 		break;
248 	case SIR_LIM_AUTH_FAIL_TIMEOUT:
249 		lim_process_auth_failure_timeout(mac_ctx);
250 		break;
251 	case SIR_LIM_AUTH_RSP_TIMEOUT:
252 		lim_process_auth_rsp_timeout(mac_ctx, msg->bodyval);
253 		break;
254 	case SIR_LIM_ASSOC_FAIL_TIMEOUT:
255 		lim_process_assoc_failure_timeout(mac_ctx, msg->bodyval);
256 		break;
257 	case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
258 		lim_process_ft_preauth_rsp_timeout(mac_ctx);
259 		break;
260 	case SIR_LIM_DISASSOC_ACK_TIMEOUT:
261 		lim_process_disassoc_ack_timeout(mac_ctx);
262 		break;
263 	case SIR_LIM_AUTH_RETRY_TIMEOUT:
264 		lim_process_auth_retry_timer(mac_ctx);
265 		break;
266 	case SIR_LIM_AUTH_SAE_TIMEOUT:
267 		lim_process_sae_auth_timeout(mac_ctx);
268 		break;
269 	case SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT:
270 		lim_process_rrm_sta_stats_rsp_timeout(mac_ctx);
271 		break;
272 	case LIM_MLM_TSPEC_REQ:
273 	default:
274 		break;
275 	} /* switch (msg->type) */
276 }
277 
update_rmfEnabled(struct bss_params * addbss_param,struct pe_session * session)278 static void update_rmfEnabled(struct bss_params *addbss_param,
279 			      struct pe_session *session)
280 {
281 	addbss_param->rmfEnabled = session->limRmfEnabled;
282 }
283 
284 /**
285  * lim_mlm_add_bss() - HAL interface for WMA_ADD_BSS_REQ
286  * @mac_ctx: global MAC context
287  * @mlm_start_req: MLM start request
288  * @session: PE session entry
289  *
290  * Package WMA_ADD_BSS_REQ to HAL, in order to start a BSS
291  *
292  * Return: eSIR_SME_SUCCESS on success, other error codes otherwise
293  */
294 tSirResultCodes
lim_mlm_add_bss(struct mac_context * mac_ctx,tLimMlmStartReq * mlm_start_req,struct pe_session * session)295 lim_mlm_add_bss(struct mac_context *mac_ctx,
296 		tLimMlmStartReq *mlm_start_req, struct pe_session *session)
297 {
298 	struct vdev_mlme_obj *mlme_obj;
299 	struct wlan_objmgr_vdev *vdev = session->vdev;
300 	uint8_t vdev_id = session->vdev_id;
301 	QDF_STATUS status = QDF_STATUS_SUCCESS;
302 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
303 	struct bss_params *addbss_param = NULL;
304 
305 	if (!wma)
306 		return eSIR_SME_INVALID_PARAMETERS;
307 
308 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
309 	if (!mlme_obj) {
310 		pe_err("vdev component object is NULL");
311 		return eSIR_SME_INVALID_PARAMETERS;
312 	}
313 
314 	qdf_mem_copy(mlme_obj->mgmt.generic.bssid, mlm_start_req->bssId,
315 		     QDF_MAC_ADDR_SIZE);
316 	if (lim_is_session_he_capable(session)) {
317 		lim_decide_he_op(mac_ctx, &mlme_obj->proto.he_ops_info.he_ops,
318 				 session);
319 		lim_update_usr_he_cap(mac_ctx, session);
320 	}
321 
322 #ifdef WLAN_FEATURE_11BE
323 	if (lim_is_session_eht_capable(session)) {
324 		lim_decide_eht_op(mac_ctx,
325 				  &mlme_obj->proto.eht_ops_info.eht_ops,
326 				  session);
327 		lim_update_usr_eht_cap(mac_ctx, session);
328 	}
329 #endif
330 
331 	/* Set a new state for MLME */
332 	session->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_STATE;
333 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
334 			 session->limMlmState));
335 
336 	status = lim_pre_vdev_start(mac_ctx, mlme_obj, session);
337 	if (QDF_IS_STATUS_ERROR(status))
338 		goto send_fail_resp;
339 
340 	 addbss_param = qdf_mem_malloc(sizeof(struct bss_params));
341 	if (!addbss_param)
342 		goto send_fail_resp;
343 
344 	addbss_param->vhtCapable = mlm_start_req->htCapable;
345 	addbss_param->htCapable = session->vhtCapability;
346 	addbss_param->ch_width = session->ch_width;
347 	update_rmfEnabled(addbss_param, session);
348 	addbss_param->staContext.fShortGI20Mhz =
349 		lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_20MHZ, session);
350 	addbss_param->staContext.fShortGI40Mhz =
351 		lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_40MHZ, session);
352 	status = wma_pre_vdev_start_setup(vdev_id, addbss_param);
353 	qdf_mem_free(addbss_param);
354 	if (QDF_IS_STATUS_ERROR(status))
355 		goto send_fail_resp;
356 
357 	if (session->wps_state == SAP_WPS_DISABLED)
358 		ucfg_pmo_disable_wakeup_event(wma->psoc, vdev_id,
359 					      WOW_PROBE_REQ_WPS_IE_EVENT);
360 	status = wma_vdev_pre_start(vdev_id, false);
361 	if (QDF_IS_STATUS_ERROR(status))
362 		goto peer_cleanup;
363 	status = vdev_mgr_start_send(mlme_obj, false);
364 	if (QDF_IS_STATUS_ERROR(status))
365 		goto peer_cleanup;
366 	wma_post_vdev_start_setup(vdev_id);
367 
368 	return eSIR_SME_SUCCESS;
369 
370 peer_cleanup:
371 	wma_remove_bss_peer_on_failure(wma, vdev_id);
372 send_fail_resp:
373 	wma_send_add_bss_resp(wma, vdev_id, QDF_STATUS_E_FAILURE);
374 
375 	return eSIR_SME_SUCCESS;
376 }
377 
lim_process_mlm_start_req(struct mac_context * mac_ctx,tLimMlmStartReq * mlm_start_req)378 void lim_process_mlm_start_req(struct mac_context *mac_ctx,
379 			       tLimMlmStartReq *mlm_start_req)
380 {
381 	tLimMlmStartCnf mlm_start_cnf;
382 	struct pe_session *session = NULL;
383 
384 	if (!mlm_start_req) {
385 		pe_err("Buffer is Pointing to NULL");
386 		return;
387 	}
388 
389 	session = pe_find_session_by_session_id(mac_ctx,
390 				mlm_start_req->sessionId);
391 	if (!session) {
392 		pe_err("Session Does not exist for given sessionID");
393 		mlm_start_cnf.resultCode = eSIR_SME_REFUSED;
394 		goto end;
395 	}
396 
397 	if (session->limMlmState != eLIM_MLM_IDLE_STATE) {
398 		/*
399 		 * Should not have received Start req in states other than idle.
400 		 * Return Start confirm with failure code.
401 		 */
402 		pe_err("received unexpected MLM_START_REQ in state %X",
403 			session->limMlmState);
404 		lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
405 		mlm_start_cnf.resultCode =
406 				eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
407 		goto end;
408 	}
409 
410 	mlm_start_cnf.resultCode =
411 		lim_mlm_add_bss(mac_ctx, mlm_start_req, session);
412 
413 end:
414 	/* Update PE session Id */
415 	mlm_start_cnf.sessionId = mlm_start_req->sessionId;
416 
417 	/*
418 	 * Respond immediately to LIM, only if MLME has not been
419 	 * successfully able to send WMA_ADD_BSS_REQ to HAL.
420 	 * Else, LIM_MLM_START_CNF will be sent after receiving
421 	 * WMA_ADD_BSS_RSP from HAL
422 	 */
423 	if (eSIR_SME_SUCCESS != mlm_start_cnf.resultCode)
424 		lim_send_start_bss_confirm(mac_ctx, &mlm_start_cnf);
425 }
426 
427 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
428 void
lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context * mac,struct wlan_objmgr_vdev * vdev)429 lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context *mac,
430 					      struct wlan_objmgr_vdev *vdev)
431 {
432 	if (!mac) {
433 		pe_err("Mac ctx is NULL");
434 		return;
435 	}
436 
437 	/*
438 	 * If PASN peer delete all command to firmware timedout, then
439 	 * the PASN peers will not be cleaned up. So cleanup the
440 	 * objmgr peers from here and reset the peer delete all in
441 	 * progress flag.
442 	 */
443 	if (wifi_pos_get_pasn_peer_count(vdev))
444 		wifi_pos_cleanup_pasn_peers(mac->psoc, vdev);
445 
446 	wifi_pos_set_delete_all_peer_in_progress(vdev, false);
447 
448 	pe_debug("Resume vdev delete");
449 	if (mac->sme.sme_vdev_del_cb)
450 		mac->sme.sme_vdev_del_cb(MAC_HANDLE(mac), vdev);
451 }
452 #endif
453 
lim_send_peer_create_resp(struct mac_context * mac,uint8_t vdev_id,QDF_STATUS qdf_status,uint8_t * peer_mac)454 void lim_send_peer_create_resp(struct mac_context *mac, uint8_t vdev_id,
455 			       QDF_STATUS qdf_status, uint8_t *peer_mac)
456 {
457 	struct wlan_objmgr_vdev *vdev;
458 	QDF_STATUS status;
459 
460 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
461 						    vdev_id,
462 						    WLAN_LEGACY_MAC_ID);
463 	if (!vdev)
464 		return;
465 	status = wlan_cm_bss_peer_create_rsp(vdev, qdf_status,
466 					     (struct qdf_mac_addr *)peer_mac);
467 
468 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
469 }
470 
471 static void
lim_process_mlm_post_join_suspend_link(struct mac_context * mac_ctx,struct pe_session * session)472 lim_process_mlm_post_join_suspend_link(struct mac_context *mac_ctx,
473 				       struct pe_session *session)
474 {
475 	lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
476 
477 	/* assign appropriate sessionId to the timer object */
478 	mac_ctx->lim.lim_timers.gLimJoinFailureTimer.sessionId =
479 		session->peSessionId;
480 
481 	/*
482 	 * store the channel switch session_entry in the lim
483 	 * global variable
484 	 */
485 	session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_JOIN;
486 	session->pLimMlmReassocRetryReq = NULL;
487 	lim_send_switch_chnl_params(mac_ctx, session);
488 }
489 
490 /**
491  * lim_process_mlm_join_req() - process mlm join request.
492  *
493  * @mac_ctx:    Pointer to Global MAC structure
494  * @mlm_join_req:        Pointer to the mlme join request
495  *
496  * This function is called to process MLM_JOIN_REQ message
497  * from SME. It does following:
498  * 1) Initialize LIM, HAL, DPH
499  * 2) Configure the BSS for which the JOIN REQ was received
500  *   a) Send WMA_ADD_BSS_REQ to HAL -
501  *   This will identify the BSS that we are interested in
502  *   --AND--
503  *   Add a STA entry for the AP (in a STA context)
504  *   b) Wait for WMA_ADD_BSS_RSP
505  *   c) Send WMA_ADD_STA_REQ to HAL
506  *   This will add the "local STA" entry to the STA table
507  * 3) Continue as before, i.e,
508  *   a) Send a PROBE REQ
509  *   b) Wait for PROBE RSP/BEACON containing the SSID that
510  *   we are interested in
511  *   c) Then start an AUTH seq
512  *   d) Followed by the ASSOC seq
513  *
514  * @Return: None
515  */
lim_process_mlm_join_req(struct mac_context * mac_ctx,tLimMlmJoinReq * mlm_join_req)516 void lim_process_mlm_join_req(struct mac_context *mac_ctx,
517 			      tLimMlmJoinReq *mlm_join_req)
518 {
519 	uint8_t sessionid;
520 	struct pe_session *session;
521 
522 	sessionid = mlm_join_req->sessionId;
523 
524 	session = pe_find_session_by_session_id(mac_ctx, sessionid);
525 	if (!session) {
526 		pe_err("SessionId:%d does not exist", sessionid);
527 		return;
528 	}
529 
530 	session->pLimMlmJoinReq = mlm_join_req;
531 	lim_process_mlm_post_join_suspend_link(mac_ctx, session);
532 }
533 
534 /**
535  * lim_is_auth_req_expected() - check if auth request is expected
536  *
537  * @mac_ctx: global MAC context
538  * @session: PE session entry
539  *
540  * This function is called by lim_process_mlm_auth_req to check
541  * if auth request is expected.
542  *
543  * Return: true if expected and false otherwise
544  */
lim_is_auth_req_expected(struct mac_context * mac_ctx,struct pe_session * session)545 static bool lim_is_auth_req_expected(struct mac_context *mac_ctx,
546 				     struct pe_session *session)
547 {
548 	bool flag = false;
549 
550 	/*
551 	 * Expect Auth request only when:
552 	 * 1. STA joined/associated with a BSS or
553 	 * 2. STA is going to authenticate with a unicast
554 	 * address and requested authentication algorithm is
555 	 * supported.
556 	 */
557 
558 	flag = (((LIM_IS_STA_ROLE(session) &&
559 		 ((session->limMlmState == eLIM_MLM_JOINED_STATE) ||
560 		  (session->limMlmState ==
561 					eLIM_MLM_LINK_ESTABLISHED_STATE)))) &&
562 		(!IEEE80211_IS_MULTICAST(
563 			mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr)) &&
564 		 lim_is_auth_algo_supported(mac_ctx,
565 			mac_ctx->lim.gpLimMlmAuthReq->authType, session));
566 
567 	return flag;
568 }
569 
570 /**
571  * lim_is_preauth_ctx_exists() - check if preauth context exists
572  * @mac_ctx:          global MAC context
573  * @session:          PE session entry
574  * @preauth_node_ptr: pointer to preauth node pointer
575  *
576  * This function is called by lim_process_mlm_auth_req to check
577  * if preauth context already exists
578  *
579  * Return: true if exists and false otherwise
580  */
lim_is_preauth_ctx_exists(struct mac_context * mac_ctx,struct pe_session * session,struct tLimPreAuthNode ** preauth_node_ptr)581 static bool lim_is_preauth_ctx_exists(struct mac_context *mac_ctx,
582 				      struct pe_session *session,
583 				      struct tLimPreAuthNode **preauth_node_ptr)
584 {
585 	bool fl = false;
586 	struct tLimPreAuthNode *preauth_node;
587 	tpDphHashNode stads;
588 	tSirMacAddr curr_bssid;
589 
590 	preauth_node = *preauth_node_ptr;
591 	sir_copy_mac_addr(curr_bssid, session->bssId);
592 	stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
593 				   &session->dph.dphHashTable);
594 	preauth_node = lim_search_pre_auth_list(mac_ctx,
595 				mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr);
596 
597 	fl = (((LIM_IS_STA_ROLE(session)) &&
598 	       (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
599 	      ((stads) &&
600 	       (mac_ctx->lim.gpLimMlmAuthReq->authType ==
601 			stads->mlmStaContext.authType)) &&
602 	       (!qdf_mem_cmp(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
603 			curr_bssid, sizeof(tSirMacAddr)))) ||
604 	      ((preauth_node) &&
605 	       (preauth_node->authType ==
606 			mac_ctx->lim.gpLimMlmAuthReq->authType)));
607 
608 	return fl;
609 }
610 
611 #ifdef WLAN_FEATURE_SAE
612 static inline
lim_get_sae_keymgmt_suite(uint32_t keymgmt)613 uint32_t lim_get_sae_keymgmt_suite(uint32_t keymgmt)
614 {
615 	/* Select the best SAE AKM suite supported */
616 	if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY))
617 		return WLAN_AKM_FT_SAE_EXT_KEY;
618 	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))
619 		return WLAN_AKM_SAE_EXT_KEY;
620 	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE))
621 		return WLAN_AKM_FT_SAE;
622 	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE))
623 		return WLAN_AKM_SAE;
624 
625 	pe_err("Invalid SAE Keymgmt suite %d", keymgmt);
626 	return WLAN_AKM_SAE;
627 }
628 
lim_trigger_auth_req_sae(struct mac_context * mac_ctx,struct pe_session * session,struct qdf_mac_addr * peer_bssid)629 QDF_STATUS lim_trigger_auth_req_sae(struct mac_context *mac_ctx,
630 				    struct pe_session *session,
631 				    struct qdf_mac_addr *peer_bssid)
632 {
633 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
634 	struct sir_sae_info *sae_info;
635 	struct scheduler_msg msg = {0};
636 	uint32_t keymgmt;
637 
638 	sae_info = qdf_mem_malloc(sizeof(*sae_info));
639 	if (!sae_info)
640 		return QDF_STATUS_E_FAILURE;
641 
642 	sae_info->msg_type = eWNI_SME_TRIGGER_SAE;
643 	sae_info->msg_len = sizeof(*sae_info);
644 	sae_info->vdev_id = session->smeSessionId;
645 
646 	qdf_copy_macaddr(&sae_info->peer_mac_addr, peer_bssid);
647 	keymgmt = wlan_crypto_get_param(session->vdev,
648 					WLAN_CRYPTO_PARAM_KEY_MGMT);
649 	sae_info->akm = lim_get_sae_keymgmt_suite(keymgmt);
650 
651 	sae_info->ssid.length = session->ssId.length;
652 	qdf_mem_copy(sae_info->ssid.ssId,
653 		session->ssId.ssId,
654 		session->ssId.length);
655 
656 	pe_debug("vdev_id %d ssid " QDF_SSID_FMT " " QDF_MAC_ADDR_FMT "akm %d",
657 		 sae_info->vdev_id,
658 		 QDF_SSID_REF(sae_info->ssid.length, sae_info->ssid.ssId),
659 		 QDF_MAC_ADDR_REF(sae_info->peer_mac_addr.bytes),
660 		 sae_info->akm);
661 
662 	msg.type = eWNI_SME_TRIGGER_SAE;
663 	msg.bodyptr = sae_info;
664 	msg.bodyval = 0;
665 
666 	qdf_status = mac_ctx->lim.sme_msg_callback(mac_ctx, &msg);
667 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
668 		pe_err("SAE failed for AUTH frame");
669 		qdf_mem_free(sae_info);
670 		return qdf_status;
671 	}
672 
673 	return qdf_status;
674 }
675 
676 /**
677  * lim_process_mlm_auth_req_sae() - Handle SAE authentication
678  * @mac_ctx: global MAC context
679  * @session: PE session entry
680  *
681  * This function is called by lim_process_mlm_auth_req to handle SAE
682  * authentication.
683  *
684  * Return: QDF_STATUS
685  */
lim_process_mlm_auth_req_sae(struct mac_context * mac_ctx,struct pe_session * session)686 static QDF_STATUS lim_process_mlm_auth_req_sae(struct mac_context *mac_ctx,
687 					       struct pe_session *session)
688 {
689 	QDF_STATUS qdf_status;
690 
691 	qdf_status = lim_trigger_auth_req_sae(
692 					mac_ctx, session,
693 					(struct qdf_mac_addr *)session->bssId);
694 	if (QDF_IS_STATUS_ERROR(qdf_status))
695 		return qdf_status;
696 
697 	session->limMlmState = eLIM_MLM_WT_SAE_AUTH_STATE;
698 
699 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
700 		       session->limMlmState));
701 
702 	mac_ctx->lim.lim_timers.sae_auth_timer.sessionId =
703 					session->peSessionId;
704 
705 	/* Activate SAE auth timer */
706 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
707 			 session->peSessionId, eLIM_AUTH_SAE_TIMER));
708 	if (tx_timer_activate(&mac_ctx->lim.lim_timers.sae_auth_timer)
709 		    != TX_SUCCESS) {
710 		pe_err("could not start Auth SAE timer");
711 	}
712 
713 	return qdf_status;
714 }
715 #else
lim_process_mlm_auth_req_sae(struct mac_context * mac_ctx,struct pe_session * session)716 static QDF_STATUS lim_process_mlm_auth_req_sae(struct mac_context *mac_ctx,
717 		struct pe_session *session)
718 {
719 	return QDF_STATUS_E_NOSUPPORT;
720 }
721 #endif
722 
723 
724 /**
725  * lim_process_mlm_auth_req() - process lim auth request
726  *
727  * @mac_ctx:   global MAC context
728  * @msg:       MLM auth request message
729  *
730  * This function is called to process MLM_AUTH_REQ message from SME
731  *
732  * @Return: None
733  */
lim_process_mlm_auth_req(struct mac_context * mac_ctx,uint32_t * msg)734 static void lim_process_mlm_auth_req(struct mac_context *mac_ctx, uint32_t *msg)
735 {
736 	uint32_t num_preauth_ctx;
737 	tSirMacAddr curr_bssid;
738 	tSirMacAuthFrameBody *auth_frame_body;
739 	tLimMlmAuthCnf mlm_auth_cnf;
740 	struct tLimPreAuthNode *preauth_node = NULL;
741 	uint8_t session_id;
742 	struct pe_session *session;
743 
744 	if (!msg) {
745 		pe_err("Buffer is Pointing to NULL");
746 		return;
747 	}
748 
749 	mac_ctx->lim.gpLimMlmAuthReq = (tLimMlmAuthReq *) msg;
750 	session_id = mac_ctx->lim.gpLimMlmAuthReq->sessionId;
751 	session = pe_find_session_by_session_id(mac_ctx, session_id);
752 	if (!session) {
753 		pe_err("SessionId:%d does not exist", session_id);
754 		qdf_mem_free(msg);
755 		mac_ctx->lim.gpLimMlmAuthReq = NULL;
756 		return;
757 	}
758 
759 	pe_debug("vdev %d Systemrole %d mlmstate %d from: " QDF_MAC_ADDR_FMT "with authtype %d",
760 		 session->vdev_id, GET_LIM_SYSTEM_ROLE(session),
761 		 session->limMlmState,
762 		 QDF_MAC_ADDR_REF(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr),
763 		 mac_ctx->lim.gpLimMlmAuthReq->authType);
764 
765 	sir_copy_mac_addr(curr_bssid, session->bssId);
766 
767 	if (!lim_is_auth_req_expected(mac_ctx, session)) {
768 		/*
769 		 * Unexpected auth request.
770 		 * Return Auth confirm with Invalid parameters code.
771 		 */
772 		pe_err("Auth req not expected is_privacy_enabled %d is_auth_open_system %d auth type %d",
773 			mac_ctx->mlme_cfg->wep_params.is_privacy_enabled,
774 			mac_ctx->mlme_cfg->wep_params.is_auth_open_system,
775 			mac_ctx->lim.gpLimMlmAuthReq->authType);
776 		mlm_auth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
777 		goto end;
778 	}
779 
780 	/*
781 	 * This is a request for pre-authentication. Check if there exists
782 	 * context already for the requested peer OR
783 	 * if this request is for the AP we're currently associated with.
784 	 * If yes, return auth confirm immediately when
785 	 * requested auth type is same as the one used before.
786 	 */
787 	if (lim_is_preauth_ctx_exists(mac_ctx, session, &preauth_node)) {
788 		pe_debug("Already have pre-auth context with peer: "
789 		    QDF_MAC_ADDR_FMT,
790 		    QDF_MAC_ADDR_REF(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr));
791 		mlm_auth_cnf.resultCode = (tSirResultCodes)STATUS_SUCCESS;
792 		goto end;
793 	} else {
794 		num_preauth_ctx = mac_ctx->mlme_cfg->lfr.max_num_pre_auth;
795 		if (mac_ctx->lim.gLimNumPreAuthContexts == num_preauth_ctx) {
796 			pe_warn("Number of pre-auth reached max limit");
797 			/* Return Auth confirm with reject code */
798 			mlm_auth_cnf.resultCode =
799 				eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED;
800 			goto end;
801 		}
802 	}
803 
804 	/* Delete pre-auth node if exists */
805 	if (preauth_node)
806 		lim_delete_pre_auth_node(mac_ctx,
807 			 mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr);
808 
809 	session->limPrevMlmState = session->limMlmState;
810 
811 	auth_frame_body = qdf_mem_malloc(sizeof(*auth_frame_body));
812 	if (!auth_frame_body) {
813 		pe_err("mem alloc failed for auth frame body");
814 		return;
815 	}
816 
817 	if ((mac_ctx->lim.gpLimMlmAuthReq->authType == eSIR_AUTH_TYPE_SAE) &&
818 	     !session->sae_pmk_cached) {
819 		if (lim_process_mlm_auth_req_sae(mac_ctx, session) !=
820 					QDF_STATUS_SUCCESS) {
821 			mlm_auth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
822 			qdf_mem_free(auth_frame_body);
823 			goto end;
824 		} else {
825 			pe_debug("lim_process_mlm_auth_req_sae is successful");
826 			auth_frame_body->authAlgoNumber = eSIR_AUTH_TYPE_SAE;
827 			auth_frame_body->authTransactionSeqNumber =
828 							SIR_MAC_AUTH_FRAME_1;
829 			auth_frame_body->authStatusCode = 0;
830 			host_log_wlan_auth_info(auth_frame_body->authAlgoNumber,
831 				auth_frame_body->authTransactionSeqNumber,
832 				auth_frame_body->authStatusCode);
833 
834 			qdf_mem_free(auth_frame_body);
835 			return;
836 		}
837 	} else
838 		session->limMlmState = eLIM_MLM_WT_AUTH_FRAME2_STATE;
839 
840 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
841 		       session->limMlmState));
842 
843 	/* Mark auth algo as open when auth type is SAE and PMK is cached */
844 	if ((mac_ctx->lim.gpLimMlmAuthReq->authType == eSIR_AUTH_TYPE_SAE) &&
845 	   session->sae_pmk_cached) {
846 		auth_frame_body->authAlgoNumber = eSIR_OPEN_SYSTEM;
847 	} else {
848 		auth_frame_body->authAlgoNumber =
849 		(uint8_t) mac_ctx->lim.gpLimMlmAuthReq->authType;
850 	}
851 
852 	/* Prepare & send Authentication frame */
853 	auth_frame_body->authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
854 	auth_frame_body->authStatusCode = 0;
855 	host_log_wlan_auth_info(auth_frame_body->authAlgoNumber,
856 				auth_frame_body->authTransactionSeqNumber,
857 				auth_frame_body->authStatusCode);
858 	mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
859 	lim_send_auth_mgmt_frame(mac_ctx,
860 		auth_frame_body, mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
861 		LIM_NO_WEP_IN_FC, session);
862 
863 	/* assign appropriate session_id to the timer object */
864 	mac_ctx->lim.lim_timers.gLimAuthFailureTimer.sessionId = session_id;
865 
866 	/* assign appropriate sessionId to the timer object */
867 	 mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId =
868 								  session_id;
869 	 lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER);
870 	/* Activate Auth failure timer */
871 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
872 			 session->peSessionId, eLIM_AUTH_FAIL_TIMER));
873 	 lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_FAIL_TIMER);
874 	if (tx_timer_activate(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer)
875 	    != TX_SUCCESS) {
876 		pe_err("could not start Auth failure timer");
877 		/* Cleanup as if auth timer expired */
878 		lim_process_auth_failure_timeout(mac_ctx);
879 	} else {
880 		MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
881 			   session->peSessionId, eLIM_AUTH_RETRY_TIMER));
882 		/* Activate Auth Retry timer */
883 		if (tx_timer_activate
884 		    (&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer)
885 							      != TX_SUCCESS)
886 			pe_err("could not activate Auth Retry timer");
887 	}
888 
889 	qdf_mem_free(auth_frame_body);
890 
891 	return;
892 end:
893 	qdf_mem_copy((uint8_t *) &mlm_auth_cnf.peerMacAddr,
894 		     (uint8_t *) &mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
895 		     sizeof(tSirMacAddr));
896 
897 	mlm_auth_cnf.authType = mac_ctx->lim.gpLimMlmAuthReq->authType;
898 	mlm_auth_cnf.sessionId = session_id;
899 
900 	qdf_mem_free(mac_ctx->lim.gpLimMlmAuthReq);
901 	mac_ctx->lim.gpLimMlmAuthReq = NULL;
902 	pe_debug("SessionId:%d LimPostSme LIM_MLM_AUTH_CNF",
903 		session_id);
904 	lim_post_sme_message(mac_ctx, LIM_MLM_AUTH_CNF,
905 			     (uint32_t *) &mlm_auth_cnf);
906 }
907 
lim_store_pmfcomeback_timerinfo(struct pe_session * session_entry)908 static void lim_store_pmfcomeback_timerinfo(struct pe_session *session_entry)
909 {
910 	if (session_entry->opmode != QDF_STA_MODE ||
911 	    !session_entry->limRmfEnabled)
912 		return;
913 	/*
914 	 * Store current MLM state in case ASSOC response returns with
915 	 * TRY_AGAIN_LATER return code.
916 	 */
917 	session_entry->pmf_retry_timer_info.lim_prev_mlm_state =
918 		session_entry->limPrevMlmState;
919 	session_entry->pmf_retry_timer_info.lim_mlm_state =
920 		session_entry->limMlmState;
921 }
922 
923 /**
924  * lim_process_mlm_assoc_req() - This function is called to process
925  * MLM_ASSOC_REQ message from SME
926  *
927  * @mac_ctx:       Pointer to Global MAC structure
928  * @msg_buf:       A pointer to the MLM message buffer
929  *
930  * This function is called to process MLM_ASSOC_REQ message from SME
931  *
932  * @Return None
933  */
934 
lim_process_mlm_assoc_req(struct mac_context * mac_ctx,uint32_t * msg_buf)935 static void lim_process_mlm_assoc_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
936 {
937 	tSirMacAddr curr_bssId;
938 	tLimMlmAssocReq *mlm_assoc_req;
939 	tLimMlmAssocCnf mlm_assoc_cnf;
940 	struct pe_session *session_entry;
941 
942 	if (!msg_buf) {
943 		pe_err("Buffer is Pointing to NULL");
944 		return;
945 	}
946 
947 	mlm_assoc_req = (tLimMlmAssocReq *) msg_buf;
948 	session_entry = pe_find_session_by_session_id(mac_ctx,
949 						      mlm_assoc_req->sessionId);
950 	if (!session_entry) {
951 		pe_err("SessionId:%d Session Does not exist",
952 			mlm_assoc_req->sessionId);
953 		qdf_mem_free(mlm_assoc_req);
954 		return;
955 	}
956 
957 	sir_copy_mac_addr(curr_bssId, session_entry->bssId);
958 
959 	if (!(!LIM_IS_AP_ROLE(session_entry) &&
960 		(session_entry->limMlmState == eLIM_MLM_AUTHENTICATED_STATE ||
961 		 session_entry->limMlmState == eLIM_MLM_JOINED_STATE) &&
962 		(!qdf_mem_cmp(mlm_assoc_req->peerMacAddr,
963 		 curr_bssId, sizeof(tSirMacAddr))))) {
964 		/*
965 		 * Received Association request either in invalid state
966 		 * or to a peer MAC entity whose address is different
967 		 * from one that STA is currently joined with or on AP.
968 		 * Return Assoc confirm with Invalid parameters code.
969 		 */
970 		pe_warn("received unexpected MLM_ASSOC_CNF in state %X for role=%d, MAC addr= "
971 			   QDF_MAC_ADDR_FMT, session_entry->limMlmState,
972 			GET_LIM_SYSTEM_ROLE(session_entry),
973 			QDF_MAC_ADDR_REF(mlm_assoc_req->peerMacAddr));
974 		lim_print_mlm_state(mac_ctx, LOGW, session_entry->limMlmState);
975 		mlm_assoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
976 		mlm_assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
977 		goto end;
978 	}
979 
980 	/* map the session entry pointer to the AssocFailureTimer */
981 	mac_ctx->lim.lim_timers.gLimAssocFailureTimer.sessionId =
982 		mlm_assoc_req->sessionId;
983 	lim_store_pmfcomeback_timerinfo(session_entry);
984 	session_entry->limPrevMlmState = session_entry->limMlmState;
985 	session_entry->limMlmState = eLIM_MLM_WT_ASSOC_RSP_STATE;
986 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
987 			 session_entry->peSessionId,
988 			 session_entry->limMlmState));
989 	pe_debug("vdev %d Sending Assoc_Req Frame, timeout %d msec",
990 		 session_entry->vdev_id,
991 		 (int)mac_ctx->lim.lim_timers.gLimAssocFailureTimer.initScheduleTimeInMsecs);
992 
993 	/* Prepare and send Association request frame */
994 	lim_send_assoc_req_mgmt_frame(mac_ctx, mlm_assoc_req, session_entry);
995 
996 	/* Start association failure timer */
997 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
998 			 session_entry->peSessionId, eLIM_ASSOC_FAIL_TIMER));
999 	if (tx_timer_activate(&mac_ctx->lim.lim_timers.gLimAssocFailureTimer)
1000 	    != TX_SUCCESS) {
1001 		pe_warn("SessionId:%d couldn't start Assoc failure timer",
1002 			session_entry->peSessionId);
1003 		/* Cleanup as if assoc timer expired */
1004 		lim_process_assoc_failure_timeout(mac_ctx, LIM_ASSOC);
1005 	}
1006 
1007 	return;
1008 end:
1009 	/* Update PE session Id */
1010 	mlm_assoc_cnf.sessionId = mlm_assoc_req->sessionId;
1011 	/* Free up buffer allocated for assoc_req */
1012 	qdf_mem_free(mlm_assoc_req);
1013 	lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
1014 			     (uint32_t *) &mlm_assoc_cnf);
1015 }
1016 
1017 /**
1018  * lim_process_mlm_disassoc_req_ntf() - process disassoc request notification
1019  *
1020  * @mac_ctx:        global MAC context
1021  * @suspend_status: suspend status
1022  * @msg:            mlm message buffer
1023  *
1024  * This function is used to process MLM disassoc notification
1025  *
1026  * Return: None
1027  */
1028 static void
lim_process_mlm_disassoc_req_ntf(struct mac_context * mac_ctx,QDF_STATUS suspend_status,uint32_t * msg)1029 lim_process_mlm_disassoc_req_ntf(struct mac_context *mac_ctx,
1030 				 QDF_STATUS suspend_status, uint32_t *msg)
1031 {
1032 	uint16_t aid;
1033 	struct qdf_mac_addr curr_bssid;
1034 	tpDphHashNode stads;
1035 	tLimMlmDisassocReq *mlm_disassocreq;
1036 	tLimMlmDisassocCnf mlm_disassoccnf;
1037 	struct pe_session *session;
1038 	extern bool send_disassoc_frame;
1039 	tLimMlmStates mlm_state;
1040 	struct disassoc_rsp *sme_disassoc_rsp;
1041 
1042 	if (QDF_STATUS_SUCCESS != suspend_status)
1043 		pe_err("Suspend Status is not success %X",
1044 			suspend_status);
1045 
1046 	mlm_disassocreq = (tLimMlmDisassocReq *) msg;
1047 
1048 	session = pe_find_session_by_session_id(mac_ctx,
1049 				mlm_disassocreq->sessionId);
1050 	if (!session) {
1051 		pe_err("session does not exist for given sessionId %d",
1052 			mlm_disassocreq->sessionId);
1053 		mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
1054 		goto end;
1055 	}
1056 
1057 	qdf_mem_copy(curr_bssid.bytes, session->bssId, QDF_MAC_ADDR_SIZE);
1058 
1059 	switch (GET_LIM_SYSTEM_ROLE(session)) {
1060 	case eLIM_STA_ROLE:
1061 		if (!qdf_is_macaddr_equal(&mlm_disassocreq->peer_macaddr,
1062 				     &curr_bssid)) {
1063 			pe_warn("received MLM_DISASSOC_REQ with invalid BSS: "QDF_MAC_ADDR_FMT,
1064 				QDF_MAC_ADDR_REF(
1065 				mlm_disassocreq->peer_macaddr.bytes));
1066 
1067 			/*
1068 			 * Disassociation response due to host triggered
1069 			 * disassociation
1070 			 */
1071 			sme_disassoc_rsp =
1072 				qdf_mem_malloc(sizeof(*sme_disassoc_rsp));
1073 			if (!sme_disassoc_rsp) {
1074 				qdf_mem_free(mlm_disassocreq);
1075 				return;
1076 			}
1077 
1078 			pe_debug("send disassoc rsp with ret code %d for "QDF_MAC_ADDR_FMT,
1079 				 eSIR_SME_DEAUTH_STATUS,
1080 				 QDF_MAC_ADDR_REF(
1081 					mlm_disassocreq->peer_macaddr.bytes));
1082 
1083 			sme_disassoc_rsp->messageType = eWNI_SME_DISASSOC_RSP;
1084 			sme_disassoc_rsp->length = sizeof(*sme_disassoc_rsp);
1085 			sme_disassoc_rsp->sessionId =
1086 					mlm_disassocreq->sessionId;
1087 			sme_disassoc_rsp->status_code = eSIR_SME_DEAUTH_STATUS;
1088 
1089 			qdf_copy_macaddr(&sme_disassoc_rsp->peer_macaddr,
1090 					 &mlm_disassocreq->peer_macaddr);
1091 			msg = (uint32_t *)sme_disassoc_rsp;
1092 
1093 			lim_send_sme_disassoc_deauth_ntf(mac_ctx,
1094 					QDF_STATUS_SUCCESS, msg);
1095 			qdf_mem_free(mlm_disassocreq);
1096 			return;
1097 
1098 		}
1099 		break;
1100 	default:
1101 		break;
1102 	} /* end switch (GET_LIM_SYSTEM_ROLE(session)) */
1103 
1104 	/*
1105 	 * Check if there exists a context for the peer entity
1106 	 * to be disassociated with.
1107 	 */
1108 	stads = dph_lookup_hash_entry(mac_ctx,
1109 				      mlm_disassocreq->peer_macaddr.bytes,
1110 				      &aid, &session->dph.dphHashTable);
1111 	if (stads)
1112 		mlm_state = stads->mlmStaContext.mlmState;
1113 
1114 	if ((!stads) ||
1115 	    (stads &&
1116 	     ((mlm_state != eLIM_MLM_LINK_ESTABLISHED_STATE) &&
1117 	      (mlm_state != eLIM_MLM_WT_ASSOC_CNF_STATE) &&
1118 	      (mlm_state != eLIM_MLM_ASSOCIATED_STATE)))) {
1119 		/*
1120 		 * Received LIM_MLM_DISASSOC_REQ for STA that does not
1121 		 * have context or in some transit state.
1122 		 */
1123 		pe_warn("Invalid MLM_DISASSOC_REQ, Addr= " QDF_MAC_ADDR_FMT,
1124 			QDF_MAC_ADDR_REF(mlm_disassocreq->peer_macaddr.bytes));
1125 		if (stads)
1126 			pe_err("Sta MlmState: %d", stads->mlmStaContext.mlmState);
1127 
1128 		/* Prepare and Send LIM_MLM_DISASSOC_CNF */
1129 		mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
1130 		goto end;
1131 	}
1132 
1133 	stads->mlmStaContext.disassocReason = mlm_disassocreq->reasonCode;
1134 	stads->mlmStaContext.cleanupTrigger = mlm_disassocreq->disassocTrigger;
1135 
1136 	/*
1137 	 * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
1138 	 * This is to address the issue of race condition between
1139 	 * disconnect request from the HDD and deauth from AP
1140 	 */
1141 
1142 	stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
1143 
1144 	/* Send Disassociate frame to peer entity */
1145 	if (send_disassoc_frame && (mlm_disassocreq->reasonCode !=
1146 	    REASON_AUTHORIZED_ACCESS_LIMIT_REACHED)) {
1147 		if (mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq) {
1148 			pe_err("pMlmDisassocReq is not NULL, freeing");
1149 			qdf_mem_free(mac_ctx->lim.limDisassocDeauthCnfReq.
1150 				     pMlmDisassocReq);
1151 		}
1152 		mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq =
1153 			mlm_disassocreq;
1154 		/*
1155 		 * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
1156 		 * This is to address the issue of race condition between
1157 		 * disconnect request from the HDD and deauth from AP
1158 		 */
1159 		stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
1160 
1161 		lim_send_disassoc_mgmt_frame(mac_ctx,
1162 			mlm_disassocreq->reasonCode,
1163 			mlm_disassocreq->peer_macaddr.bytes, session, true);
1164 		/*
1165 		 * Abort Tx so that data frames won't be sent to the AP
1166 		 * after sending Disassoc.
1167 		 */
1168 		if (LIM_IS_STA_ROLE(session))
1169 			wma_tx_abort(session->smeSessionId);
1170 	} else {
1171 		lim_mlo_notify_peer_disconn(session, stads);
1172 		/* Disassoc frame is not sent OTA */
1173 		send_disassoc_frame = 1;
1174 		/* Receive path cleanup with dummy packet */
1175 		if (QDF_STATUS_SUCCESS !=
1176 		    lim_cleanup_rx_path(mac_ctx, stads, session, true)) {
1177 			mlm_disassoccnf.resultCode =
1178 				eSIR_SME_RESOURCES_UNAVAILABLE;
1179 			goto end;
1180 		}
1181 		/* Free up buffer allocated for mlmDisassocReq */
1182 		qdf_mem_free(mlm_disassocreq);
1183 	}
1184 
1185 	return;
1186 
1187 end:
1188 	qdf_mem_copy((uint8_t *) &mlm_disassoccnf.peerMacAddr,
1189 		     (uint8_t *) mlm_disassocreq->peer_macaddr.bytes,
1190 		     QDF_MAC_ADDR_SIZE);
1191 	mlm_disassoccnf.aid = mlm_disassocreq->aid;
1192 	mlm_disassoccnf.disassocTrigger = mlm_disassocreq->disassocTrigger;
1193 
1194 	/* Update PE session ID */
1195 	mlm_disassoccnf.sessionId = mlm_disassocreq->sessionId;
1196 
1197 	/* Free up buffer allocated for mlmDisassocReq */
1198 	qdf_mem_free(mlm_disassocreq);
1199 
1200 	lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF,
1201 			     (uint32_t *) &mlm_disassoccnf);
1202 }
1203 
1204 /**
1205  * lim_check_disassoc_deauth_ack_pending() - check if deauth is pending
1206  *
1207  * @mac_ctx - global MAC context
1208  * @sta_mac - station MAC
1209  *
1210  * This function checks if diassociation or deauthentication is pending for
1211  * given station MAC address.
1212  *
1213  * Return: true if pending and false otherwise.
1214  */
lim_check_disassoc_deauth_ack_pending(struct mac_context * mac_ctx,uint8_t * sta_mac)1215 bool lim_check_disassoc_deauth_ack_pending(struct mac_context *mac_ctx,
1216 					   uint8_t *sta_mac)
1217 {
1218 	tLimMlmDisassocReq *disassoc_req;
1219 	tLimMlmDeauthReq *deauth_req;
1220 
1221 	disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
1222 	deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
1223 	if ((disassoc_req && (!qdf_mem_cmp((uint8_t *) sta_mac,
1224 			      (uint8_t *) &disassoc_req->peer_macaddr.bytes,
1225 			       QDF_MAC_ADDR_SIZE))) ||
1226 	    (deauth_req && (!qdf_mem_cmp((uint8_t *) sta_mac,
1227 			      (uint8_t *) &deauth_req->peer_macaddr.bytes,
1228 			       QDF_MAC_ADDR_SIZE)))) {
1229 		pe_debug("Disassoc/Deauth ack pending");
1230 		return true;
1231 	} else {
1232 		pe_debug("Disassoc/Deauth Ack not pending");
1233 		return false;
1234 	}
1235 }
1236 
1237 /*
1238  * lim_clean_up_disassoc_deauth_req() - cleans up pending disassoc or deauth req
1239  *
1240  * @mac_ctx:        mac_ctx
1241  * @sta_mac:        sta mac address
1242  * @clean_rx_path:  flag to indicate whether to cleanup rx path or not
1243  *
1244  * This function cleans up pending disassoc or deauth req
1245  *
1246  * Return: void
1247  */
lim_clean_up_disassoc_deauth_req(struct mac_context * mac_ctx,uint8_t * sta_mac,bool clean_rx_path)1248 void lim_clean_up_disassoc_deauth_req(struct mac_context *mac_ctx,
1249 				      uint8_t *sta_mac, bool clean_rx_path)
1250 {
1251 	tLimMlmDisassocReq *mlm_disassoc_req;
1252 	tLimMlmDeauthReq *mlm_deauth_req;
1253 
1254 	mlm_disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
1255 	if (mlm_disassoc_req &&
1256 	    (!qdf_mem_cmp((uint8_t *) sta_mac,
1257 			     (uint8_t *) &mlm_disassoc_req->peer_macaddr.bytes,
1258 			     QDF_MAC_ADDR_SIZE))) {
1259 		if (clean_rx_path) {
1260 			lim_process_disassoc_ack_timeout(mac_ctx);
1261 		} else {
1262 			if (tx_timer_running(
1263 			    &mac_ctx->lim.lim_timers.gLimDisassocAckTimer)) {
1264 				lim_deactivate_and_change_timer(mac_ctx,
1265 						eLIM_DISASSOC_ACK_TIMER);
1266 			}
1267 			qdf_mem_free(mlm_disassoc_req);
1268 			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq =
1269 				NULL;
1270 		}
1271 	}
1272 
1273 	mlm_deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
1274 	if (mlm_deauth_req &&
1275 	    (!qdf_mem_cmp((uint8_t *) sta_mac,
1276 			     (uint8_t *) &mlm_deauth_req->peer_macaddr.bytes,
1277 			     QDF_MAC_ADDR_SIZE))) {
1278 		if (clean_rx_path) {
1279 			lim_process_deauth_ack_timeout(mac_ctx,
1280 						       mlm_deauth_req->sessionId);
1281 		} else {
1282 			if (tx_timer_running(
1283 				&mac_ctx->lim.lim_timers.gLimDeauthAckTimer)) {
1284 				lim_deactivate_and_change_timer(mac_ctx,
1285 						eLIM_DEAUTH_ACK_TIMER);
1286 			}
1287 			qdf_mem_free(mlm_deauth_req);
1288 			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq =
1289 				NULL;
1290 		}
1291 	}
1292 }
1293 
1294 /*
1295  * lim_process_disassoc_ack_timeout() - wrapper function around
1296  * lim_send_disassoc_cnf
1297  *
1298  * @mac_ctx:        mac_ctx
1299  *
1300  * wrapper function around lim_send_disassoc_cnf
1301  *
1302  * Return: void
1303  */
lim_process_disassoc_ack_timeout(struct mac_context * mac_ctx)1304 void lim_process_disassoc_ack_timeout(struct mac_context *mac_ctx)
1305 {
1306 	lim_send_disassoc_cnf(mac_ctx);
1307 }
1308 
1309 /**
1310  * lim_process_mlm_disassoc_req() - This function is called to process
1311  * MLM_DISASSOC_REQ message from SME
1312  *
1313  * @mac_ctx:      Pointer to Global MAC structure
1314  * @msg_buf:      A pointer to the MLM message buffer
1315  *
1316  * This function is called to process MLM_DISASSOC_REQ message from SME
1317  *
1318  * @Return: None
1319  */
1320 static void
lim_process_mlm_disassoc_req(struct mac_context * mac_ctx,uint32_t * msg_buf)1321 lim_process_mlm_disassoc_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
1322 {
1323 	tLimMlmDisassocReq *mlm_disassoc_req;
1324 
1325 	if (!msg_buf) {
1326 		pe_err("Buffer is Pointing to NULL");
1327 		return;
1328 	}
1329 
1330 	mlm_disassoc_req = (tLimMlmDisassocReq *) msg_buf;
1331 	lim_process_mlm_disassoc_req_ntf(mac_ctx, QDF_STATUS_SUCCESS,
1332 					 (uint32_t *) msg_buf);
1333 }
1334 
1335 /**
1336  * lim_process_mlm_deauth_req_ntf() - This function is process mlm deauth req
1337  * notification
1338  *
1339  * @mac_ctx:         Pointer to Global MAC structure
1340  * @suspend_status:  suspend status
1341  * @msg_buf:         A pointer to the MLM message buffer
1342  *
1343  * This function is process mlm deauth req notification
1344  *
1345  * @Return: None
1346  */
1347 static void
lim_process_mlm_deauth_req_ntf(struct mac_context * mac_ctx,QDF_STATUS suspend_status,uint32_t * msg_buf)1348 lim_process_mlm_deauth_req_ntf(struct mac_context *mac_ctx,
1349 			       QDF_STATUS suspend_status, uint32_t *msg_buf)
1350 {
1351 	uint16_t aid, i;
1352 	tSirMacAddr curr_bssId;
1353 	tpDphHashNode sta_ds;
1354 	struct tLimPreAuthNode *auth_node;
1355 	tLimMlmDeauthReq *mlm_deauth_req;
1356 	tLimMlmDeauthCnf mlm_deauth_cnf;
1357 	struct pe_session *session;
1358 	struct deauth_rsp *sme_deauth_rsp;
1359 
1360 	if (QDF_STATUS_SUCCESS != suspend_status)
1361 		pe_err("Suspend Status is not success %X",
1362 			suspend_status);
1363 
1364 	mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf;
1365 	session = pe_find_session_by_session_id(mac_ctx,
1366 				mlm_deauth_req->sessionId);
1367 	if (!session) {
1368 		pe_err("session does not exist for given sessionId %d",
1369 			mlm_deauth_req->sessionId);
1370 		qdf_mem_free(mlm_deauth_req);
1371 		return;
1372 	}
1373 	sir_copy_mac_addr(curr_bssId, session->bssId);
1374 
1375 	switch (GET_LIM_SYSTEM_ROLE(session)) {
1376 	case eLIM_STA_ROLE:
1377 		switch (session->limMlmState) {
1378 		case eLIM_MLM_IDLE_STATE:
1379 			/*
1380 			 * Attempting to Deauthenticate with a pre-authenticated
1381 			 * peer. Deauthetiate with peer if there exists a
1382 			 * pre-auth context below.
1383 			 */
1384 			break;
1385 		case eLIM_MLM_AUTHENTICATED_STATE:
1386 		case eLIM_MLM_WT_ASSOC_RSP_STATE:
1387 		case eLIM_MLM_LINK_ESTABLISHED_STATE:
1388 			if (qdf_mem_cmp(mlm_deauth_req->peer_macaddr.bytes,
1389 					curr_bssId, QDF_MAC_ADDR_SIZE)) {
1390 				pe_err("received MLM_DEAUTH_REQ with invalid BSS id "
1391 					   "Peer MAC: "QDF_MAC_ADDR_FMT
1392 					   " CFG BSSID Addr : "QDF_MAC_ADDR_FMT,
1393 					QDF_MAC_ADDR_REF(
1394 						mlm_deauth_req->peer_macaddr.bytes),
1395 					QDF_MAC_ADDR_REF(curr_bssId));
1396 				/*
1397 				 * Deauthentication response to host triggered
1398 				 * deauthentication
1399 				 */
1400 				sme_deauth_rsp =
1401 				    qdf_mem_malloc(sizeof(*sme_deauth_rsp));
1402 				if (!sme_deauth_rsp) {
1403 					qdf_mem_free(mlm_deauth_req);
1404 					return;
1405 				}
1406 
1407 				sme_deauth_rsp->messageType =
1408 						eWNI_SME_DEAUTH_RSP;
1409 				sme_deauth_rsp->length =
1410 						sizeof(*sme_deauth_rsp);
1411 				sme_deauth_rsp->status_code =
1412 						eSIR_SME_DEAUTH_STATUS;
1413 				sme_deauth_rsp->sessionId =
1414 						session->vdev_id;
1415 
1416 				qdf_mem_copy(sme_deauth_rsp->peer_macaddr.bytes,
1417 					     mlm_deauth_req->peer_macaddr.bytes,
1418 					     QDF_MAC_ADDR_SIZE);
1419 
1420 				msg_buf = (uint32_t *)sme_deauth_rsp;
1421 
1422 				lim_send_sme_disassoc_deauth_ntf(mac_ctx,
1423 						QDF_STATUS_SUCCESS, msg_buf);
1424 				qdf_mem_free(mlm_deauth_req);
1425 				return;
1426 			}
1427 
1428 			if ((session->limMlmState ==
1429 			     eLIM_MLM_AUTHENTICATED_STATE) ||
1430 			    (session->limMlmState ==
1431 			     eLIM_MLM_WT_ASSOC_RSP_STATE)) {
1432 				/* Send deauth frame to peer entity */
1433 				lim_send_deauth_mgmt_frame(mac_ctx,
1434 					mlm_deauth_req->reasonCode,
1435 					mlm_deauth_req->peer_macaddr.bytes,
1436 					session, false);
1437 				/* Prepare and Send LIM_MLM_DEAUTH_CNF */
1438 				mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
1439 				session->limMlmState = eLIM_MLM_IDLE_STATE;
1440 				MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
1441 						 session->peSessionId,
1442 						 session->limMlmState));
1443 				goto end;
1444 			}
1445 			break;
1446 		default:
1447 			pe_warn("received MLM_DEAUTH_REQ with in state %d for peer "
1448 				   QDF_MAC_ADDR_FMT,
1449 				session->limMlmState,
1450 				QDF_MAC_ADDR_REF(
1451 					mlm_deauth_req->peer_macaddr.bytes));
1452 			lim_print_mlm_state(mac_ctx, LOGW,
1453 					    session->limMlmState);
1454 			/* Prepare and Send LIM_MLM_DEAUTH_CNF */
1455 			mlm_deauth_cnf.resultCode =
1456 				eSIR_SME_STA_NOT_AUTHENTICATED;
1457 
1458 			goto end;
1459 		}
1460 		break;
1461 	default:
1462 		break;
1463 	} /* end switch (GET_LIM_SYSTEM_ROLE(session)) */
1464 
1465 	/*
1466 	 * Check if there exists a context for the peer entity
1467 	 * to be deauthenticated with.
1468 	 */
1469 	sta_ds = dph_lookup_hash_entry(mac_ctx,
1470 				       mlm_deauth_req->peer_macaddr.bytes,
1471 				       &aid,
1472 				       &session->dph.dphHashTable);
1473 
1474 	if (!sta_ds && (!mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled
1475 	    || (mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled &&
1476 	    !qdf_is_macaddr_broadcast(&mlm_deauth_req->peer_macaddr)))) {
1477 		/* Check if there exists pre-auth context for this STA */
1478 		auth_node = lim_search_pre_auth_list(mac_ctx, mlm_deauth_req->
1479 						     peer_macaddr.bytes);
1480 		if (!auth_node) {
1481 			/*
1482 			 * Received DEAUTH REQ for a STA that is neither
1483 			 * Associated nor Pre-authenticated. Log error,
1484 			 * Prepare and Send LIM_MLM_DEAUTH_CNF
1485 			 */
1486 			pe_warn("rcvd MLM_DEAUTH_REQ in mlme state %d STA does not have context, Addr="QDF_MAC_ADDR_FMT,
1487 				session->limMlmState,
1488 				QDF_MAC_ADDR_REF(
1489 					mlm_deauth_req->peer_macaddr.bytes));
1490 			mlm_deauth_cnf.resultCode =
1491 				eSIR_SME_STA_NOT_AUTHENTICATED;
1492 		} else {
1493 			mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
1494 			/* Delete STA from pre-auth STA list */
1495 			lim_delete_pre_auth_node(mac_ctx,
1496 						 mlm_deauth_req->
1497 						 peer_macaddr.bytes);
1498 			/*Send Deauthentication frame to peer entity*/
1499 			lim_send_deauth_mgmt_frame(mac_ctx,
1500 						   mlm_deauth_req->reasonCode,
1501 						   mlm_deauth_req->
1502 						   peer_macaddr.bytes,
1503 						   session, false);
1504 		}
1505 		goto end;
1506 	} else if (sta_ds && (sta_ds->mlmStaContext.mlmState !=
1507 		   eLIM_MLM_LINK_ESTABLISHED_STATE) &&
1508 		   (sta_ds->mlmStaContext.mlmState !=
1509 		   eLIM_MLM_WT_ASSOC_CNF_STATE)) {
1510 		/*
1511 		 * received MLM_DEAUTH_REQ for STA that either has no
1512 		 * context or in some transit state
1513 		 */
1514 		pe_warn("Invalid MLM_DEAUTH_REQ, Addr=" QDF_MAC_ADDR_FMT,
1515 			QDF_MAC_ADDR_REF(mlm_deauth_req->
1516 			peer_macaddr.bytes));
1517 		/* Prepare and Send LIM_MLM_DEAUTH_CNF */
1518 		mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
1519 		goto end;
1520 	} else if (sta_ds) {
1521 		/* sta_ds->mlmStaContext.rxPurgeReq     = 1; */
1522 		sta_ds->mlmStaContext.disassocReason =
1523 						mlm_deauth_req->reasonCode;
1524 		sta_ds->mlmStaContext.cleanupTrigger =
1525 						mlm_deauth_req->deauthTrigger;
1526 
1527 		/*
1528 		 * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
1529 		 * This is to address the issue of race condition between
1530 		 * disconnect request from the HDD and disassoc from
1531 		 * inactivity timer. This will make sure that we will not
1532 		 * process disassoc if deauth is in progress for the station
1533 		 * and thus mlmStaContext.cleanupTrigger will not be
1534 		 * overwritten.
1535 		 */
1536 		sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
1537 	} else if (mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled &&
1538 		   qdf_is_macaddr_broadcast(&mlm_deauth_req->peer_macaddr)) {
1539 		for (i = 0; i < session->dph.dphHashTable.size; i++) {
1540 			sta_ds = dph_get_hash_entry(mac_ctx, i,
1541 						   &session->dph.dphHashTable);
1542 			if (!sta_ds)
1543 				continue;
1544 
1545 			sta_ds->mlmStaContext.disassocReason =
1546 					mlm_deauth_req->reasonCode;
1547 			sta_ds->mlmStaContext.cleanupTrigger =
1548 						mlm_deauth_req->deauthTrigger;
1549 			sta_ds->mlmStaContext.mlmState =
1550 						eLIM_MLM_WT_DEL_STA_RSP_STATE;
1551 		}
1552 	}
1553 
1554 	if (mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq) {
1555 		pe_err("pMlmDeauthReq is not NULL, freeing");
1556 		qdf_mem_free(mac_ctx->lim.limDisassocDeauthCnfReq.
1557 			     pMlmDeauthReq);
1558 	}
1559 	mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = mlm_deauth_req;
1560 
1561 	/* Send Deauthentication frame to peer entity */
1562 	if (mlm_deauth_req->reasonCode != REASON_DISASSOC_DUE_TO_INACTIVITY ||
1563 	    wlan_son_peer_is_kickout_allow(session->vdev, sta_ds->staAddr)) {
1564 		lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode,
1565 					   mlm_deauth_req->peer_macaddr.bytes,
1566 					   session, true);
1567 	} else {
1568 		pe_err("peer " QDF_MAC_ADDR_FMT " is in band steering, do not send deauth frame",
1569 		       QDF_MAC_ADDR_REF(mlm_deauth_req->peer_macaddr.bytes));
1570 		mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
1571 		goto end;
1572 	}
1573 
1574 	return;
1575 end:
1576 	qdf_copy_macaddr(&mlm_deauth_cnf.peer_macaddr,
1577 			 &mlm_deauth_req->peer_macaddr);
1578 	mlm_deauth_cnf.deauthTrigger = mlm_deauth_req->deauthTrigger;
1579 	mlm_deauth_cnf.aid = mlm_deauth_req->aid;
1580 	mlm_deauth_cnf.sessionId = mlm_deauth_req->sessionId;
1581 
1582 	/* Free up buffer allocated for mlmDeauthReq */
1583 	qdf_mem_free(mlm_deauth_req);
1584 	lim_post_sme_message(mac_ctx,
1585 			     LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlm_deauth_cnf);
1586 }
1587 
1588 /*
1589  * lim_process_deauth_ack_timeout() - wrapper function around
1590  * lim_send_deauth_cnf
1591  *
1592  * @pMacGlobal:     mac_ctx
1593  * @vdev_id:        vdev id
1594  *
1595  * wrapper function around lim_send_deauth_cnf
1596  *
1597  * Return: void
1598  */
lim_process_deauth_ack_timeout(void * pMacGlobal,uint32_t vdev_id)1599 void lim_process_deauth_ack_timeout(void *pMacGlobal, uint32_t vdev_id)
1600 {
1601 	struct mac_context *mac_ctx = (struct mac_context *)pMacGlobal;
1602 
1603 	pe_debug("Deauth Ack timeout for vdev id %d", vdev_id);
1604 	lim_send_deauth_cnf(mac_ctx, vdev_id);
1605 }
1606 
1607 /*
1608  * lim_process_mlm_deauth_req() - This function is called to process
1609  * MLM_DEAUTH_REQ message from SME
1610  *
1611  * @mac_ctx:      Pointer to Global MAC structure
1612  * @msg_buf:      A pointer to the MLM message buffer
1613  *
1614  * This function is called to process MLM_DEAUTH_REQ message from SME
1615  *
1616  * @Return: None
1617  */
lim_process_mlm_deauth_req(struct mac_context * mac_ctx,uint32_t * msg_buf)1618 void lim_process_mlm_deauth_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
1619 {
1620 	tLimMlmDeauthReq *mlm_deauth_req;
1621 	struct pe_session *session;
1622 
1623 	if (!msg_buf) {
1624 		pe_err("Buffer is Pointing to NULL");
1625 		return;
1626 	}
1627 
1628 	mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf;
1629 	session = pe_find_session_by_session_id(mac_ctx,
1630 				mlm_deauth_req->sessionId);
1631 	if (!session) {
1632 		pe_err("session does not exist for given sessionId %d",
1633 			mlm_deauth_req->sessionId);
1634 		qdf_mem_free(mlm_deauth_req);
1635 		return;
1636 	}
1637 	lim_process_mlm_deauth_req_ntf(mac_ctx, QDF_STATUS_SUCCESS,
1638 				       (uint32_t *) msg_buf);
1639 }
1640 
lim_process_join_failure_timeout(struct mac_context * mac_ctx)1641 void lim_process_join_failure_timeout(struct mac_context *mac_ctx)
1642 {
1643 	tLimMlmJoinCnf mlm_join_cnf;
1644 	uint32_t len;
1645 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1646 	host_log_rssi_pkt_type *rssi_log = NULL;
1647 #endif
1648 	struct pe_session *session;
1649 
1650 	session = pe_find_session_by_session_id(mac_ctx,
1651 			mac_ctx->lim.lim_timers.gLimJoinFailureTimer.sessionId);
1652 	if (!session) {
1653 		pe_err("Session Does not exist for given sessionID");
1654 		return;
1655 	}
1656 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1657 	WLAN_HOST_DIAG_LOG_ALLOC(rssi_log,
1658 				host_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C);
1659 	if (rssi_log)
1660 		rssi_log->rssi = session->rssi;
1661 	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
1662 #endif
1663 	session->join_probe_cnt = 0;
1664 
1665 	if (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) {
1666 		len = sizeof(tSirMacAddr);
1667 		/* Change timer for future activations */
1668 		lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
1669 		/* Change Periodic probe req timer for future activation */
1670 		lim_deactivate_and_change_timer(mac_ctx,
1671 					eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
1672 		/* Issue MLM join confirm with timeout reason code */
1673 		pe_err("Join Failure Timeout, In eLIM_MLM_WT_JOIN_BEACON_STATE session:%d "
1674 			   QDF_MAC_ADDR_FMT,
1675 			session->peSessionId,
1676 			QDF_MAC_ADDR_REF(session->bssId));
1677 
1678 		mlm_join_cnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE;
1679 		mlm_join_cnf.protStatusCode = STATUS_NO_NETWORK_FOUND;
1680 		session->limMlmState = eLIM_MLM_IDLE_STATE;
1681 		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
1682 				 session->peSessionId, session->limMlmState));
1683 		/* Update PE session Id */
1684 		mlm_join_cnf.sessionId = session->peSessionId;
1685 		/* Freeup buffer allocated to join request */
1686 		if (session->pLimMlmJoinReq) {
1687 			qdf_mem_free(session->pLimMlmJoinReq);
1688 			session->pLimMlmJoinReq = NULL;
1689 		}
1690 		lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
1691 				     (uint32_t *) &mlm_join_cnf);
1692 		return;
1693 	} else {
1694 		pe_warn("received unexpected JOIN failure timeout in state %X",
1695 			session->limMlmState);
1696 		lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
1697 	}
1698 }
1699 
1700 /**
1701  * lim_process_periodic_join_probe_req_timer() - This function is called to
1702  * process periodic probe request send during joining process.
1703  *
1704  * @mac_ctx:      Pointer to Global MAC structure
1705  *
1706  * This function is called to process periodic probe request send during
1707  * joining process.
1708  *
1709  * @Return None
1710  */
lim_process_periodic_join_probe_req_timer(struct mac_context * mac_ctx)1711 static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ctx)
1712 {
1713 	struct pe_session *session;
1714 	tSirMacSSid ssid;
1715 	tSirMacAddr bssid;
1716 	tSirMacAddr bcast_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1717 
1718 	session = pe_find_session_by_session_id(mac_ctx,
1719 	      mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer.sessionId);
1720 	if (!session) {
1721 		pe_err("session does not exist for given SessionId: %d",
1722 			mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer.
1723 			sessionId);
1724 		return;
1725 	}
1726 
1727 	if ((true ==
1728 	    tx_timer_running(&mac_ctx->lim.lim_timers.gLimJoinFailureTimer))
1729 		&& (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE)) {
1730 		qdf_mem_copy(ssid.ssId, session->ssId.ssId,
1731 			     session->ssId.length);
1732 		ssid.length = session->ssId.length;
1733 		sir_copy_mac_addr(bssid,
1734 				  session->pLimMlmJoinReq->bssDescription.bssId);
1735 
1736 		/*
1737 		 * Some APs broadcasting hidden SSID doesn't respond to unicast
1738 		 * probe requests, however those APs respond to broadcast probe
1739 		 * requests. Therefore for hidden ssid connections, after 3
1740 		 * unicast probe requests, try the pending probes with broadcast
1741 		 * mac.
1742 		 */
1743 		if (session->ssidHidden && session->join_probe_cnt > 2)
1744 			sir_copy_mac_addr(bssid, bcast_mac);
1745 
1746 		lim_send_probe_req_mgmt_frame(mac_ctx, &ssid, bssid,
1747 					      session->curr_op_freq,
1748 			session->self_mac_addr, session->dot11mode,
1749 			&session->lim_join_req->addIEScan.length,
1750 			session->lim_join_req->addIEScan.addIEdata);
1751 		lim_deactivate_and_change_timer(mac_ctx,
1752 				eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
1753 		/* Activate Join Periodic Probe Req timer */
1754 		if (tx_timer_activate(
1755 		    &mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer) !=
1756 		    TX_SUCCESS) {
1757 			pe_warn("could not activate Periodic Join req failure timer");
1758 			return;
1759 		}
1760 		session->join_probe_cnt++;
1761 	}
1762 }
1763 
lim_send_pre_auth_failure(uint8_t vdev_id,tSirMacAddr bssid)1764 static void lim_send_pre_auth_failure(uint8_t vdev_id, tSirMacAddr bssid)
1765 {
1766 	struct scheduler_msg sch_msg = {0};
1767 	struct wmi_roam_auth_status_params *params;
1768 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1769 
1770 	params = qdf_mem_malloc(sizeof(*params));
1771 	if (!params)
1772 		return;
1773 
1774 	params->vdev_id = vdev_id;
1775 	params->preauth_status = STATUS_UNSPECIFIED_FAILURE;
1776 	qdf_mem_copy(params->bssid.bytes, bssid, QDF_MAC_ADDR_SIZE);
1777 	qdf_mem_zero(params->pmkid, PMKID_LEN);
1778 
1779 	sch_msg.type = WMA_ROAM_PRE_AUTH_STATUS;
1780 	sch_msg.bodyptr = params;
1781 	pe_debug("Sending pre auth failure for mac_addr " QDF_MAC_ADDR_FMT,
1782 		 QDF_MAC_ADDR_REF(params->bssid.bytes));
1783 
1784 	status = scheduler_post_message(QDF_MODULE_ID_PE,
1785 					QDF_MODULE_ID_WMA,
1786 					QDF_MODULE_ID_WMA,
1787 					&sch_msg);
1788 	if (QDF_IS_STATUS_ERROR(status)) {
1789 		pe_err("Sending preauth status failed");
1790 		qdf_mem_free(params);
1791 	}
1792 }
1793 
lim_handle_sae_auth_timeout(struct mac_context * mac_ctx,struct pe_session * session_entry)1794 static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx,
1795 					struct pe_session *session_entry)
1796 {
1797 	struct sae_auth_retry *sae_retry;
1798 	tpSirMacMgmtHdr mac_hdr;
1799 
1800 	sae_retry = mlme_get_sae_auth_retry(session_entry->vdev);
1801 	if (!(sae_retry && sae_retry->sae_auth.ptr)) {
1802 		pe_debug("sae auth frame is not buffered vdev id %d",
1803 			 session_entry->vdev_id);
1804 		return;
1805 	}
1806 
1807 	if (!sae_retry->sae_auth_max_retry) {
1808 		if (!wlan_cm_is_vdev_connecting(session_entry->vdev)) {
1809 			mac_hdr = (tpSirMacMgmtHdr)sae_retry->sae_auth.ptr;
1810 			lim_send_pre_auth_failure(session_entry->vdev_id,
1811 						  mac_hdr->bssId);
1812 		}
1813 		goto free_and_deactivate_timer;
1814 	}
1815 
1816 	pe_debug("Retry sae auth for seq num %d vdev id %d",
1817 		 mac_ctx->mgmtSeqNum, session_entry->vdev_id);
1818 	lim_send_frame(mac_ctx, session_entry->vdev_id, sae_retry->sae_auth.ptr,
1819 		       sae_retry->sae_auth.len);
1820 	sae_retry->sae_auth_max_retry--;
1821 
1822 	if (TX_SUCCESS != tx_timer_activate(
1823 	    &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer))
1824 		goto free_and_deactivate_timer;
1825 	return;
1826 
1827 free_and_deactivate_timer:
1828 	lim_sae_auth_cleanup_retry(mac_ctx, session_entry->vdev_id);
1829 }
1830 
1831 /**
1832  * lim_process_auth_retry_timer()- function to Retry Auth when auth timeout
1833  * occurs
1834  * @mac_ctx:pointer to global mac
1835  *
1836  * Return: void
1837  */
lim_process_auth_retry_timer(struct mac_context * mac_ctx)1838 static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
1839 {
1840 	struct pe_session *session_entry;
1841 	tAniAuthType auth_type;
1842 	tLimTimers *lim_timers = &mac_ctx->lim.lim_timers;
1843 	uint16_t pe_session_id =
1844 		lim_timers->g_lim_periodic_auth_retry_timer.sessionId;
1845 
1846 	session_entry = pe_find_session_by_session_id(mac_ctx, pe_session_id);
1847 	if (!session_entry) {
1848 		pe_err("session does not exist for pe_session_id: %d",
1849 		       pe_session_id);
1850 		return;
1851 	}
1852 
1853 	/** For WPA3 SAE gLimAuthFailureTimer is not running hence
1854 	 *  we don't enter in below "if" block in case of wpa3 sae
1855 	 */
1856 	if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer) &&
1857 	    (session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) &&
1858 	     (LIM_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) {
1859 		/*
1860 		 * Send the auth retry only in case we have received ack failure
1861 		 * else just restart the retry timer.
1862 		 */
1863 		if (((mac_ctx->auth_ack_status == LIM_ACK_RCD_FAILURE) ||
1864 		     (mac_ctx->auth_ack_status == LIM_TX_FAILED)) &&
1865 		      mac_ctx->lim.gpLimMlmAuthReq) {
1866 			tSirMacAuthFrameBody *auth_frame;
1867 
1868 			auth_type = mac_ctx->lim.gpLimMlmAuthReq->authType;
1869 
1870 			auth_frame = qdf_mem_malloc(sizeof(*auth_frame));
1871 			if (!auth_frame) {
1872 				pe_err("malloc failed for auth_frame");
1873 				return;
1874 			}
1875 
1876 			/* Prepare & send Authentication frame */
1877 			if (session_entry->sae_pmk_cached &&
1878 			    auth_type == eSIR_AUTH_TYPE_SAE)
1879 				auth_frame->authAlgoNumber = eSIR_OPEN_SYSTEM;
1880 			else
1881 				auth_frame->authAlgoNumber = (uint8_t)auth_type;
1882 
1883 			auth_frame->authTransactionSeqNumber =
1884 						SIR_MAC_AUTH_FRAME_1;
1885 			auth_frame->authStatusCode = 0;
1886 			pe_debug("Retry Auth");
1887 			lim_increase_fils_sequence_number(session_entry);
1888 			lim_send_auth_mgmt_frame(mac_ctx, auth_frame,
1889 				mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
1890 				LIM_NO_WEP_IN_FC, session_entry);
1891 
1892 			qdf_mem_free(auth_frame);
1893 		}
1894 
1895 		lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER);
1896 
1897 		/* Activate Auth Retry timer */
1898 		if (tx_timer_activate
1899 		     (&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer)
1900 			 != TX_SUCCESS)
1901 			pe_err("could not activate Auth Retry failure timer");
1902 
1903 		return;
1904 	}
1905 
1906 	/* Auth retry time out for wpa3 sae */
1907 	lim_handle_sae_auth_timeout(mac_ctx, session_entry);
1908 } /*** lim_process_auth_retry_timer() ***/
1909 
lim_process_auth_failure_timeout(struct mac_context * mac_ctx)1910 void lim_process_auth_failure_timeout(struct mac_context *mac_ctx)
1911 {
1912 	/* fetch the pe_session based on the sessionId */
1913 	struct pe_session *session;
1914 	uint32_t val;
1915 	enum wlan_status_code proto_status_code;
1916 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1917 	host_log_rssi_pkt_type *rssi_log = NULL;
1918 #endif
1919 
1920 	session = pe_find_session_by_session_id(mac_ctx,
1921 			mac_ctx->lim.lim_timers.gLimAuthFailureTimer.sessionId);
1922 	if (!session) {
1923 		pe_err("Session Does not exist for given sessionID");
1924 		return;
1925 	}
1926 
1927 	pe_warn("received AUTH failure timeout in sessionid %d "
1928 		   "limMlmstate %X limSmeState %X",
1929 		session->peSessionId, session->limMlmState,
1930 		session->limSmeState);
1931 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
1932 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_TIMEOUT, session,
1933 				0, AUTH_FAILURE_TIMEOUT);
1934 
1935 	WLAN_HOST_DIAG_LOG_ALLOC(rssi_log, host_log_rssi_pkt_type,
1936 				 LOG_WLAN_RSSI_UPDATE_C);
1937 	if (rssi_log)
1938 		rssi_log->rssi = session->rssi;
1939 	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
1940 #endif
1941 
1942 	switch (session->limMlmState) {
1943 	case eLIM_MLM_WT_AUTH_FRAME2_STATE:
1944 	case eLIM_MLM_WT_AUTH_FRAME4_STATE:
1945 		/*
1946 		 * Requesting STA did not receive next auth frame before Auth
1947 		 * Failure timeout. Issue MLM auth confirm with timeout reason
1948 		 * code. Restore default failure timeout
1949 		 */
1950 		if (QDF_P2P_CLIENT_MODE == session->opmode &&
1951 		    session->defaultAuthFailureTimeout) {
1952 			if (cfg_in_range(CFG_AUTH_FAILURE_TIMEOUT,
1953 					 session->defaultAuthFailureTimeout)) {
1954 				val = session->defaultAuthFailureTimeout;
1955 			} else {
1956 				val = cfg_default(CFG_AUTH_FAILURE_TIMEOUT);
1957 				session->defaultAuthFailureTimeout = val;
1958 			}
1959 			mac_ctx->mlme_cfg->timeouts.auth_failure_timeout = val;
1960 		}
1961 		lim_fill_status_code(SIR_MAC_MGMT_AUTH,
1962 				     mac_ctx->auth_ack_status,
1963 				     &proto_status_code);
1964 		lim_restore_from_auth_state(mac_ctx,
1965 				eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
1966 				proto_status_code, session);
1967 		mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
1968 		break;
1969 	default:
1970 		/*
1971 		 * Auth failure timer should not have timed out
1972 		 * in states other than wt_auth_frame2/4
1973 		 */
1974 		pe_err("received unexpected AUTH failure timeout in state %X",
1975 			session->limMlmState);
1976 		lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
1977 		break;
1978 	}
1979 }
1980 
1981 /**
1982  * lim_process_auth_rsp_timeout() - This function is called to process Min
1983  * Channel Timeout during channel scan.
1984  *
1985  * @mac_ctx:      Pointer to Global MAC structure
1986  *
1987  * This function is called to process Min Channel Timeout during channel scan.
1988  *
1989  * @Return: None
1990  */
1991 static void
lim_process_auth_rsp_timeout(struct mac_context * mac_ctx,uint32_t auth_idx)1992 lim_process_auth_rsp_timeout(struct mac_context *mac_ctx, uint32_t auth_idx)
1993 {
1994 	struct tLimPreAuthNode *auth_node;
1995 	struct pe_session *session;
1996 	uint8_t session_id;
1997 
1998 	auth_node = lim_get_pre_auth_node_from_index(mac_ctx,
1999 				&mac_ctx->lim.gLimPreAuthTimerTable, auth_idx);
2000 	if (!auth_node) {
2001 		pe_warn("Invalid auth node");
2002 		return;
2003 	}
2004 
2005 	session = pe_find_session_by_bssid(mac_ctx, auth_node->peerMacAddr,
2006 					   &session_id);
2007 	if (!session) {
2008 		pe_warn("session does not exist for given BSSID");
2009 		return;
2010 	}
2011 
2012 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2013 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_TIMEOUT,
2014 				session, 0, AUTH_RESPONSE_TIMEOUT);
2015 #endif
2016 
2017 	if (LIM_IS_AP_ROLE(session)) {
2018 		if (auth_node->mlmState != eLIM_MLM_WT_AUTH_FRAME3_STATE) {
2019 			pe_err("received AUTH rsp timeout in unexpected "
2020 				   "state for MAC address: " QDF_MAC_ADDR_FMT,
2021 				QDF_MAC_ADDR_REF(auth_node->peerMacAddr));
2022 		} else {
2023 			auth_node->mlmState = eLIM_MLM_AUTH_RSP_TIMEOUT_STATE;
2024 			auth_node->fTimerStarted = 0;
2025 			pe_debug("AUTH rsp timedout for MAC address "
2026 				   QDF_MAC_ADDR_FMT,
2027 				QDF_MAC_ADDR_REF(auth_node->peerMacAddr));
2028 			/* Change timer to reactivate it in future */
2029 			lim_deactivate_and_change_per_sta_id_timer(mac_ctx,
2030 				eLIM_AUTH_RSP_TIMER, auth_node->authNodeIdx);
2031 			lim_delete_pre_auth_node(mac_ctx,
2032 						 auth_node->peerMacAddr);
2033 		}
2034 	}
2035 }
2036 
lim_process_assoc_failure_timeout(struct mac_context * mac_ctx,uint32_t msg_type)2037 void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
2038 				       uint32_t msg_type)
2039 {
2040 
2041 	tLimMlmAssocCnf mlm_assoc_cnf;
2042 	struct pe_session *session;
2043 	enum wlan_status_code proto_status_code;
2044 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2045 	host_log_rssi_pkt_type *rssi_log = NULL;
2046 #endif
2047 	/*
2048 	 * to fetch the lim/mlm state based on the session_id, use the
2049 	 * below pe_session
2050 	 */
2051 	uint8_t session_id;
2052 
2053 	if (msg_type == LIM_ASSOC)
2054 		session_id =
2055 		    mac_ctx->lim.lim_timers.gLimAssocFailureTimer.sessionId;
2056 	else
2057 		session_id =
2058 		    mac_ctx->lim.lim_timers.gLimReassocFailureTimer.sessionId;
2059 
2060 	session = pe_find_session_by_session_id(mac_ctx, session_id);
2061 	if (!session) {
2062 		pe_err("Session Does not exist for given sessionID");
2063 		return;
2064 	}
2065 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2066 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_TIMEOUT,
2067 				session, 0, 0);
2068 
2069 	WLAN_HOST_DIAG_LOG_ALLOC(rssi_log,
2070 				 host_log_rssi_pkt_type,
2071 				 LOG_WLAN_RSSI_UPDATE_C);
2072 	if (rssi_log)
2073 		rssi_log->rssi = session->rssi;
2074 	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
2075 #endif
2076 
2077 	pe_debug("Re/Association Response not received before timeout");
2078 
2079 	/*
2080 	 * Send Deauth to handle the scenareo where association timeout happened
2081 	 * when device has missed the assoc resp sent by peer.
2082 	 * By sending deauth try to clear the session created on peer device.
2083 	 */
2084 	if (msg_type == LIM_ASSOC &&
2085 	    mlme_get_reconn_after_assoc_timeout_flag(mac_ctx->psoc,
2086 						     session->vdev_id)) {
2087 		pe_debug("vdev: %d skip sending deauth on channel freq %d to BSSID: "
2088 			QDF_MAC_ADDR_FMT, session->vdev_id,
2089 			session->curr_op_freq,
2090 			QDF_MAC_ADDR_REF(session->bssId));
2091 	} else {
2092 		pe_debug("vdev: %d try sending deauth on channel freq %d to BSSID: "
2093 			QDF_MAC_ADDR_FMT, session->vdev_id,
2094 			session->curr_op_freq,
2095 			QDF_MAC_ADDR_REF(session->bssId));
2096 		lim_send_deauth_mgmt_frame(mac_ctx,
2097 					   REASON_UNSPEC_FAILURE,
2098 					   session->bssId, session, false);
2099 	}
2100 	if ((LIM_IS_AP_ROLE(session)) ||
2101 	    ((session->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) &&
2102 	    (session->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) &&
2103 	    (session->limMlmState != eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) {
2104 		/*
2105 		 * Re/Assoc failure timer should not have timedout on AP
2106 		 * or in a state other than wt_re/assoc_response.
2107 		 */
2108 		pe_warn("received unexpected REASSOC failure timeout in state %X for role %d",
2109 			session->limMlmState,
2110 			GET_LIM_SYSTEM_ROLE(session));
2111 		lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
2112 		return;
2113 	}
2114 
2115 	if ((msg_type == LIM_ASSOC) || ((msg_type == LIM_REASSOC)
2116 	     && (session->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) {
2117 		pe_err("(Re)Assoc Failure Timeout occurred");
2118 		session->limMlmState = eLIM_MLM_IDLE_STATE;
2119 		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
2120 			session->peSessionId, session->limMlmState));
2121 		/* Change timer for future activations */
2122 		lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER);
2123 		lim_stop_pmfcomeback_timer(session);
2124 		/*
2125 		 * Free up buffer allocated for JoinReq held by
2126 		 * MLM state machine
2127 		 */
2128 		if (session->pLimMlmJoinReq) {
2129 			qdf_mem_free(session->pLimMlmJoinReq);
2130 			session->pLimMlmJoinReq = NULL;
2131 		}
2132 		/* To remove the preauth node in case of fail to associate */
2133 		if (lim_search_pre_auth_list(mac_ctx, session->bssId)) {
2134 			pe_debug("delete pre auth node for "QDF_MAC_ADDR_FMT,
2135 				QDF_MAC_ADDR_REF(session->bssId));
2136 			lim_delete_pre_auth_node(mac_ctx,
2137 						 session->bssId);
2138 		}
2139 		lim_fill_status_code(SIR_MAC_MGMT_ASSOC_RSP,
2140 				     mac_ctx->assoc_ack_status,
2141 				     &proto_status_code);
2142 
2143 		mlm_assoc_cnf.resultCode = eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE;
2144 		mlm_assoc_cnf.protStatusCode = proto_status_code;
2145 		/* Update PE session Id */
2146 		mlm_assoc_cnf.sessionId = session->peSessionId;
2147 		if (msg_type == LIM_ASSOC) {
2148 			lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
2149 					     (uint32_t *) &mlm_assoc_cnf);
2150 		} else {
2151 			/*
2152 			 * Will come here only in case of 11r, Ese FT
2153 			 * when reassoc rsp is not received and we
2154 			 * receive a reassoc - timesout
2155 			 */
2156 			mlm_assoc_cnf.resultCode =
2157 				eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE;
2158 			lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
2159 					     (uint32_t *) &mlm_assoc_cnf);
2160 		}
2161 	} else {
2162 		/*
2163 		 * Restore pre-reassoc req state.
2164 		 * Set BSSID to currently associated AP address.
2165 		 */
2166 		session->limMlmState = session->limPrevMlmState;
2167 		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
2168 				 session->peSessionId, session->limMlmState));
2169 		lim_restore_pre_reassoc_state(mac_ctx,
2170 				eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE,
2171 				STATUS_UNSPECIFIED_FAILURE, session);
2172 	}
2173 }
2174