1 /*
2 * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 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 * DOC: lim_reassoc_utils.c
22 *
23 * Host based roaming re-association utilities
24 */
25
26 #include "cds_api.h"
27 #include "ani_global.h"
28 #include "wni_api.h"
29 #include "sir_common.h"
30
31 #include "wni_cfg.h"
32
33 #include "sch_api.h"
34 #include "utils_api.h"
35 #include "lim_utils.h"
36 #include "lim_assoc_utils.h"
37 #include "lim_security_utils.h"
38 #include "lim_ser_des_utils.h"
39 #include "lim_admit_control.h"
40 #include "lim_send_messages.h"
41 #include "lim_ft_defs.h"
42 #include "lim_session.h"
43 #include "lim_process_fils.h"
44
45 #include "qdf_types.h"
46 #include "wma_types.h"
47 #include "lim_types.h"
48
49 /**
50 * lim_update_re_assoc_globals() - Update reassoc global data
51 * @mac: Global MAC context
52 * @pAssocRsp: Reassociation response data
53 * @pe_session: PE Session
54 *
55 * This function is called to Update the Globals (LIM) during ReAssoc.
56 *
57 * Return: None
58 */
59
lim_update_re_assoc_globals(struct mac_context * mac,tpSirAssocRsp pAssocRsp,struct pe_session * pe_session)60 void lim_update_re_assoc_globals(struct mac_context *mac, tpSirAssocRsp pAssocRsp,
61 struct pe_session *pe_session)
62 {
63 /* Update the current Bss Information */
64 qdf_mem_copy(pe_session->bssId,
65 pe_session->limReAssocbssId, sizeof(tSirMacAddr));
66 pe_session->curr_op_freq = pe_session->lim_reassoc_chan_freq;
67 pe_session->htSecondaryChannelOffset =
68 pe_session->reAssocHtSupportedChannelWidthSet;
69 pe_session->htRecommendedTxWidthSet =
70 pe_session->reAssocHtRecommendedTxWidthSet;
71 pe_session->htSecondaryChannelOffset =
72 pe_session->reAssocHtSecondaryChannelOffset;
73 pe_session->limCurrentBssCaps = pe_session->limReassocBssCaps;
74 pe_session->limCurrentBssQosCaps =
75 pe_session->limReassocBssQosCaps;
76
77 qdf_mem_copy((uint8_t *) &pe_session->ssId,
78 (uint8_t *) &pe_session->limReassocSSID,
79 pe_session->limReassocSSID.length + 1);
80
81 /* Store assigned AID for TIM processing */
82 pe_session->limAID = pAssocRsp->aid & 0x3FFF;
83 /** Set the State Back to ReAssoc Rsp*/
84 pe_session->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
85 MTRACE(mac_trace
86 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
87 pe_session->limMlmState));
88
89 }
90
91 /**
92 * @lim_handle_del_bss_in_re_assoc_context() - DEL BSS during reassociation
93 * @mac: Global MAC Context
94 * @sta: Station Hash entry
95 * @pe_session: PE Session
96 *
97 * While Processing the ReAssociation Response Frame in STA,
98 * a.immediately after receiving the Reassoc Response the RxCleanUp is
99 * being issued and the end of DelBSS the new BSS is being added.
100 *
101 * b. If an AP rejects the ReAssociation (Disassoc/Deauth) with some context
102 * change, We need to update CSR with ReAssocCNF Response with the
103 * ReAssoc Fail and the reason Code, that is also being handled in the
104 * DELBSS context only
105 *
106 * Return: None
107 */
lim_handle_del_bss_in_re_assoc_context(struct mac_context * mac,tpDphHashNode sta,struct pe_session * pe_session)108 void lim_handle_del_bss_in_re_assoc_context(struct mac_context *mac,
109 tpDphHashNode sta, struct pe_session *pe_session)
110 {
111 tLimMlmReassocCnf mlmReassocCnf;
112 struct bss_description *bss_desc;
113 /*
114 * Skipped the DeleteDPH Hash Entry as we need it for the new BSS
115 * Set the MlmState to IDLE
116 */
117 pe_session->limMlmState = eLIM_MLM_IDLE_STATE;
118 /* Update PE session Id */
119 mlmReassocCnf.sessionId = pe_session->peSessionId;
120 switch (pe_session->limSmeState) {
121 case eLIM_SME_WT_REASSOC_STATE:
122 {
123 tpSirAssocRsp assocRsp;
124 tpDphHashNode sta;
125 QDF_STATUS retStatus = QDF_STATUS_SUCCESS;
126 tpSchBeaconStruct beacon_struct;
127
128 beacon_struct = qdf_mem_malloc(sizeof(tSchBeaconStruct));
129 if (!beacon_struct) {
130 mlmReassocCnf.resultCode =
131 eSIR_SME_RESOURCES_UNAVAILABLE;
132 mlmReassocCnf.protStatusCode =
133 STATUS_UNSPECIFIED_FAILURE;
134 lim_delete_dph_hash_entry(mac, pe_session->bssId,
135 DPH_STA_HASH_INDEX_PEER, pe_session);
136 goto error;
137 }
138 /* Delete the older STA Table entry */
139 lim_delete_dph_hash_entry(mac, pe_session->bssId,
140 DPH_STA_HASH_INDEX_PEER, pe_session);
141 /*
142 * Add an entry for AP to hash table
143 * maintained by DPH module
144 */
145 sta = dph_add_hash_entry(mac,
146 pe_session->limReAssocbssId,
147 DPH_STA_HASH_INDEX_PEER,
148 &pe_session->dph.dphHashTable);
149 if (!sta) {
150 /* Could not add hash table entry */
151 pe_err("could not add hash entry at DPH for BSSID: "QDF_MAC_ADDR_FMT,
152 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId));
153 mlmReassocCnf.resultCode =
154 eSIR_SME_RESOURCES_UNAVAILABLE;
155 mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS;
156 qdf_mem_free(beacon_struct);
157 goto error;
158 }
159 /*
160 * While Processing the ReAssoc Response Frame the Rsp Frame
161 * is being stored to be used here for sending ADDBSS
162 */
163 assocRsp =
164 (tpSirAssocRsp) pe_session->limAssocResponseData;
165
166 bss_desc = &pe_session->pLimReAssocReq->bssDescription;
167 lim_extract_ap_capabilities(mac,
168 (uint8_t *)bss_desc->ieFields,
169 lim_get_ielen_from_bss_description(bss_desc),
170 beacon_struct);
171
172 lim_update_assoc_sta_datas(mac, sta, assocRsp,
173 pe_session, beacon_struct);
174 lim_update_re_assoc_globals(mac, assocRsp, pe_session);
175 if (mac->lim.gLimProtectionControl !=
176 MLME_FORCE_POLICY_PROTECTION_DISABLE)
177 lim_decide_sta_protection_on_assoc(mac,
178 beacon_struct,
179 pe_session);
180 if (beacon_struct->erpPresent) {
181 if (beacon_struct->erpIEInfo.barkerPreambleMode)
182 pe_session->beaconParams.fShortPreamble = 0;
183 else
184 pe_session->beaconParams.fShortPreamble = 1;
185 }
186 /*
187 * updateBss flag is false, as in this case, PE is first
188 * deleting the existing BSS and then adding a new one
189 */
190 if (QDF_STATUS_SUCCESS !=
191 lim_sta_send_add_bss(mac, assocRsp, beacon_struct,
192 bss_desc,
193 false, pe_session)) {
194 pe_err("Posting ADDBSS in the ReAssocCtx Failed");
195 retStatus = QDF_STATUS_E_FAILURE;
196 }
197 if (retStatus != QDF_STATUS_SUCCESS) {
198 mlmReassocCnf.resultCode =
199 eSIR_SME_RESOURCES_UNAVAILABLE;
200 mlmReassocCnf.protStatusCode =
201 STATUS_UNSPECIFIED_FAILURE;
202 qdf_mem_free(assocRsp);
203 mac->lim.gLimAssocResponseData = NULL;
204 qdf_mem_free(beacon_struct);
205 goto error;
206 }
207 qdf_mem_free(assocRsp->sha384_ft_subelem.gtk);
208 qdf_mem_free(assocRsp->sha384_ft_subelem.igtk);
209 qdf_mem_free(assocRsp);
210 qdf_mem_free(beacon_struct);
211 pe_session->limAssocResponseData = NULL;
212 }
213 break;
214 default:
215 pe_err("DelBss in wrong system Role and SME State");
216 mlmReassocCnf.resultCode = eSIR_SME_REFUSED;
217 mlmReassocCnf.protStatusCode =
218 eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
219 goto error;
220 }
221 return;
222 error:
223 lim_post_sme_message(mac, LIM_MLM_REASSOC_CNF,
224 (uint32_t *) &mlmReassocCnf);
225 }
226
227 /**
228 * @lim_handle_add_bss_in_re_assoc_context() - ADD BSS during reassociation
229 * @mac: Global MAC Context
230 * @sta: Station Hash entry
231 * @pe_session: PE Session
232 *
233 * While Processing the ReAssociation Response Frame in STA,
234 * a. immediately after receiving the Reassoc Response the RxCleanUp is
235 * being issued and the end of DelBSS the new BSS is being added.
236 *
237 * b. If an AP rejects the ReAssociation (Disassoc/Deauth) with some context
238 * change, We need to update CSR with ReAssocCNF Response with the
239 * ReAssoc Fail and the reason Code, that is also being handled in the
240 * DELBSS context only
241 *
242 * Return: None
243 */
lim_handle_add_bss_in_re_assoc_context(struct mac_context * mac,tpDphHashNode sta,struct pe_session * pe_session)244 void lim_handle_add_bss_in_re_assoc_context(struct mac_context *mac,
245 tpDphHashNode sta, struct pe_session *pe_session)
246 {
247 tLimMlmReassocCnf mlmReassocCnf;
248 /** Skipped the DeleteDPH Hash Entry as we need it for the new BSS*/
249 /** Set the MlmState to IDLE*/
250 pe_session->limMlmState = eLIM_MLM_IDLE_STATE;
251 MTRACE(mac_trace
252 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
253 pe_session->limMlmState));
254 switch (pe_session->limSmeState) {
255 case eLIM_SME_WT_REASSOC_STATE: {
256 tpSirAssocRsp assocRsp;
257 tpDphHashNode sta;
258 QDF_STATUS retStatus = QDF_STATUS_SUCCESS;
259 tSchBeaconStruct *pBeaconStruct;
260
261 pBeaconStruct =
262 qdf_mem_malloc(sizeof(tSchBeaconStruct));
263 if (!pBeaconStruct) {
264 mlmReassocCnf.resultCode =
265 eSIR_SME_RESOURCES_UNAVAILABLE;
266 mlmReassocCnf.protStatusCode =
267 eSIR_SME_RESOURCES_UNAVAILABLE;
268 goto Error;
269 }
270 /* Get the AP entry from DPH hash table */
271 sta =
272 dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
273 &pe_session->dph.dphHashTable);
274 if (!sta) {
275 pe_err("Fail to get STA PEER entry from hash");
276 mlmReassocCnf.resultCode =
277 eSIR_SME_RESOURCES_UNAVAILABLE;
278 mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS;
279 qdf_mem_free(pBeaconStruct);
280 goto Error;
281 }
282 /*
283 * While Processing the ReAssoc Response Frame the Rsp Frame
284 * is being stored to be used here for sending ADDBSS
285 */
286 assocRsp =
287 (tpSirAssocRsp) pe_session->limAssocResponseData;
288 lim_extract_ap_capabilities(mac,
289 (uint8_t *)pe_session->pLimReAssocReq->bssDescription.ieFields,
290 lim_get_ielen_from_bss_description
291 (&pe_session->pLimReAssocReq->bssDescription),
292 pBeaconStruct);
293 lim_update_assoc_sta_datas(mac, sta, assocRsp,
294 pe_session, pBeaconStruct);
295 lim_update_re_assoc_globals(mac, assocRsp, pe_session);
296 if (mac->lim.gLimProtectionControl !=
297 MLME_FORCE_POLICY_PROTECTION_DISABLE)
298 lim_decide_sta_protection_on_assoc(mac,
299 pBeaconStruct,
300 pe_session);
301
302 if (pBeaconStruct->erpPresent) {
303 if (pBeaconStruct->erpIEInfo.barkerPreambleMode)
304 pe_session->beaconParams.
305 fShortPreamble = 0;
306 else
307 pe_session->beaconParams.
308 fShortPreamble = 1;
309 }
310
311 pe_session->isNonRoamReassoc = 1;
312 if (QDF_STATUS_SUCCESS !=
313 lim_sta_send_add_bss(mac, assocRsp, pBeaconStruct,
314 &pe_session->pLimReAssocReq->
315 bssDescription, true,
316 pe_session)) {
317 pe_err("Post ADDBSS in the ReAssocCtxt Failed");
318 retStatus = QDF_STATUS_E_FAILURE;
319 }
320 if (retStatus != QDF_STATUS_SUCCESS) {
321 mlmReassocCnf.resultCode =
322 eSIR_SME_RESOURCES_UNAVAILABLE;
323 mlmReassocCnf.protStatusCode =
324 STATUS_UNSPECIFIED_FAILURE;
325 qdf_mem_free(assocRsp);
326 mac->lim.gLimAssocResponseData = NULL;
327 qdf_mem_free(pBeaconStruct);
328 goto Error;
329 }
330 qdf_mem_free(assocRsp->sha384_ft_subelem.gtk);
331 qdf_mem_free(assocRsp->sha384_ft_subelem.igtk);
332 qdf_mem_free(assocRsp);
333 pe_session->limAssocResponseData = NULL;
334 qdf_mem_free(pBeaconStruct);
335 }
336 break;
337 default:
338 pe_err("DelBss in the wrong system Role and SME State");
339 mlmReassocCnf.resultCode = eSIR_SME_REFUSED;
340 mlmReassocCnf.protStatusCode =
341 eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
342 goto Error;
343 }
344 return;
345 Error:
346 lim_post_sme_message(mac, LIM_MLM_REASSOC_CNF,
347 (uint32_t *) &mlmReassocCnf);
348 }
349
350 /**
351 * lim_is_reassoc_in_progress() - Check if reassoiciation is in progress
352 * @mac: Global MAC Context
353 * @pe_session: PE Session
354 *
355 * Return: true When STA is waiting for Reassoc response from AP
356 * else false
357 */
lim_is_reassoc_in_progress(struct mac_context * mac,struct pe_session * pe_session)358 bool lim_is_reassoc_in_progress(struct mac_context *mac, struct pe_session *pe_session)
359 {
360 if (!pe_session)
361 return false;
362
363 if (LIM_IS_STA_ROLE(pe_session) &&
364 (pe_session->limSmeState == eLIM_SME_WT_REASSOC_STATE))
365 return true;
366
367 return false;
368 }
369
370 /**
371 * lim_add_ft_sta_self()- function to add STA once we have connected with a
372 * new AP
373 * @mac_ctx: pointer to global mac structure
374 * @assoc_id: association id for the station connection
375 * @session_entry: pe session entr
376 *
377 * This function is called to add a STA once we have connected with a new
378 * AP, that we have performed an FT to.
379 *
380 * The Add STA Response is created and now after the ADD Bss Is Successful
381 * we add the self sta. We update with the association id from the reassoc
382 * response from the AP.
383 *
384 * Return: QDF_STATUS_SUCCESS on success else QDF_STATUS failure codes
385 */
lim_add_ft_sta_self(struct mac_context * mac_ctx,uint16_t assoc_id,struct pe_session * session_entry)386 QDF_STATUS lim_add_ft_sta_self(struct mac_context *mac_ctx, uint16_t assoc_id,
387 struct pe_session *session_entry)
388 {
389 tpAddStaParams add_sta_params = NULL;
390 QDF_STATUS ret_code = QDF_STATUS_SUCCESS;
391 struct scheduler_msg msg_q = {0};
392 tpDphHashNode sta_ds;
393
394 sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
395 &session_entry->dph.dphHashTable);
396
397 if (!sta_ds) {
398 pe_err("Could not get hash entry at DPH");
399 return QDF_STATUS_E_FAILURE;
400 }
401
402 add_sta_params = session_entry->ftPEContext.pAddStaReq;
403 add_sta_params->assocId = assoc_id;
404 add_sta_params->smesessionId = session_entry->smeSessionId;
405
406 qdf_mem_copy(add_sta_params->supportedRates.supportedMCSSet,
407 sta_ds->supportedRates.supportedMCSSet,
408 SIR_MAC_MAX_SUPPORTED_MCS_SET);
409
410 if (lim_is_fils_connection(session_entry))
411 add_sta_params->no_ptk_4_way = true;
412
413 msg_q.type = WMA_ADD_STA_REQ;
414 msg_q.reserved = 0;
415 msg_q.bodyptr = add_sta_params;
416 msg_q.bodyval = 0;
417
418 pe_debug("Sending WMA_ADD_STA_REQ (aid %d)", add_sta_params->assocId);
419 MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId,
420 msg_q.type));
421
422 session_entry->limPrevMlmState = session_entry->limMlmState;
423 MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
424 session_entry->peSessionId, eLIM_MLM_WT_ADD_STA_RSP_STATE));
425 session_entry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE;
426 ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q);
427 if (QDF_STATUS_SUCCESS != ret_code) {
428 pe_err("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X",
429 ret_code);
430 qdf_mem_free(add_sta_params);
431 }
432
433 session_entry->ftPEContext.pAddStaReq = NULL;
434 return ret_code;
435 }
436
437 /**
438 * lim_restore_pre_reassoc_state() - Restore the pre-association context
439 * @mac: Global MAC Context
440 * @resultCode: Assoc response result
441 * @protStatusCode: Internal protocol status code
442 * @pe_session: PE Session
443 *
444 * This function is called on STA role whenever Reasociation
445 * Response with a reject code is received from AP.
446 * Reassociation failure timer is stopped, Old (or current) AP's
447 * context is restored both at Polaris & software
448 *
449 * Return: None
450 */
451
452 void
lim_restore_pre_reassoc_state(struct mac_context * mac,tSirResultCodes resultCode,uint16_t protStatusCode,struct pe_session * pe_session)453 lim_restore_pre_reassoc_state(struct mac_context *mac,
454 tSirResultCodes resultCode, uint16_t protStatusCode,
455 struct pe_session *pe_session)
456 {
457 tLimMlmReassocCnf mlmReassocCnf;
458
459 pe_debug("sessionid: %d protStatusCode: %d resultCode: %d",
460 pe_session->smeSessionId, protStatusCode, resultCode);
461
462 pe_session->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
463 MTRACE(mac_trace
464 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
465 eLIM_MLM_LINK_ESTABLISHED_STATE));
466
467 /* 'Change' timer for future activations */
468 lim_deactivate_and_change_timer(mac, eLIM_REASSOC_FAIL_TIMER);
469
470 /* @ToDo:Need to Integrate the STOP the Dataxfer to AP from 11H code */
471
472 mlmReassocCnf.resultCode = resultCode;
473 mlmReassocCnf.protStatusCode = protStatusCode;
474 mlmReassocCnf.sessionId = pe_session->peSessionId;
475 lim_post_sme_message(mac,
476 LIM_MLM_REASSOC_CNF, (uint32_t *) &mlmReassocCnf);
477 }
478
479 /**
480 * lim_post_reassoc_failure() - Post failure message to SME
481 * @mac: Global MAC Context
482 * @resultCode: Result Code
483 * @protStatusCode: Protocol Status Code
484 * @pe_session: PE Session
485 *
486 * Return: None
487 */
lim_post_reassoc_failure(struct mac_context * mac,tSirResultCodes resultCode,uint16_t protStatusCode,struct pe_session * pe_session)488 void lim_post_reassoc_failure(struct mac_context *mac,
489 tSirResultCodes resultCode, uint16_t protStatusCode,
490 struct pe_session *pe_session)
491 {
492 tLimMlmReassocCnf mlmReassocCnf;
493
494 pe_session->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
495 MTRACE(mac_trace
496 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
497 eLIM_MLM_LINK_ESTABLISHED_STATE));
498
499 lim_deactivate_and_change_timer(mac, eLIM_REASSOC_FAIL_TIMER);
500
501 mlmReassocCnf.resultCode = resultCode;
502 mlmReassocCnf.protStatusCode = protStatusCode;
503 mlmReassocCnf.sessionId = pe_session->peSessionId;
504 lim_post_sme_message(mac,
505 LIM_MLM_REASSOC_CNF, (uint32_t *) &mlmReassocCnf);
506 }
507
508