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