1 /* 2 * Copyright (c) 2016-2021 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_ft_preauth.c 22 * 23 * Pre-Authentication implementation for host based roaming 24 */ 25 #include <lim_send_messages.h> 26 #include <lim_types.h> 27 #include <lim_ft.h> 28 #include <lim_ft_defs.h> 29 #include <lim_utils.h> 30 #include <lim_prop_exts_utils.h> 31 #include <lim_assoc_utils.h> 32 #include <lim_session.h> 33 #include <lim_session_utils.h> 34 #include <lim_admit_control.h> 35 #include <wlan_scan_api.h> 36 #include "wma.h" 37 #include "wlan_crypto_global_api.h" 38 39 /** 40 * lim_ft_cleanup_pre_auth_info() - Cleanup preauth related information 41 * @mac: Global MAC Context 42 * @pe_session: PE Session 43 * 44 * This routine is called to free the FT context, session and other 45 * information used during preauth operation. 46 * 47 * Return: None 48 */ 49 void lim_ft_cleanup_pre_auth_info(struct mac_context *mac, 50 struct pe_session *pe_session) 51 { 52 struct pe_session *pReAssocSessionEntry = NULL; 53 uint8_t sessionId = 0; 54 55 if (!pe_session) { 56 pe_err("pe_session is NULL"); 57 return; 58 } 59 60 /* Nothing to be done if the session is not in STA mode */ 61 if (!LIM_IS_STA_ROLE(pe_session)) { 62 pe_err("pe_session is not in STA mode"); 63 return; 64 } 65 66 if (pe_session->ftPEContext.pFTPreAuthReq) { 67 pReAssocSessionEntry = 68 pe_find_session_by_bssid(mac, 69 pe_session->ftPEContext. 70 pFTPreAuthReq->preAuthbssId, 71 &sessionId); 72 73 if (pe_session->ftPEContext.pFTPreAuthReq-> 74 pbssDescription) { 75 qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq-> 76 pbssDescription); 77 pe_session->ftPEContext.pFTPreAuthReq-> 78 pbssDescription = NULL; 79 } 80 qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq); 81 pe_session->ftPEContext.pFTPreAuthReq = NULL; 82 } 83 84 if (pe_session->ftPEContext.pAddBssReq) { 85 qdf_mem_free(pe_session->ftPEContext.pAddBssReq); 86 pe_session->ftPEContext.pAddBssReq = NULL; 87 } 88 89 if (pe_session->ftPEContext.pAddStaReq) { 90 qdf_mem_free(pe_session->ftPEContext.pAddStaReq); 91 pe_session->ftPEContext.pAddStaReq = NULL; 92 } 93 94 /* The session is being deleted, cleanup the contents */ 95 qdf_mem_zero(&pe_session->ftPEContext, sizeof(tftPEContext)); 96 97 /* Delete the session created while handling pre-auth response */ 98 if (pReAssocSessionEntry) { 99 /* If we have successful pre-auth response, then we would have 100 * created a session on which reassoc request will be sent 101 */ 102 if (pReAssocSessionEntry->valid && 103 pReAssocSessionEntry->limSmeState == 104 eLIM_SME_WT_REASSOC_STATE) { 105 pe_debug("Deleting Preauth session(%d)", 106 pReAssocSessionEntry->peSessionId); 107 pe_delete_session(mac, pReAssocSessionEntry); 108 } 109 } 110 } 111 112 /* 113 * lim_process_ft_pre_auth_req() - process ft pre auth req 114 * 115 * @mac_ctx: global mac ctx 116 * @ft_pre_auth_req: ft preauth request 117 * 118 * In this function, we process the FT Pre Auth Req: 119 * We receive Pre-Auth, suspend link, register a call back. In the call back, 120 * we will need to accept frames from the new bssid. Send out the auth req to 121 * new AP. Start timer and when the timer is done or if we receive the Auth 122 * response. We change channel. Resume link 123 * 124 * Return: value to indicate if buffer was consumed 125 */ 126 bool lim_process_ft_pre_auth_req(struct mac_context *mac_ctx, 127 tpSirFTPreAuthReq ft_pre_auth_req) 128 { 129 bool buf_consumed = false; 130 struct pe_session *session; 131 uint8_t session_id; 132 133 if (!ft_pre_auth_req) { 134 pe_err("tSirFTPreAuthReq is NULL"); 135 return buf_consumed; 136 } 137 138 /* Get the current session entry */ 139 session = pe_find_session_by_bssid(mac_ctx, 140 ft_pre_auth_req->currbssId, 141 &session_id); 142 if (!session) { 143 pe_err("Unable to find session for the bssid " 144 QDF_MAC_ADDR_FMT, 145 QDF_MAC_ADDR_REF(ft_pre_auth_req->currbssId)); 146 /* Post the FT Pre Auth Response to SME */ 147 lim_post_ft_pre_auth_rsp(mac_ctx, QDF_STATUS_E_FAILURE, NULL, 0, 148 session); 149 buf_consumed = true; 150 return buf_consumed; 151 } 152 153 /* Nothing to be done if the session is not in STA mode */ 154 if (!LIM_IS_STA_ROLE(session)) { 155 pe_err("session is not in STA mode"); 156 buf_consumed = true; 157 return buf_consumed; 158 } 159 160 /* Can set it only after sending auth */ 161 session->ftPEContext.ftPreAuthStatus = QDF_STATUS_E_FAILURE; 162 session->ftPEContext.ftPreAuthSession = true; 163 164 /* Indicate that this is the session on which preauth is being done */ 165 if (session->ftPEContext.pFTPreAuthReq) { 166 if (session->ftPEContext.pFTPreAuthReq->pbssDescription) { 167 qdf_mem_free( 168 session->ftPEContext.pFTPreAuthReq->pbssDescription); 169 session->ftPEContext.pFTPreAuthReq->pbssDescription = 170 NULL; 171 } 172 qdf_mem_free(session->ftPEContext.pFTPreAuthReq); 173 session->ftPEContext.pFTPreAuthReq = NULL; 174 } 175 176 /* We need information from the Pre-Auth Req. Lets save that */ 177 session->ftPEContext.pFTPreAuthReq = ft_pre_auth_req; 178 179 pe_debug("PRE Auth ft_ies_length=%02x%02x%02x", 180 session->ftPEContext.pFTPreAuthReq->ft_ies[0], 181 session->ftPEContext.pFTPreAuthReq->ft_ies[1], 182 session->ftPEContext.pFTPreAuthReq->ft_ies[2]); 183 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 184 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, 185 session, 0, 0); 186 #endif 187 188 /* 189 * Dont need to suspend if APs are in same channel and DUT 190 * is not in MCC state 191 */ 192 if ((session->curr_op_freq != 193 session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq) 194 || lim_is_in_mcc(mac_ctx)) { 195 /* Need to suspend link only if the channels are different */ 196 pe_debug("Performing pre-auth on diff channel(session %pK)", 197 session); 198 lim_send_preauth_scan_offload(mac_ctx, session, 199 session->ftPEContext.pFTPreAuthReq); 200 } else { 201 pe_debug("Performing pre-auth on same channel (session %pK)", 202 session); 203 /* We are in the same channel. Perform pre-auth */ 204 lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL, 205 session); 206 } 207 208 return buf_consumed; 209 } 210 211 /** 212 * lim_perform_ft_pre_auth() - Perform preauthentication 213 * @mac: Global MAC Context 214 * @status: Status Code 215 * @data: pre-auth data 216 * @pe_session: PE Session 217 * 218 * This routine will trigger the sending of authentication frame 219 * to the peer. 220 * 221 * Return: None 222 */ 223 void lim_perform_ft_pre_auth(struct mac_context *mac, QDF_STATUS status, 224 uint32_t *data, struct pe_session *pe_session) 225 { 226 tSirMacAuthFrameBody authFrame; 227 bool is_open = false; 228 229 if (!pe_session) { 230 pe_err("pe_session is NULL"); 231 return; 232 } 233 234 if (cm_is_open_mode(pe_session->vdev)) 235 is_open = true; 236 237 if (pe_session->is11Rconnection && 238 pe_session->ftPEContext.pFTPreAuthReq) { 239 /* Only 11r assoc has FT IEs */ 240 if ((!is_open) && 241 (pe_session->ftPEContext.pFTPreAuthReq->ft_ies_length 242 == 0)) { 243 pe_err("FTIEs for Auth Req Seq 1 is absent"); 244 goto preauth_fail; 245 } 246 } 247 248 if (status != QDF_STATUS_SUCCESS) { 249 pe_err("Change channel not successful for FT pre-auth"); 250 goto preauth_fail; 251 } 252 253 /* Nothing to be done if the session is not in STA mode */ 254 if (!LIM_IS_STA_ROLE(pe_session)) { 255 pe_err("pe_session is not in STA mode"); 256 return; 257 } 258 if (cm_is_auth_type_sae(pe_session->vdev)) { 259 struct qdf_mac_addr *pre_auth_bssid = (struct qdf_mac_addr *) 260 pe_session->ftPEContext.pFTPreAuthReq->preAuthbssId; 261 262 lim_trigger_auth_req_sae(mac, pe_session, pre_auth_bssid); 263 return; 264 } 265 pe_debug("Entered wait auth2 state for FT (old session %pK)", 266 pe_session); 267 if (pe_session->is11Rconnection) { 268 /* Now we are on the right channel and need to send out Auth1 269 * and receive Auth2 270 */ 271 authFrame.authAlgoNumber = eSIR_FT_AUTH; 272 } else { 273 /* Will need to make isESEconnection a enum may be for further 274 * improvements to this to match this algorithm number 275 */ 276 authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM; 277 } 278 authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; 279 authFrame.authStatusCode = 0; 280 281 mac->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId = 282 pe_session->peSessionId; 283 284 /* Start timer here to come back to operating channel */ 285 mac->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId = 286 pe_session->peSessionId; 287 if (TX_SUCCESS != 288 tx_timer_activate(&mac->lim.lim_timers.gLimFTPreAuthRspTimer)) { 289 pe_err("FT Auth Rsp Timer Start Failed"); 290 goto preauth_fail; 291 } 292 MTRACE(mac_trace(mac, TRACE_CODE_TIMER_ACTIVATE, 293 pe_session->peSessionId, eLIM_FT_PREAUTH_RSP_TIMER)); 294 295 pe_debug("FT Auth Rsp Timer Started"); 296 #ifdef FEATURE_WLAN_DIAG_SUPPORT 297 lim_diag_event_report(mac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, 298 mac->lim.pe_session, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS); 299 #endif 300 if (pe_session->ftPEContext.pFTPreAuthReq) 301 lim_send_auth_mgmt_frame(mac, &authFrame, 302 pe_session->ftPEContext.pFTPreAuthReq->preAuthbssId, 303 LIM_NO_WEP_IN_FC, pe_session); 304 305 return; 306 307 preauth_fail: 308 lim_handle_ft_pre_auth_rsp(mac, QDF_STATUS_E_FAILURE, NULL, 0, pe_session); 309 return; 310 } 311 312 /** 313 * lim_ft_setup_auth_session() - Fill the FT Session 314 * @mac: Global MAC Context 315 * @pe_session: PE Session 316 * 317 * Setup the session and the add bss req for the pre-auth AP. 318 * 319 * Return: Success or Failure Status 320 */ 321 QDF_STATUS lim_ft_setup_auth_session(struct mac_context *mac, 322 struct pe_session *pe_session) 323 { 324 struct pe_session *ft_session = NULL; 325 uint8_t sessionId = 0; 326 struct sSirFTPreAuthReq *req; 327 QDF_STATUS status; 328 329 ft_session = 330 pe_find_session_by_bssid(mac, pe_session->limReAssocbssId, 331 &sessionId); 332 if (!ft_session) { 333 pe_err("No session found for bssid: "QDF_MAC_ADDR_FMT, 334 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId)); 335 return QDF_STATUS_E_FAILURE; 336 } 337 338 /* Nothing to be done if the session is not in STA mode */ 339 if (!LIM_IS_STA_ROLE(pe_session)) { 340 pe_err("pe_session is not in STA mode"); 341 return QDF_STATUS_E_FAILURE; 342 } 343 344 req = pe_session->ftPEContext.pFTPreAuthReq; 345 if (req && req->pbssDescription) { 346 status = lim_fill_ft_session(mac, 347 req->pbssDescription, ft_session, 348 pe_session, WLAN_PHYMODE_AUTO); 349 if (QDF_IS_STATUS_ERROR(status)) 350 pe_err("Failed to fill ft session for vdev id %d", 351 ft_session->vdev_id); 352 353 lim_ft_prepare_add_bss_req(mac, ft_session, 354 req->pbssDescription); 355 } 356 357 return QDF_STATUS_SUCCESS; 358 } 359 360 /** 361 * lim_ft_process_pre_auth_result() - Process the Auth frame 362 * @mac: Global MAC context 363 * @pe_session: PE Session 364 * 365 * Return: None 366 */ 367 static void lim_ft_process_pre_auth_result(struct mac_context *mac, 368 struct pe_session *pe_session) 369 { 370 if (!pe_session || 371 !pe_session->ftPEContext.pFTPreAuthReq) 372 return; 373 374 /* Nothing to be done if the session is not in STA mode */ 375 if (!LIM_IS_STA_ROLE(pe_session)) { 376 pe_err("pe_session is not in STA mode"); 377 return; 378 } 379 380 if (pe_session->ftPEContext.ftPreAuthStatus == QDF_STATUS_SUCCESS) { 381 pe_session->ftPEContext.ftPreAuthStatus = 382 lim_ft_setup_auth_session(mac, pe_session); 383 } 384 /* Post the FT Pre Auth Response to SME */ 385 lim_post_ft_pre_auth_rsp(mac, 386 pe_session->ftPEContext.ftPreAuthStatus, 387 pe_session->ftPEContext.saved_auth_rsp, 388 pe_session->ftPEContext.saved_auth_rsp_length, 389 pe_session); 390 } 391 392 /** 393 * lim_handle_ft_pre_auth_rsp() - Handle the Auth response 394 * @mac: Global MAC Context 395 * @status: Status Code 396 * @auth_rsp: Auth Response 397 * @auth_rsp_length: Auth response length 398 * @pe_session: PE Session 399 * 400 * Send the FT Pre Auth Response to SME whenever we have a status 401 * ready to be sent to SME 402 * 403 * SME will be the one to send it up to the supplicant to receive 404 * FTIEs which will be required for Reassoc Req. 405 * 406 * @Return: None 407 */ 408 void lim_handle_ft_pre_auth_rsp(struct mac_context *mac, QDF_STATUS status, 409 uint8_t *auth_rsp, uint16_t auth_rsp_length, 410 struct pe_session *pe_session) 411 { 412 struct pe_session *ft_session = NULL; 413 uint8_t sessionId = 0; 414 struct bss_description *pbssDescription = NULL; 415 #ifdef FEATURE_WLAN_DIAG_SUPPORT 416 lim_diag_event_report(mac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, 417 pe_session, (uint16_t) status, 0); 418 #endif 419 420 /* Nothing to be done if the session is not in STA mode */ 421 if (!LIM_IS_STA_ROLE(pe_session)) { 422 pe_err("pe_session is not in STA mode"); 423 return; 424 } 425 426 /* Save the status of pre-auth */ 427 pe_session->ftPEContext.ftPreAuthStatus = status; 428 429 /* Save the auth rsp, so we can send it to 430 * SME once we resume link 431 */ 432 pe_session->ftPEContext.saved_auth_rsp_length = 0; 433 if ((auth_rsp) && (auth_rsp_length < MAX_FTIE_SIZE)) { 434 qdf_mem_copy(pe_session->ftPEContext.saved_auth_rsp, 435 auth_rsp, auth_rsp_length); 436 pe_session->ftPEContext.saved_auth_rsp_length = 437 auth_rsp_length; 438 } 439 440 if (!pe_session->ftPEContext.pFTPreAuthReq || 441 !pe_session->ftPEContext.pFTPreAuthReq->pbssDescription) { 442 pe_err("pFTPreAuthReq or pbssDescription is NULL"); 443 return; 444 } 445 446 /* Create FT session for the re-association at this point */ 447 if (pe_session->ftPEContext.ftPreAuthStatus == QDF_STATUS_SUCCESS) { 448 pbssDescription = 449 pe_session->ftPEContext.pFTPreAuthReq->pbssDescription; 450 ft_session = 451 pe_create_session(mac, pbssDescription->bssId, 452 &sessionId, 453 mac->lim.max_sta_of_pe_session, 454 pe_session->bssType, 455 pe_session->vdev_id); 456 if (!ft_session) { 457 pe_err("Session not created for pre-auth 11R AP"); 458 status = QDF_STATUS_E_FAILURE; 459 pe_session->ftPEContext.ftPreAuthStatus = status; 460 goto send_rsp; 461 } 462 463 sir_copy_mac_addr(ft_session->self_mac_addr, 464 pe_session->self_mac_addr); 465 sir_copy_mac_addr(ft_session->limReAssocbssId, 466 pbssDescription->bssId); 467 468 /* Update the beacon/probe filter in mac_ctx */ 469 lim_set_bcn_probe_filter(mac, ft_session, 0); 470 471 if (ft_session->bssType == eSIR_INFRASTRUCTURE_MODE) 472 ft_session->limSystemRole = eLIM_STA_ROLE; 473 else 474 pe_err("Invalid bss type"); 475 476 ft_session->limPrevSmeState = ft_session->limSmeState; 477 ft_session->ht_config = pe_session->ht_config; 478 ft_session->limSmeState = eLIM_SME_WT_REASSOC_STATE; 479 480 if (wlan_reg_is_24ghz_ch_freq(pe_session->ftPEContext. 481 pFTPreAuthReq->pre_auth_channel_freq)) 482 ft_session->vdev_nss = mac->vdev_type_nss_2g.sta; 483 else 484 ft_session->vdev_nss = mac->vdev_type_nss_5g.sta; 485 486 /* Update the ReAssoc BSSID of the current session */ 487 sir_copy_mac_addr(pe_session->limReAssocbssId, 488 pbssDescription->bssId); 489 pe_debug("created session (%pK) with id = %d BSSID = "QDF_MAC_ADDR_FMT, 490 ft_session, ft_session->peSessionId, 491 QDF_MAC_ADDR_REF(pe_session->limReAssocbssId)); 492 } 493 send_rsp: 494 if ((pe_session->curr_op_freq != 495 pe_session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq) || 496 lim_is_in_mcc(mac)) { 497 pe_debug("Pre auth on diff freq as connected AP freq %d or mcc pe sessions exist, so abort scan", 498 pe_session->ftPEContext.pFTPreAuthReq->pre_auth_channel_freq); 499 500 /* Need to move to the original AP channel */ 501 lim_process_abort_scan_ind(mac, pe_session->smeSessionId, 502 pe_session->ftPEContext.pFTPreAuthReq->scan_id, 503 mac->lim.req_id | PREAUTH_REQUESTOR_ID); 504 } 505 /* 506 * Send resp to connection manager, even in case scan needs abort, 507 * scan complete will be no-op. 508 */ 509 lim_ft_process_pre_auth_result(mac, pe_session); 510 } 511 512 /* 513 * lim_process_ft_preauth_rsp_timeout() - process ft preauth rsp timeout 514 * 515 * @mac_ctx: global mac ctx 516 * 517 * This function is called if preauth response is not received from the AP 518 * within this timeout while FT in progress 519 * 520 * Return: void 521 */ 522 void lim_process_ft_preauth_rsp_timeout(struct mac_context *mac_ctx) 523 { 524 struct pe_session *session; 525 526 /* 527 * We have failed pre auth. We need to resume link and get back on 528 * home channel 529 */ 530 pe_err("FT Pre-Auth Time Out!!!!"); 531 session = pe_find_session_by_session_id(mac_ctx, 532 mac_ctx->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId); 533 if (!session) { 534 pe_err("Session Does not exist for given sessionID"); 535 return; 536 } 537 538 /* Nothing to be done if the session is not in STA mode */ 539 if (!LIM_IS_STA_ROLE(session)) { 540 pe_err("session is not in STA mode"); 541 return; 542 } 543 544 /* Reset the flag to indicate preauth request session */ 545 session->ftPEContext.ftPreAuthSession = false; 546 547 if (!session->ftPEContext.pFTPreAuthReq) { 548 /* Auth Rsp might already be posted to SME and ftcleanup done */ 549 pe_err("pFTPreAuthReq is NULL sessionId: %d", 550 mac_ctx->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId); 551 return; 552 } 553 554 /* 555 * To handle the race condition where we receive preauth rsp after 556 * timer has expired. 557 */ 558 if (true == 559 session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) { 560 pe_err("Auth rsp already posted to SME (session %pK)", 561 session); 562 return; 563 } else { 564 /* 565 * Here we are sending preauth rsp with failure state 566 * and which is forwarded to SME. Now, if we receive an preauth 567 * resp from AP with success it would create a FT pesession, but 568 * will be dropped in SME leaving behind the pesession. Mark 569 * Preauth rsp processed so that any rsp from AP is dropped in 570 * lim_process_auth_frame_no_session. 571 */ 572 pe_debug("Auth rsp not yet posted to SME (session %pK)", 573 session); 574 session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = true; 575 } 576 577 /* 578 * Attempted at Pre-Auth and failed. If we are off channel. We need 579 * to get back to home channel 580 */ 581 lim_handle_ft_pre_auth_rsp(mac_ctx, QDF_STATUS_E_FAILURE, NULL, 0, session); 582 } 583 584 /* 585 * lim_cm_post_preauth_rsp() - post preauth response to osif. 586 * 587 * @mac_ctx: global mac ctx 588 * @status: status code to post in auth rsp 589 * @auth_rsp: pointer to auth rsp FT ie 590 * @auth_rsp_length: len of the IE field 591 * @session: pe session 592 * 593 * post preauth response to osif. 594 * 595 * Return: void 596 */ 597 static void 598 lim_cm_post_preauth_rsp(struct mac_context *mac_ctx, QDF_STATUS status, 599 uint8_t *auth_rsp, uint16_t auth_rsp_length, 600 struct pe_session *session) 601 { 602 QDF_STATUS qdf_status; 603 struct scheduler_msg rsp_msg = {0}; 604 struct wlan_preauth_rsp *rsp; 605 606 rsp = qdf_mem_malloc(sizeof(*rsp)); 607 if (!rsp) 608 return; 609 610 rsp->psoc = mac_ctx->psoc; 611 if (session) { 612 /* Nothing to be done if the session is not in STA mode */ 613 if (!LIM_IS_STA_ROLE(session)) { 614 pe_err("session is not in STA mode"); 615 qdf_mem_free(rsp); 616 return; 617 } 618 rsp->vdev_id = session->vdev_id; 619 /* The bssid of the AP we are sending Auth1 to. */ 620 if (session->ftPEContext.pFTPreAuthReq) 621 qdf_mem_copy(rsp->pre_auth_bssid.bytes, 622 session->ftPEContext. 623 pFTPreAuthReq->preAuthbssId, 624 QDF_MAC_ADDR_SIZE); 625 } 626 rsp->status = status; 627 628 /* Attach the auth response now back to osif */ 629 rsp->ft_ie_length = 0; 630 if (auth_rsp && (auth_rsp_length < MAX_FTIE_SIZE)) { 631 /* Only 11r assoc has FT IEs */ 632 qdf_mem_copy(rsp->ft_ie, auth_rsp, auth_rsp_length); 633 rsp->ft_ie_length = auth_rsp_length; 634 } 635 636 rsp_msg.bodyptr = rsp; 637 rsp_msg.callback = cm_handle_preauth_rsp; 638 639 qdf_status = scheduler_post_message( 640 QDF_MODULE_ID_PE, QDF_MODULE_ID_OS_IF, 641 QDF_MODULE_ID_OS_IF, &rsp_msg); 642 643 if (QDF_IS_STATUS_ERROR(qdf_status)) { 644 pe_err("Failed to post preauth rsp to sme vdev_id %d", 645 rsp->vdev_id); 646 qdf_mem_free(rsp); 647 } 648 } 649 650 /* 651 * lim_post_ft_pre_auth_rsp() - post ft pre auth response to SME. 652 * 653 * @mac_ctx: global mac ctx 654 * @status: status code to post in auth rsp 655 * @auth_rsp: pointer to auth rsp FT ie 656 * @auth_rsp_length: len of the IE field 657 * @session: pe session 658 * 659 * post pre auth response to SME. 660 * 661 * Return: void 662 */ 663 void lim_post_ft_pre_auth_rsp(struct mac_context *mac_ctx, 664 QDF_STATUS status, 665 uint8_t *auth_rsp, 666 uint16_t auth_rsp_length, 667 struct pe_session *session) 668 { 669 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 670 if (status == QDF_STATUS_SUCCESS) 671 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PREAUTH_DONE, 672 session, status, 0); 673 #endif 674 lim_cm_post_preauth_rsp(mac_ctx, status, auth_rsp, auth_rsp_length, 675 session); 676 } 677 678 /** 679 * lim_send_preauth_scan_offload() - Send scan command to handle preauth. 680 * 681 * @mac_ctx: Pointer to Global MAC structure 682 * @session_entry: pe session 683 * @ft_preauth_req: Preauth request with parameters 684 * 685 * Builds a single channel scan request and sends it to scan module. 686 * Scan dwell time is the time allocated to go to preauth candidate 687 * channel for auth frame exchange. 688 * 689 * Return: Status of sending message to scan module. 690 */ 691 QDF_STATUS lim_send_preauth_scan_offload(struct mac_context *mac_ctx, 692 struct pe_session *session_entry, 693 tSirFTPreAuthReq *ft_preauth_req) 694 { 695 struct scan_start_request *req; 696 struct wlan_objmgr_vdev *vdev; 697 uint8_t vdev_id; 698 QDF_STATUS status = QDF_STATUS_SUCCESS; 699 700 if (!session_entry) { 701 pe_err("Session entry is NULL"); 702 return QDF_STATUS_E_FAILURE; 703 } 704 705 vdev_id = session_entry->smeSessionId; 706 707 req = qdf_mem_malloc(sizeof(*req)); 708 if (!req) 709 return QDF_STATUS_E_NOMEM; 710 711 qdf_mem_zero(req, sizeof(*req)); 712 713 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, 714 vdev_id, 715 WLAN_LEGACY_MAC_ID); 716 if (!vdev) { 717 pe_err("vdev_id %d: vdev is NULL", vdev_id); 718 qdf_mem_free(req); 719 return QDF_STATUS_E_FAILURE; 720 } 721 722 wlan_scan_init_default_params(vdev, req); 723 724 qdf_mem_copy(req->scan_req.bssid_list, 725 (uint8_t *)ft_preauth_req->currbssId, 726 QDF_MAC_ADDR_SIZE); 727 728 req->scan_req.scan_id = wlan_scan_get_scan_id(mac_ctx->psoc); 729 if (!req->scan_req.scan_id) { 730 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 731 qdf_mem_free(req); 732 pe_err("Invalid scan ID"); 733 return QDF_STATUS_E_FAILURE; 734 } 735 ft_preauth_req->scan_id = req->scan_req.scan_id; 736 req->scan_req.vdev_id = vdev_id; 737 req->scan_req.scan_req_id = mac_ctx->lim.req_id | PREAUTH_REQUESTOR_ID; 738 req->scan_req.scan_priority = SCAN_PRIORITY_VERY_HIGH; 739 req->scan_req.scan_f_passive = true; 740 741 req->scan_req.chan_list.num_chan = 1; 742 req->scan_req.chan_list.chan[0].freq = 743 ft_preauth_req->pre_auth_channel_freq; 744 745 req->scan_req.dwell_time_active = LIM_FT_PREAUTH_ACTIVE_SCAN_TIME; 746 req->scan_req.dwell_time_passive = LIM_FT_PREAUTH_PASSIVE_SCAN_TIME; 747 748 status = wlan_scan_start(req); 749 if (QDF_IS_STATUS_ERROR(status)) 750 /* Don't free req here, ucfg_scan_start will do free */ 751 pe_info("Issue scan req failed"); 752 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 753 return status; 754 } 755 756 void lim_preauth_scan_event_handler(struct mac_context *mac_ctx, 757 enum sir_scan_event_type event, 758 uint8_t vdev_id, uint32_t scan_id) 759 { 760 struct pe_session *session_entry; 761 762 session_entry = pe_find_session_by_scan_id(mac_ctx, scan_id); 763 /* Pre-auth request is sent */ 764 if (session_entry) { 765 if ((event == SIR_SCAN_EVENT_FOREIGN_CHANNEL) && 766 (session_entry->ftPEContext.ftPreAuthStatus 767 == QDF_STATUS_SUCCESS)) { 768 pe_err("Pre-auth is done, skip sending pre-auth req"); 769 return; 770 } 771 } else { 772 /* For the first pre-auth request 773 * need to get it by sme session id (vdev id) 774 */ 775 session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 776 } 777 778 if (!session_entry) { 779 pe_err("vdev_id :%d PeSessionId:%d does not exist", vdev_id, 780 mac_ctx->lim.lim_timers.gLimFTPreAuthRspTimer.sessionId); 781 return; 782 } 783 784 switch (event) { 785 case SIR_SCAN_EVENT_START_FAILED: 786 /* Scan command is rejected by firmware */ 787 pe_err("Failed to start preauth scan"); 788 lim_post_ft_pre_auth_rsp(mac_ctx, QDF_STATUS_E_FAILURE, NULL, 0, 789 session_entry); 790 return; 791 792 case SIR_SCAN_EVENT_COMPLETED: 793 /* 794 * Scan either completed successfully or or got terminated 795 * after successful auth, or timed out. Either way, STA 796 * is back to home channel. Data traffic can continue. 797 * Don't do anything as preauth timer/auth resp will take care 798 * of the sending resp to the connection manager. 799 */ 800 break; 801 802 case SIR_SCAN_EVENT_FOREIGN_CHANNEL: 803 /* Sta is on candidate channel. Send auth */ 804 lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL, 805 session_entry); 806 break; 807 default: 808 /* Don't print message for scan events that are ignored */ 809 break; 810 } 811 } 812 813