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 /*
21 *
22 * This file lim_process_deauth_frame.cc contains the code
23 * for processing Deauthentication Frame.
24 * Author: Chandra Modumudi
25 * Date: 03/24/02
26 * History:-
27 * Date Modified by Modification Information
28 * --------------------------------------------------------------------
29 *
30 */
31 #include "cds_api.h"
32 #include "ani_global.h"
33
34 #include "utils_api.h"
35 #include "lim_types.h"
36 #include "lim_utils.h"
37 #include "lim_assoc_utils.h"
38 #include "lim_security_utils.h"
39 #include "lim_ser_des_utils.h"
40 #include "sch_api.h"
41 #include "lim_send_messages.h"
42 #include "wlan_connectivity_logging.h"
43 #include "cds_ieee80211_common.h"
44
45 /**
46 * lim_process_deauth_frame
47 *
48 ***FUNCTION:
49 * This function is called by limProcessMessageQueue() upon
50 * Deauthentication frame reception.
51 *
52 ***LOGIC:
53 *
54 ***ASSUMPTIONS:
55 *
56 ***NOTE:
57 *
58 * @param mac - Pointer to Global MAC structure
59 * @param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs
60 * @return None
61 */
62
63 void
lim_process_deauth_frame(struct mac_context * mac,uint8_t * pRxPacketInfo,struct pe_session * pe_session)64 lim_process_deauth_frame(struct mac_context *mac, uint8_t *pRxPacketInfo,
65 struct pe_session *pe_session)
66 {
67 uint8_t *pBody;
68 uint16_t reasonCode;
69 tpSirMacMgmtHdr pHdr;
70 struct pe_session *pRoamSessionEntry = NULL;
71 uint8_t roamSessionId;
72 uint32_t frameLen;
73 int32_t frame_rssi;
74
75 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
76
77 pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
78 frame_rssi = (int32_t)WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo);
79 frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
80 if (frameLen < sizeof(reasonCode)) {
81 pe_err("Deauth Frame length invalid %d", frameLen);
82 return ;
83 }
84
85 if (LIM_IS_STA_ROLE(pe_session) &&
86 wlan_drop_mgmt_frame_on_link_removal(pe_session->vdev)) {
87 pe_debug("Received deauth Frame when link removed on vdev %d",
88 wlan_vdev_get_id(pe_session->vdev));
89 return;
90 }
91
92 if (LIM_IS_STA_ROLE(pe_session) &&
93 !(lim_is_sb_disconnect_allowed(pe_session) ||
94 (pe_session->limMlmState == eLIM_MLM_WT_SAE_AUTH_STATE &&
95 pe_session->limSmeState == eLIM_SME_WT_AUTH_STATE))) {
96 /*Every 15th deauth frame will be logged in kmsg */
97 if (!(mac->lim.deauthMsgCnt & 0xF)) {
98 pe_debug("received Deauth frame in DEAUTH_WT_STATE"
99 "(already processing previously received DEAUTH frame)"
100 "Dropping this.. Deauth Failed %d",
101 ++mac->lim.deauthMsgCnt);
102 } else {
103 mac->lim.deauthMsgCnt++;
104 }
105 return;
106 }
107
108 if (IEEE80211_IS_MULTICAST(pHdr->sa)) {
109 /* Received Deauth frame from a BC/MC address */
110 /* Log error and ignore it */
111 pe_debug("received Deauth frame from a BC/MC address");
112 return;
113 }
114
115 if (IEEE80211_IS_MULTICAST(pHdr->da) &&
116 !QDF_IS_ADDR_BROADCAST(pHdr->da)) {
117 /* Received Deauth frame for a MC address */
118 /* Log error and ignore it */
119 pe_debug("received Deauth frame for a MC address");
120 return;
121 }
122 if (!lim_validate_received_frame_a1_addr(mac,
123 pHdr->da, pe_session)) {
124 pe_err("rx frame doesn't have valid a1 address, drop it");
125 return;
126 }
127
128 /* PMF: If this session is a PMF session, then ensure that this frame was protected */
129 if (is_mgmt_protected(pe_session->vdev_id, (const uint8_t *)pHdr->sa) &&
130 (WMA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) &
131 DPU_FEEDBACK_UNPROTECTED_ERROR)) {
132 pe_debug("received an unprotected deauth from AP");
133 /*
134 * When 11w offload is enabled then
135 * firmware should not fwd this frame
136 */
137 if (LIM_IS_STA_ROLE(pe_session) && mac->pmf_offload) {
138 pe_err("11w offload is enable,unprotected deauth is not expected");
139 return;
140 }
141
142 /* If the frame received is unprotected, forward it to the supplicant to initiate */
143 /* an SA query */
144
145 /* send the unprotected frame indication to SME */
146 lim_send_sme_unprotected_mgmt_frame_ind(mac, pHdr->fc.subType,
147 (uint8_t *) pHdr,
148 (frameLen +
149 sizeof(tSirMacMgmtHdr)),
150 pe_session->smeSessionId,
151 pe_session);
152 return;
153 }
154
155 /* Get reasonCode from Deauthentication frame body */
156 reasonCode = sir_read_u16(pBody);
157
158 pe_nofl_rl_info("Deauth RX: vdev %d from "QDF_MAC_ADDR_FMT" for "QDF_MAC_ADDR_FMT" RSSI = %d reason %d mlm state = %d, sme state = %d systemrole = %d ",
159 pe_session->vdev_id, QDF_MAC_ADDR_REF(pHdr->sa),
160 QDF_MAC_ADDR_REF(pHdr->da), frame_rssi,
161 reasonCode, pe_session->limMlmState,
162 pe_session->limSmeState,
163 GET_LIM_SYSTEM_ROLE(pe_session));
164
165 lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_FRAME_EVENT,
166 pe_session, 0, reasonCode);
167
168 lim_cp_stats_cstats_log_deauth_evt(pe_session, CSTATS_DIR_RX,
169 reasonCode);
170
171 if (lim_check_disassoc_deauth_ack_pending(mac, (uint8_t *) pHdr->sa)) {
172 pe_debug("Ignore the Deauth received, while waiting for ack of "
173 "disassoc/deauth");
174 lim_clean_up_disassoc_deauth_req(mac, (uint8_t *) pHdr->sa, 1);
175 wlan_connectivity_mgmt_event(mac->psoc, (struct wlan_frame_hdr *)pHdr,
176 pe_session->vdev_id, reasonCode,
177 0, frame_rssi, 0, 0, 0, 0,
178 WLAN_DEAUTH_RX);
179 return;
180 }
181
182 if (LIM_IS_AP_ROLE(pe_session)) {
183 switch (reasonCode) {
184 case REASON_UNSPEC_FAILURE:
185 case REASON_DEAUTH_NETWORK_LEAVING:
186 /* Valid reasonCode in received Deauthentication frame */
187 break;
188
189 default:
190 /* Invalid reasonCode in received Deauthentication frame */
191 /* Log error and ignore the frame */
192 pe_err("received Deauth frame with invalid reasonCode %d from "
193 QDF_MAC_ADDR_FMT, reasonCode,
194 QDF_MAC_ADDR_REF(pHdr->sa));
195
196 break;
197 }
198 } else if (LIM_IS_STA_ROLE(pe_session)) {
199 switch (reasonCode) {
200 case REASON_UNSPEC_FAILURE:
201 case REASON_PREV_AUTH_NOT_VALID:
202 case REASON_DEAUTH_NETWORK_LEAVING:
203 case REASON_CLASS2_FRAME_FROM_NON_AUTH_STA:
204 case REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA:
205 case REASON_STA_NOT_AUTHENTICATED:
206 /* Valid reasonCode in received Deauth frame */
207 break;
208
209 default:
210 /* Invalid reasonCode in received Deauth frame */
211 /* Log error and ignore the frame */
212 pe_err("received Deauth frame with invalid reasonCode %d from "
213 QDF_MAC_ADDR_FMT, reasonCode,
214 QDF_MAC_ADDR_REF(pHdr->sa));
215
216 break;
217 }
218 } else {
219 /* Received Deauth frame un-known role. Log and ignore it */
220 pe_err("received Deauth frame with reasonCode %d in role %d from "
221 QDF_MAC_ADDR_FMT, reasonCode,
222 GET_LIM_SYSTEM_ROLE(pe_session),
223 QDF_MAC_ADDR_REF(pHdr->sa));
224
225 return;
226 }
227
228 /** If we are in the middle of ReAssoc, a few things could happen:
229 * - STA is reassociating to current AP, and receives deauth from:
230 * a) current AP
231 * b) other AP
232 * - STA is reassociating to a new AP, and receives deauth from:
233 * c) current AP
234 * d) reassoc AP
235 * e) other AP
236 *
237 * The logic is:
238 * 1) If rcv deauth from an AP other than the one we're trying to
239 * reassociate with, then drop the deauth frame (case b, c, e)
240 * 2) If rcv deauth from the "new" reassoc AP (case d), then restore
241 * context with previous AP and send SME_REASSOC_RSP failure.
242 * 3) If rcv deauth from the reassoc AP, which is also the same
243 * AP we're currently associated with (case a), then proceed
244 * with normal deauth processing.
245 */
246 pRoamSessionEntry =
247 pe_find_session_by_bssid(mac, pe_session->limReAssocbssId,
248 &roamSessionId);
249
250 if (lim_is_reassoc_in_progress(mac, pe_session) ||
251 lim_is_reassoc_in_progress(mac, pRoamSessionEntry) ||
252 MLME_IS_ROAMING_IN_PROG(mac->psoc, pe_session->vdev_id)) {
253 /*
254 * For LFR3, the roaming bssid is not known during ROAM_START,
255 * so check if the deauth is received from current AP when
256 * roaming is being done in the firmware
257 */
258 if (MLME_IS_ROAMING_IN_PROG(mac->psoc, pe_session->vdev_id) &&
259 IS_CURRENT_BSSID(mac, pHdr->sa, pe_session)) {
260 pe_debug("LFR3: Drop deauth frame from connected AP");
261 /*
262 * recvd_deauth_while_roaming will be stored in the
263 * current AP session amd if roaming has been aborted
264 * for some reason and come back to same AP, then issue
265 * a disconnect internally if this flag is true. There
266 * is no need to reset this flag to false, because if
267 * roaming succeeds, then this session gets deleted and
268 * new session is created.
269 */
270 pe_session->recvd_deauth_while_roaming = true;
271 pe_session->deauth_disassoc_rc = reasonCode;
272 return;
273 }
274 if (!IS_REASSOC_BSSID(mac, pHdr->sa, pe_session)) {
275 pe_debug("Rcv Deauth from unknown/different "
276 "AP while ReAssoc. Ignore " QDF_MAC_ADDR_FMT
277 "limReAssocbssId : " QDF_MAC_ADDR_FMT,
278 QDF_MAC_ADDR_REF(pHdr->sa),
279 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId));
280 return;
281 }
282
283 /** Received deauth from the new AP to which we tried to ReAssociate.
284 * Drop ReAssoc and Restore the Previous context( current connected AP).
285 */
286 if (!IS_CURRENT_BSSID(mac, pHdr->sa, pe_session)) {
287 pe_debug("received DeAuth from the New AP to "
288 "which ReAssoc is sent " QDF_MAC_ADDR_FMT
289 "pe_session->bssId: " QDF_MAC_ADDR_FMT,
290 QDF_MAC_ADDR_REF(pHdr->sa),
291 QDF_MAC_ADDR_REF(pe_session->bssId));
292
293 lim_restore_pre_reassoc_state(mac,
294 eSIR_SME_REASSOC_REFUSED,
295 reasonCode,
296 pe_session);
297 return;
298 }
299 }
300
301 /* If received DeAuth from AP other than the one we're trying to join with
302 * nor associated with, then ignore deauth and delete Pre-auth entry.
303 */
304 if (!LIM_IS_AP_ROLE(pe_session)) {
305 if (!IS_CURRENT_BSSID(mac, pHdr->bssId, pe_session)) {
306 pe_err("received DeAuth from an AP other "
307 "than we're trying to join. Ignore. "
308 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(pHdr->sa));
309
310 if (lim_search_pre_auth_list(mac, pHdr->sa)) {
311 pe_debug("Preauth entry exist. Deleting");
312 lim_delete_pre_auth_node(mac, pHdr->sa);
313 }
314 return;
315 }
316 }
317
318 lim_extract_ies_from_deauth_disassoc(pe_session, (uint8_t *)pHdr,
319 WMA_GET_RX_MPDU_LEN(pRxPacketInfo));
320 wlan_connectivity_mgmt_event(mac->psoc, (struct wlan_frame_hdr *)pHdr,
321 pe_session->vdev_id, reasonCode,
322 0, frame_rssi, 0, 0, 0, 0,
323 WLAN_DEAUTH_RX);
324
325 lim_perform_deauth(mac, pe_session, reasonCode, pHdr->sa,
326 frame_rssi);
327
328 if (mac->mlme_cfg->gen.fatal_event_trigger &&
329 (reasonCode != REASON_UNSPEC_FAILURE &&
330 reasonCode != REASON_DEAUTH_NETWORK_LEAVING &&
331 reasonCode != REASON_DISASSOC_NETWORK_LEAVING)) {
332 cds_flush_logs(WLAN_LOG_TYPE_FATAL,
333 WLAN_LOG_INDICATOR_HOST_DRIVER,
334 WLAN_LOG_REASON_DISCONNECT,
335 false, false);
336 }
337
338 } /*** end lim_process_deauth_frame() ***/
339
340 #ifdef WLAN_FEATURE_SAE
341 /*
342 * lim_process_sae_auth_msg() - Process auth msg after receiving deauth
343 * @mac_ctx: Global MAC context
344 * @pe_session: PE session entry pointer
345 * @addr: peer address/ source address
346 *
347 * Return: None
348 */
lim_process_sae_auth_msg(struct mac_context * mac_ctx,struct pe_session * pe_session,tSirMacAddr addr)349 static void lim_process_sae_auth_msg(struct mac_context *mac_ctx,
350 struct pe_session *pe_session,
351 tSirMacAddr addr)
352 {
353 struct sir_sae_msg *sae_msg;
354
355 sae_msg = qdf_mem_malloc(sizeof(*sae_msg));
356 if (!sae_msg)
357 return;
358
359 sae_msg->vdev_id = pe_session->vdev_id;
360 sae_msg->sae_status = STATUS_UNSPECIFIED_FAILURE;
361 sae_msg->result_code = eSIR_SME_AUTH_REFUSED;
362 qdf_mem_copy(sae_msg->peer_mac_addr, addr, QDF_MAC_ADDR_SIZE);
363 lim_process_sae_msg(mac_ctx, sae_msg);
364
365 qdf_mem_free(sae_msg);
366 }
367 #else
lim_process_sae_auth_msg(struct mac_context * mac_ctx,struct pe_session * pe_session,tSirMacAddr addr)368 static inline void lim_process_sae_auth_msg(struct mac_context *mac_ctx,
369 struct pe_session *pe_session,
370 tSirMacAddr addr)
371 {}
372 #endif
373
lim_perform_deauth(struct mac_context * mac_ctx,struct pe_session * pe_session,uint16_t rc,tSirMacAddr addr,int32_t frame_rssi)374 void lim_perform_deauth(struct mac_context *mac_ctx, struct pe_session *pe_session,
375 uint16_t rc, tSirMacAddr addr, int32_t frame_rssi)
376 {
377 tLimMlmDeauthInd mlmDeauthInd;
378 tLimMlmAssocCnf mlmAssocCnf;
379 uint16_t aid;
380 tpDphHashNode sta_ds;
381 tpSirAssocRsp assoc_rsp;
382
383 sta_ds = dph_lookup_hash_entry(mac_ctx, addr, &aid,
384 &pe_session->dph.dphHashTable);
385 if (!sta_ds) {
386 pe_debug("Hash entry not found");
387 return;
388 }
389 /* Check for pre-assoc states */
390 switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
391 case eLIM_STA_ROLE:
392 switch (pe_session->limMlmState) {
393 case eLIM_MLM_WT_AUTH_FRAME2_STATE:
394 /**
395 * AP sent Deauth frame while waiting
396 * for Auth frame2. Report Auth failure
397 * to SME.
398 */
399
400 pe_debug("received Deauth frame state %X with failure "
401 "code %d from " QDF_MAC_ADDR_FMT,
402 pe_session->limMlmState, rc,
403 QDF_MAC_ADDR_REF(addr));
404
405 lim_restore_from_auth_state(mac_ctx,
406 eSIR_SME_DEAUTH_WHILE_JOIN,
407 rc, pe_session);
408
409 return;
410
411 case eLIM_MLM_AUTHENTICATED_STATE:
412 pe_debug("received Deauth frame state %X with "
413 "reasonCode=%d from " QDF_MAC_ADDR_FMT,
414 pe_session->limMlmState, rc,
415 QDF_MAC_ADDR_REF(addr));
416 /* / Issue Deauth Indication to SME. */
417 qdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
418 addr, sizeof(tSirMacAddr));
419 mlmDeauthInd.reasonCode = rc;
420
421 pe_session->limMlmState = eLIM_MLM_IDLE_STATE;
422 MTRACE(mac_trace
423 (mac_ctx, TRACE_CODE_MLM_STATE,
424 pe_session->peSessionId,
425 pe_session->limMlmState));
426
427 lim_post_sme_message(mac_ctx,
428 LIM_MLM_DEAUTH_IND,
429 (uint32_t *) &mlmDeauthInd);
430 return;
431
432 case eLIM_MLM_WT_ASSOC_RSP_STATE:
433 /**
434 * AP may have 'aged-out' our Pre-auth
435 * context. Delete local pre-auth context
436 * if any and issue ASSOC_CNF to SME.
437 */
438 pe_debug("received Deauth frame state %X with "
439 "reasonCode=%d from " QDF_MAC_ADDR_FMT,
440 pe_session->limMlmState, rc,
441 QDF_MAC_ADDR_REF(addr));
442 if (lim_search_pre_auth_list(mac_ctx, addr))
443 lim_delete_pre_auth_node(mac_ctx, addr);
444
445 lim_stop_pmfcomeback_timer(pe_session);
446 if (pe_session->pLimMlmJoinReq) {
447 qdf_mem_free(pe_session->pLimMlmJoinReq);
448 pe_session->pLimMlmJoinReq = NULL;
449 }
450
451 mlmAssocCnf.resultCode = eSIR_SME_DEAUTH_WHILE_JOIN;
452 mlmAssocCnf.protStatusCode = rc;
453
454 /* PE session Id */
455 mlmAssocCnf.sessionId = pe_session->peSessionId;
456
457 pe_session->limMlmState =
458 pe_session->limPrevMlmState;
459 MTRACE(mac_trace
460 (mac_ctx, TRACE_CODE_MLM_STATE,
461 pe_session->peSessionId,
462 pe_session->limMlmState));
463
464 /* Deactivate Association response timeout */
465 lim_deactivate_and_change_timer(mac_ctx,
466 eLIM_ASSOC_FAIL_TIMER);
467
468 lim_post_sme_message(mac_ctx,
469 LIM_MLM_ASSOC_CNF,
470 (uint32_t *) &mlmAssocCnf);
471
472 return;
473
474 case eLIM_MLM_WT_ADD_STA_RSP_STATE:
475 pe_session->fDeauthReceived = true;
476 pe_debug("Received Deauth frame in state %X with Reason "
477 "Code %d from Peer" QDF_MAC_ADDR_FMT,
478 pe_session->limMlmState, rc,
479 QDF_MAC_ADDR_REF(addr));
480 return;
481
482 case eLIM_MLM_IDLE_STATE:
483 case eLIM_MLM_LINK_ESTABLISHED_STATE:
484 #ifdef FEATURE_WLAN_TDLS
485 if ((sta_ds)
486 && (STA_ENTRY_TDLS_PEER == sta_ds->staType)) {
487 pe_err("received Deauth frame in state %X with "
488 "reason code %d from Tdls peer"
489 QDF_MAC_ADDR_FMT,
490 pe_session->limMlmState, rc,
491 QDF_MAC_ADDR_REF(addr));
492 lim_send_sme_tdls_del_sta_ind(mac_ctx, sta_ds,
493 pe_session,
494 rc);
495 return;
496 } else {
497
498 /*
499 * Delete all the TDLS peers only if Deauth
500 * is received from the AP
501 */
502 if (IS_CURRENT_BSSID(mac_ctx, addr, pe_session))
503 lim_delete_tdls_peers(mac_ctx, pe_session);
504 #endif
505 /**
506 * This could be Deauthentication frame from
507 * a BSS with which pre-authentication was
508 * performed. Delete Pre-auth entry if found.
509 */
510 if (lim_search_pre_auth_list(mac_ctx, addr))
511 lim_delete_pre_auth_node(mac_ctx, addr);
512 #ifdef FEATURE_WLAN_TDLS
513 }
514 #endif
515 break;
516
517 case eLIM_MLM_WT_REASSOC_RSP_STATE:
518 pe_err("received Deauth frame state %X with "
519 "reasonCode=%d from " QDF_MAC_ADDR_FMT,
520 pe_session->limMlmState, rc,
521 QDF_MAC_ADDR_REF(addr));
522 break;
523
524 case eLIM_MLM_WT_FT_REASSOC_RSP_STATE:
525 pe_err("received Deauth frame in FT state %X with "
526 "reasonCode=%d from " QDF_MAC_ADDR_FMT,
527 pe_session->limMlmState, rc,
528 QDF_MAC_ADDR_REF(addr));
529 break;
530
531 case eLIM_MLM_WT_SAE_AUTH_STATE:
532 pe_debug("received Deauth frame state %X with "
533 "reasonCode=%d from " QDF_MAC_ADDR_FMT,
534 pe_session->limMlmState, rc,
535 QDF_MAC_ADDR_REF(addr));
536
537 /* this will be treated as SAE authenticaton failure
538 * and connect failure to userspace.
539 */
540 lim_process_sae_auth_msg(mac_ctx, pe_session, addr);
541 return;
542
543 default:
544 pe_err("received Deauth frame in state %X with "
545 "reasonCode=%d from " QDF_MAC_ADDR_FMT,
546 pe_session->limMlmState, rc,
547 QDF_MAC_ADDR_REF(addr));
548 return;
549 }
550 break;
551
552 case eLIM_AP_ROLE:
553 break;
554
555 default:
556 return;
557 } /* end switch (mac->lim.gLimSystemRole) */
558
559 /**
560 * Extract 'associated' context for STA, if any.
561 * This is maintained by DPH and created by LIM.
562 */
563 if (!sta_ds) {
564 pe_err("sta_ds is NULL");
565 return;
566 }
567
568 if ((sta_ds->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
569 (sta_ds->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE) ||
570 sta_ds->sta_deletion_in_progress) {
571 /**
572 * Already in the process of deleting context for the peer
573 * and received Deauthentication frame. Log and Ignore.
574 */
575 pe_debug("Deletion is in progress (%d) for peer:"QDF_MAC_ADDR_FMT" in mlmState %d",
576 sta_ds->sta_deletion_in_progress,
577 QDF_MAC_ADDR_REF(addr),
578 sta_ds->mlmStaContext.mlmState);
579 return;
580 }
581 sta_ds->mlmStaContext.disassocReason = rc;
582 sta_ds->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH;
583 sta_ds->sta_deletion_in_progress = true;
584
585 /* / Issue Deauth Indication to SME. */
586 qdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
587 sta_ds->staAddr, sizeof(tSirMacAddr));
588 mlmDeauthInd.reasonCode =
589 (uint8_t) sta_ds->mlmStaContext.disassocReason;
590 mlmDeauthInd.deauthTrigger = eLIM_PEER_ENTITY_DEAUTH;
591
592 /*
593 * If we're in the middle of ReAssoc and received deauth from
594 * the ReAssoc AP, then notify SME by sending REASSOC_RSP with
595 * failure result code. SME will post the disconnect to the
596 * supplicant and the latter would start a fresh assoc.
597 */
598 if (lim_is_reassoc_in_progress(mac_ctx, pe_session)) {
599 /**
600 * AP may have 'aged-out' our Pre-auth
601 * context. Delete local pre-auth context
602 * if any and issue REASSOC_CNF to SME.
603 */
604 if (lim_search_pre_auth_list(mac_ctx, addr))
605 lim_delete_pre_auth_node(mac_ctx, addr);
606
607 if (pe_session->limAssocResponseData) {
608 assoc_rsp = (tpSirAssocRsp) pe_session->
609 limAssocResponseData;
610 qdf_mem_free(assoc_rsp->sha384_ft_subelem.gtk);
611 qdf_mem_free(assoc_rsp->sha384_ft_subelem.igtk);
612 qdf_mem_free(pe_session->limAssocResponseData);
613 pe_session->limAssocResponseData = NULL;
614 }
615
616 pe_debug("Rcv Deauth from ReAssoc AP Issue REASSOC_CNF");
617 /*
618 * TODO: Instead of overloading eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE
619 * it would have been good to define/use a different failure type.
620 * Using eSIR_SME_FT_REASSOC_FAILURE does not seem to clean-up
621 * properly and we end up seeing "transmit queue timeout".
622 */
623 lim_post_reassoc_failure(mac_ctx,
624 eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE,
625 STATUS_UNSPECIFIED_FAILURE,
626 pe_session);
627 return;
628 }
629 /* reset the deauthMsgCnt here since we are able to Process
630 * the deauth frame and sending up the indication as well */
631 if (mac_ctx->lim.deauthMsgCnt != 0) {
632 mac_ctx->lim.deauthMsgCnt = 0;
633 }
634 if (LIM_IS_STA_ROLE(pe_session))
635 wma_tx_abort(pe_session->smeSessionId);
636
637 lim_update_lost_link_info(mac_ctx, pe_session, frame_rssi);
638
639 /* / Deauthentication from peer MAC entity */
640 if (LIM_IS_STA_ROLE(pe_session))
641 lim_post_sme_message(mac_ctx, LIM_MLM_DEAUTH_IND,
642 (uint32_t *) &mlmDeauthInd);
643
644 /* send eWNI_SME_DEAUTH_IND to SME */
645 lim_send_sme_deauth_ind(mac_ctx, sta_ds, pe_session);
646 return;
647
648 }
649