1 /* 2 * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: Implements connect specific APIs of connection manager 20 */ 21 22 #include "wlan_cm_main_api.h" 23 #include "wlan_scan_api.h" 24 #include "wlan_cm_roam.h" 25 #include "wlan_cm_sm.h" 26 #ifdef WLAN_POLICY_MGR_ENABLE 27 #include "wlan_policy_mgr_api.h" 28 #endif 29 #include <wlan_serialization_api.h> 30 #ifdef CONN_MGR_ADV_FEATURE 31 #include "wlan_dlm_api.h" 32 #include "wlan_cm_roam_api.h" 33 #include "wlan_tdls_api.h" 34 #include "wlan_mlo_t2lm.h" 35 #include "wlan_t2lm_api.h" 36 #endif 37 #include <wlan_utility.h> 38 #include <wlan_mlo_mgr_sta.h> 39 #include <wlan_objmgr_vdev_obj.h> 40 #include "wlan_psoc_mlme_api.h" 41 42 static void 43 cm_fill_failure_resp_from_cm_id(struct cnx_mgr *cm_ctx, 44 struct wlan_cm_connect_resp *resp, 45 wlan_cm_id cm_id, 46 enum wlan_cm_connect_fail_reason reason) 47 { 48 resp->connect_status = QDF_STATUS_E_FAILURE; 49 resp->cm_id = cm_id; 50 resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 51 resp->reason = reason; 52 /* Get bssid and ssid and freq for the cm id from the req list */ 53 cm_fill_bss_info_in_connect_rsp_by_cm_id(cm_ctx, cm_id, resp); 54 } 55 56 static QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, 57 wlan_cm_id cm_id) 58 { 59 struct wlan_cm_connect_resp *resp; 60 QDF_STATUS status; 61 62 resp = qdf_mem_malloc(sizeof(*resp)); 63 if (!resp) 64 return QDF_STATUS_E_NOMEM; 65 66 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, CM_SER_TIMEOUT); 67 status = cm_sm_deliver_event(cm_ctx->vdev, 68 WLAN_CM_SM_EV_CONNECT_FAILURE, 69 sizeof(*resp), resp); 70 qdf_mem_free(resp); 71 72 if (QDF_IS_STATUS_ERROR(status)) 73 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 74 75 return status; 76 } 77 78 #ifdef WLAN_CM_USE_SPINLOCK 79 static QDF_STATUS cm_activate_connect_req_sched_cb(struct scheduler_msg *msg) 80 { 81 struct wlan_serialization_command *cmd = msg->bodyptr; 82 struct wlan_objmgr_vdev *vdev; 83 struct cnx_mgr *cm_ctx; 84 QDF_STATUS ret = QDF_STATUS_E_FAILURE; 85 86 if (!cmd) { 87 mlme_err("cmd is null"); 88 return QDF_STATUS_E_INVAL; 89 } 90 91 vdev = cmd->vdev; 92 if (!vdev) { 93 mlme_err("vdev is null"); 94 return QDF_STATUS_E_INVAL; 95 } 96 97 cm_ctx = cm_get_cm_ctx(vdev); 98 if (!cm_ctx) 99 return QDF_STATUS_E_INVAL; 100 101 ret = cm_sm_deliver_event(vdev, 102 WLAN_CM_SM_EV_CONNECT_ACTIVE, 103 sizeof(wlan_cm_id), 104 &cmd->cmd_id); 105 106 /* 107 * Called from scheduler context hence posting failure 108 */ 109 if (QDF_IS_STATUS_ERROR(ret)) { 110 mlme_err(CM_PREFIX_FMT "Activation failed for cmd:%d", 111 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id), 112 cmd->cmd_type); 113 cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id); 114 } 115 116 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 117 return ret; 118 } 119 120 static QDF_STATUS 121 cm_activate_connect_req(struct wlan_serialization_command *cmd) 122 { 123 struct wlan_objmgr_vdev *vdev = cmd->vdev; 124 struct scheduler_msg msg = {0}; 125 QDF_STATUS ret; 126 127 msg.bodyptr = cmd; 128 msg.callback = cm_activate_connect_req_sched_cb; 129 msg.flush_callback = cm_activate_cmd_req_flush_cb; 130 131 ret = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLME_CM_ID); 132 if (QDF_IS_STATUS_ERROR(ret)) 133 return ret; 134 135 ret = scheduler_post_message(QDF_MODULE_ID_MLME, 136 QDF_MODULE_ID_MLME, 137 QDF_MODULE_ID_MLME, &msg); 138 139 if (QDF_IS_STATUS_ERROR(ret)) { 140 mlme_err(CM_PREFIX_FMT "Failed to post scheduler_msg", 141 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); 142 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 143 return ret; 144 } 145 mlme_debug(CM_PREFIX_FMT "Cmd act in sched cmd type:%d", 146 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id), 147 cmd->cmd_type); 148 149 return ret; 150 } 151 #else 152 static QDF_STATUS 153 cm_activate_connect_req(struct wlan_serialization_command *cmd) 154 { 155 return cm_sm_deliver_event(cmd->vdev, 156 WLAN_CM_SM_EV_CONNECT_ACTIVE, 157 sizeof(wlan_cm_id), 158 &cmd->cmd_id); 159 } 160 #endif 161 162 static QDF_STATUS 163 cm_ser_connect_cb(struct wlan_serialization_command *cmd, 164 enum wlan_serialization_cb_reason reason) 165 { 166 QDF_STATUS status = QDF_STATUS_SUCCESS; 167 struct wlan_objmgr_vdev *vdev; 168 struct cnx_mgr *cm_ctx; 169 170 if (!cmd) { 171 mlme_err("cmd is NULL, reason: %d", reason); 172 QDF_ASSERT(0); 173 return QDF_STATUS_E_NULL_VALUE; 174 } 175 176 vdev = cmd->vdev; 177 178 cm_ctx = cm_get_cm_ctx(vdev); 179 if (!cm_ctx) 180 return QDF_STATUS_E_NULL_VALUE; 181 182 switch (reason) { 183 case WLAN_SER_CB_ACTIVATE_CMD: 184 /* 185 * For pending to active reason, use async api to take lock. 186 * For direct activation use sync api to avoid taking lock 187 * as lock is already acquired by the requester. 188 */ 189 if (cmd->activation_reason == SER_PENDING_TO_ACTIVE) 190 status = cm_activate_connect_req(cmd); 191 else 192 status = cm_sm_deliver_event_sync(cm_ctx, 193 WLAN_CM_SM_EV_CONNECT_ACTIVE, 194 sizeof(wlan_cm_id), 195 &cmd->cmd_id); 196 if (QDF_IS_STATUS_SUCCESS(status)) 197 break; 198 /* 199 * Handle failure if posting fails, i.e. the SM state has 200 * changed or head cm_id doesn't match the active cm_id. 201 * connect active should be handled only in JOIN_PENDING. If 202 * new command has been received connect activation should be 203 * aborted from here with connect req cleanup. 204 */ 205 cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id); 206 break; 207 case WLAN_SER_CB_CANCEL_CMD: 208 /* command removed from pending list. */ 209 break; 210 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 211 mlme_err(CM_PREFIX_FMT "Active command timeout", 212 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); 213 cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev); 214 cm_connect_cmd_timeout(cm_ctx, cmd->cmd_id); 215 break; 216 case WLAN_SER_CB_RELEASE_MEM_CMD: 217 cm_reset_active_cm_id(vdev, cmd->cmd_id); 218 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 219 break; 220 default: 221 QDF_ASSERT(0); 222 status = QDF_STATUS_E_INVAL; 223 break; 224 } 225 226 return status; 227 } 228 229 static QDF_STATUS cm_ser_connect_req(struct wlan_objmgr_pdev *pdev, 230 struct cnx_mgr *cm_ctx, 231 struct cm_connect_req *cm_req) 232 { 233 struct wlan_serialization_command cmd = {0, }; 234 enum wlan_serialization_status ser_cmd_status; 235 QDF_STATUS status; 236 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 237 238 status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID); 239 if (QDF_IS_STATUS_ERROR(status)) { 240 mlme_err(CM_PREFIX_FMT "unable to get reference", 241 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 242 return status; 243 } 244 245 cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT; 246 cmd.cmd_id = cm_req->cm_id; 247 cmd.cmd_cb = cm_ser_connect_cb; 248 cmd.source = WLAN_UMAC_COMP_MLME; 249 cmd.is_high_priority = false; 250 cmd.cmd_timeout_duration = cm_ctx->connect_timeout; 251 cmd.vdev = cm_ctx->vdev; 252 cmd.is_blocking = true; 253 254 ser_cmd_status = wlan_serialization_request(&cmd); 255 switch (ser_cmd_status) { 256 case WLAN_SER_CMD_PENDING: 257 /* command moved to pending list.Do nothing */ 258 break; 259 case WLAN_SER_CMD_ACTIVE: 260 /* command moved to active list. Do nothing */ 261 break; 262 default: 263 mlme_err(CM_PREFIX_FMT "ser cmd status %d", 264 CM_PREFIX_REF(vdev_id, cm_req->cm_id), ser_cmd_status); 265 wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID); 266 267 return QDF_STATUS_E_FAILURE; 268 } 269 270 return QDF_STATUS_SUCCESS; 271 } 272 273 void 274 cm_connect_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id) 275 { 276 struct wlan_cm_connect_resp *resp; 277 278 resp = qdf_mem_malloc(sizeof(*resp)); 279 if (!resp) 280 return; 281 282 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, 283 CM_ABORT_DUE_TO_NEW_REQ_RECVD); 284 cm_connect_complete(cm_ctx, resp); 285 qdf_mem_free(resp); 286 } 287 288 QDF_STATUS 289 cm_send_connect_start_fail(struct cnx_mgr *cm_ctx, 290 struct cm_connect_req *req, 291 enum wlan_cm_connect_fail_reason reason) 292 { 293 struct wlan_cm_connect_resp *resp; 294 QDF_STATUS status; 295 296 resp = qdf_mem_malloc(sizeof(*resp)); 297 if (!resp) 298 return QDF_STATUS_E_NOMEM; 299 300 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, reason); 301 302 status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, 303 sizeof(*resp), resp); 304 qdf_mem_free(resp); 305 306 return status; 307 } 308 309 #ifdef WLAN_POLICY_MGR_ENABLE 310 311 QDF_STATUS cm_handle_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id, 312 enum wlan_cm_sm_evt event) 313 { 314 struct cm_req *cm_req; 315 enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE; 316 struct wlan_objmgr_pdev *pdev; 317 QDF_STATUS status; 318 319 if (!cm_id) 320 return QDF_STATUS_E_FAILURE; 321 322 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 323 if (!cm_req) 324 return QDF_STATUS_E_INVAL; 325 326 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 327 if (!pdev) { 328 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 329 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 330 cm_req->cm_id)); 331 goto send_failure; 332 } 333 334 if (event == WLAN_CM_SM_EV_HW_MODE_SUCCESS) { 335 status = cm_ser_connect_req(pdev, cm_ctx, &cm_req->connect_req); 336 if (QDF_IS_STATUS_ERROR(status)) { 337 reason = CM_SER_FAILURE; 338 goto send_failure; 339 } 340 return status; 341 } 342 343 /* Set reason HW mode fail for event WLAN_CM_SM_EV_HW_MODE_FAILURE */ 344 reason = CM_HW_MODE_FAILURE; 345 346 send_failure: 347 return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req, reason); 348 } 349 350 void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 351 wlan_cm_id cm_id, QDF_STATUS status) 352 { 353 struct wlan_objmgr_vdev *vdev; 354 QDF_STATUS qdf_status; 355 enum wlan_cm_sm_evt event = WLAN_CM_SM_EV_HW_MODE_SUCCESS; 356 struct cnx_mgr *cm_ctx; 357 358 mlme_debug(CM_PREFIX_FMT "Continue connect after HW mode change, status %d", 359 CM_PREFIX_REF(vdev_id, cm_id), status); 360 361 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 362 WLAN_MLME_CM_ID); 363 if (!vdev) 364 return; 365 366 cm_ctx = cm_get_cm_ctx(vdev); 367 if (!cm_ctx) { 368 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 369 return; 370 } 371 372 if (QDF_IS_STATUS_ERROR(status)) 373 event = WLAN_CM_SM_EV_HW_MODE_FAILURE; 374 qdf_status = cm_sm_deliver_event(vdev, event, sizeof(wlan_cm_id), 375 &cm_id); 376 377 /* 378 * Handle failure if posting fails, i.e. the SM state has 379 * changed or head cm_id doesn't match the active cm_id. 380 * hw mode change resp should be handled only in JOIN_PENDING. If 381 * new command has been received connect should be 382 * aborted from here with connect req cleanup. 383 */ 384 if (QDF_IS_STATUS_ERROR(status)) 385 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 386 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 387 } 388 389 static QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc, 390 qdf_list_t *scan_list, 391 uint8_t vdev_id, 392 wlan_cm_id connect_id) 393 { 394 return policy_mgr_change_hw_mode_sta_connect(psoc, scan_list, vdev_id, 395 connect_id); 396 } 397 398 399 #else 400 401 static inline 402 QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc, 403 qdf_list_t *scan_list, uint8_t vdev_id, 404 uint8_t connect_id) 405 { 406 return QDF_STATUS_E_ALREADY; 407 } 408 409 #endif /* WLAN_POLICY_MGR_ENABLE */ 410 411 static inline void cm_delete_pmksa_for_bssid(struct cnx_mgr *cm_ctx, 412 struct qdf_mac_addr *bssid) 413 { 414 struct wlan_crypto_pmksa pmksa; 415 416 qdf_mem_zero(&pmksa, sizeof(pmksa)); 417 qdf_copy_macaddr(&pmksa.bssid, bssid); 418 wlan_crypto_set_del_pmksa(cm_ctx->vdev, &pmksa, false); 419 } 420 421 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) 422 static inline 423 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx, 424 struct qdf_mac_addr *bssid) 425 { 426 cm_delete_pmksa_for_bssid(cm_ctx, bssid); 427 } 428 #else 429 static inline 430 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx, 431 struct qdf_mac_addr *bssid) 432 { 433 } 434 #endif /* WLAN_SAE_SINGLE_PMK && WLAN_FEATURE_ROAM_OFFLOAD */ 435 436 static inline void 437 cm_set_pmf_caps(struct wlan_cm_connect_req *req, struct scan_filter *filter) 438 { 439 if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED) 440 filter->pmf_cap = WLAN_PMF_REQUIRED; 441 else if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) 442 filter->pmf_cap = WLAN_PMF_CAPABLE; 443 else 444 filter->pmf_cap = WLAN_PMF_DISABLED; 445 } 446 447 #ifdef WLAN_FEATURE_11BE_MLO 448 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 449 static inline 450 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx, 451 struct cm_connect_req *req) 452 { 453 uint8_t link_id; 454 455 link_id = req->cur_candidate->entry->ml_info.self_link_id; 456 if (cm_ctx->vdev) { 457 mlme_debug("setting link ID to %d", link_id); 458 wlan_vdev_set_link_id(cm_ctx->vdev, link_id); 459 } 460 } 461 462 static void cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx, 463 struct cm_connect_req *req) 464 { 465 struct qdf_mac_addr *mac; 466 bool eht_capab; 467 468 if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE) 469 return; 470 471 wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev), 472 &eht_capab); 473 if (!eht_capab) 474 return; 475 476 mac = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(cm_ctx->vdev); 477 478 if (req->cur_candidate->entry->ie_list.multi_link_bv && 479 !qdf_is_macaddr_zero(mac)) { 480 wlan_vdev_obj_lock(cm_ctx->vdev); 481 /* Use link address for ML connection */ 482 wlan_vdev_mlme_set_macaddr(cm_ctx->vdev, 483 cm_ctx->vdev->vdev_mlme.linkaddr); 484 wlan_vdev_obj_unlock(cm_ctx->vdev); 485 wlan_vdev_mlme_set_mlo_vdev(cm_ctx->vdev); 486 mlme_debug("set link address for ML connection"); 487 } else { 488 /* Use net_dev address for non-ML connection */ 489 if (!qdf_is_macaddr_zero(mac)) { 490 wlan_vdev_obj_lock(cm_ctx->vdev); 491 wlan_vdev_mlme_set_macaddr(cm_ctx->vdev, mac->bytes); 492 wlan_vdev_obj_unlock(cm_ctx->vdev); 493 mlme_debug(QDF_MAC_ADDR_FMT " for non-ML connection", 494 QDF_MAC_ADDR_REF(mac->bytes)); 495 } 496 497 wlan_vdev_mlme_clear_mlo_vdev(cm_ctx->vdev); 498 mlme_debug("clear MLO cap for non-ML connection"); 499 } 500 } 501 #else 502 static inline 503 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx, 504 struct cm_connect_req *req) 505 { } 506 507 static void cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx, 508 struct cm_connect_req *req) 509 { 510 } 511 #endif 512 /** 513 * cm_get_bss_peer_mld_addr() - get bss peer mld mac address 514 * @req: pointer to cm_connect_req 515 * 516 * Return: mld mac address 517 */ 518 static struct qdf_mac_addr *cm_get_bss_peer_mld_addr(struct cm_connect_req *req) 519 { 520 if (req && req->cur_candidate && req->cur_candidate->entry) 521 return &req->cur_candidate->entry->ml_info.mld_mac_addr; 522 else 523 return NULL; 524 } 525 526 /** 527 * cm_bss_peer_is_assoc_peer() - is the bss peer to be created assoc peer or not 528 * @req: pointer to cm_connect_req 529 * 530 * Return: true if the bss peer to be created is assoc peer 531 */ 532 static bool cm_bss_peer_is_assoc_peer(struct cm_connect_req *req) 533 { 534 if (req) 535 return !req->req.is_non_assoc_link; 536 537 return false; 538 } 539 540 /** 541 * cm_candidate_mlo_update() - handle mlo scenario for candidate validating 542 * @scan_entry: scan result of the candidate 543 * @validate_bss_info: candidate info to be updated 544 * 545 * Return: None 546 */ 547 static void 548 cm_candidate_mlo_update(struct scan_cache_entry *scan_entry, 549 struct validate_bss_data *validate_bss_info) 550 { 551 validate_bss_info->is_mlo = !!scan_entry->ie_list.multi_link_bv; 552 validate_bss_info->scan_entry = scan_entry; 553 } 554 #else 555 static inline 556 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx, 557 struct cm_connect_req *req) 558 { } 559 560 static void cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx, 561 struct cm_connect_req *req) 562 { 563 } 564 565 static struct qdf_mac_addr *cm_get_bss_peer_mld_addr(struct cm_connect_req *req) 566 { 567 return NULL; 568 } 569 570 static bool cm_bss_peer_is_assoc_peer(struct cm_connect_req *req) 571 { 572 return false; 573 } 574 575 static inline void 576 cm_candidate_mlo_update(struct scan_cache_entry *scan_entry, 577 struct validate_bss_data *validate_bss_info) 578 { 579 } 580 #endif 581 582 static void cm_create_bss_peer(struct cnx_mgr *cm_ctx, 583 struct cm_connect_req *req) 584 { 585 QDF_STATUS status; 586 struct qdf_mac_addr *bssid; 587 struct qdf_mac_addr *mld_mac = NULL; 588 bool is_assoc_link = false; 589 bool eht_capab; 590 591 if (!cm_ctx) { 592 mlme_err("invalid cm_ctx"); 593 return; 594 } 595 if (!req || !req->cur_candidate || !req->cur_candidate->entry) { 596 mlme_err("invalid req"); 597 return; 598 } 599 600 wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev), 601 &eht_capab); 602 if (eht_capab) { 603 cm_set_vdev_link_id(cm_ctx, req); 604 mld_mac = cm_get_bss_peer_mld_addr(req); 605 is_assoc_link = cm_bss_peer_is_assoc_peer(req); 606 } 607 608 bssid = &req->cur_candidate->entry->bssid; 609 status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, bssid, 610 mld_mac, is_assoc_link); 611 if (QDF_IS_STATUS_ERROR(status)) { 612 struct wlan_cm_connect_resp *resp; 613 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 614 615 /* In case of failure try with next candidate */ 616 mlme_err(CM_PREFIX_FMT "peer create request failed %d", 617 CM_PREFIX_REF(vdev_id, req->cm_id), status); 618 619 resp = qdf_mem_malloc(sizeof(*resp)); 620 if (!resp) 621 return; 622 623 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, 624 CM_PEER_CREATE_FAILED); 625 cm_sm_deliver_event_sync(cm_ctx, 626 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 627 sizeof(*resp), resp); 628 qdf_mem_free(resp); 629 } 630 } 631 632 #if defined(CONN_MGR_ADV_FEATURE) && defined(WLAN_FEATURE_11BE_MLO) 633 static QDF_STATUS 634 cm_t2lm_validate_candidate(struct cnx_mgr *cm_ctx, 635 struct scan_cache_entry *scan_entry) 636 { 637 return wlan_t2lm_validate_candidate(cm_ctx, scan_entry); 638 } 639 #else 640 static inline QDF_STATUS 641 cm_t2lm_validate_candidate(struct cnx_mgr *cm_ctx, 642 struct scan_cache_entry *scan_entry) 643 { 644 return QDF_STATUS_SUCCESS; 645 } 646 #endif 647 648 static 649 QDF_STATUS cm_if_mgr_validate_candidate(struct cnx_mgr *cm_ctx, 650 struct scan_cache_entry *scan_entry) 651 { 652 struct if_mgr_event_data event_data = {0}; 653 QDF_STATUS status = QDF_STATUS_SUCCESS; 654 655 event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq; 656 event_data.validate_bss_info.beacon_interval = scan_entry->bcn_int; 657 qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr, 658 &scan_entry->bssid); 659 cm_candidate_mlo_update(scan_entry, &event_data.validate_bss_info); 660 661 status = cm_t2lm_validate_candidate(cm_ctx, scan_entry); 662 if (QDF_IS_STATUS_ERROR(status)) 663 return status; 664 665 return if_mgr_deliver_event(cm_ctx->vdev, 666 WLAN_IF_MGR_EV_VALIDATE_CANDIDATE, 667 &event_data); 668 } 669 670 #ifdef CONN_MGR_ADV_FEATURE 671 #ifdef WLAN_FEATURE_FILS_SK 672 /* 673 * cm_create_fils_realm_hash: API to create hash using realm 674 * @fils_info: fils connection info obtained from supplicant 675 * @tmp_hash: pointer to new hash 676 * 677 * Return: QDF_STATUS 678 */ 679 static QDF_STATUS 680 cm_create_fils_realm_hash(struct wlan_fils_con_info *fils_info, 681 uint8_t *tmp_hash) 682 { 683 uint8_t *hash; 684 uint8_t *data; 685 686 if (!fils_info->realm_len) 687 return QDF_STATUS_E_NOSUPPORT; 688 689 hash = qdf_mem_malloc(SHA256_DIGEST_SIZE); 690 if (!hash) 691 return QDF_STATUS_E_NOMEM; 692 693 data = fils_info->realm; 694 qdf_get_hash(SHA256_CRYPTO_TYPE, 1, &data, &fils_info->realm_len, hash); 695 qdf_mem_copy(tmp_hash, hash, REALM_HASH_LEN); 696 qdf_mem_free(hash); 697 698 return QDF_STATUS_SUCCESS; 699 } 700 701 static void cm_update_fils_scan_filter(struct scan_filter *filter, 702 struct cm_connect_req *cm_req) 703 704 { 705 uint8_t realm_hash[REALM_HASH_LEN]; 706 QDF_STATUS status; 707 708 if (!cm_req->req.fils_info.is_fils_connection) 709 return; 710 711 status = cm_create_fils_realm_hash(&cm_req->req.fils_info, realm_hash); 712 if (QDF_IS_STATUS_ERROR(status)) 713 return; 714 715 filter->fils_scan_filter.realm_check = true; 716 mlme_debug(CM_PREFIX_FMT "creating realm based on fils info", 717 CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id)); 718 qdf_mem_copy(filter->fils_scan_filter.fils_realm, realm_hash, 719 REALM_HASH_LEN); 720 } 721 722 static inline bool cm_is_fils_connection(struct wlan_cm_connect_resp *resp) 723 { 724 return resp->is_fils_connection; 725 } 726 727 static QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx, 728 struct wlan_cm_connect_resp *resp) 729 { 730 struct fils_connect_rsp_params *fils_ie; 731 732 fils_ie = resp->connect_ies.fils_ie; 733 734 if (!fils_ie) 735 return QDF_STATUS_E_INVAL; 736 737 cm_store_fils_key(cm_ctx, true, 0, fils_ie->tk_len, fils_ie->tk, 738 &resp->bssid, resp->cm_id); 739 cm_store_fils_key(cm_ctx, false, 2, fils_ie->gtk_len, fils_ie->gtk, 740 &resp->bssid, resp->cm_id); 741 cm_set_key(cm_ctx, true, 0, &resp->bssid); 742 cm_set_key(cm_ctx, false, 2, &resp->bssid); 743 744 return QDF_STATUS_SUCCESS; 745 } 746 747 #else 748 static inline void cm_update_fils_scan_filter(struct scan_filter *filter, 749 struct cm_connect_req *cm_req) 750 { } 751 752 static inline bool cm_is_fils_connection(struct wlan_cm_connect_resp *resp) 753 { 754 return false; 755 } 756 757 static inline QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx, 758 struct wlan_cm_connect_resp *resp) 759 { 760 return QDF_STATUS_SUCCESS; 761 } 762 #endif /* WLAN_FEATURE_FILS_SK */ 763 764 /** 765 * cm_get_vdev_id_with_active_vdev_op() - Get vdev id from serialization 766 * pending queue for which disconnect or connect is ongoing 767 * @pdev: pdev common object 768 * @object: vdev object 769 * @arg: vdev operation search arg 770 * 771 * Return: None 772 */ 773 static void cm_get_vdev_id_with_active_vdev_op(struct wlan_objmgr_pdev *pdev, 774 void *object, void *arg) 775 { 776 struct vdev_op_search_arg *vdev_arg = arg; 777 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 778 uint8_t vdev_id = wlan_vdev_get_id(vdev); 779 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 780 781 if (!vdev_arg) 782 return; 783 784 /* Avoid same vdev id check */ 785 if (vdev_arg->current_vdev_id == vdev_id) 786 return; 787 788 if (opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) { 789 if (cm_is_vdev_disconnecting(vdev)) 790 vdev_arg->sta_cli_vdev_id = vdev_id; 791 return; 792 } 793 794 if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) { 795 /* Check if START/STOP AP OP is in progress */ 796 if (wlan_ser_is_non_scan_cmd_type_in_vdev_queue(vdev, 797 WLAN_SER_CMD_VDEV_START_BSS) || 798 wlan_ser_is_non_scan_cmd_type_in_vdev_queue(vdev, 799 WLAN_SER_CMD_VDEV_STOP_BSS)) 800 vdev_arg->sap_go_vdev_id = vdev_id; 801 return; 802 } 803 } 804 805 /** 806 * cm_is_any_other_vdev_connecting_disconnecting() - check whether any other 807 * vdev is in waiting for vdev operations (connect/disconnect or start/stop AP) 808 * @cm_ctx: connection manager context 809 * @cm_req: Connect request. 810 * 811 * As Connect is a blocking call this API will make sure the vdev operations on 812 * other vdev doesn't starve 813 * 814 * Return : true if any other vdev has pending operation 815 */ 816 static bool 817 cm_is_any_other_vdev_connecting_disconnecting(struct cnx_mgr *cm_ctx, 818 struct cm_req *cm_req) 819 { 820 struct wlan_objmgr_pdev *pdev; 821 uint8_t cur_vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 822 struct vdev_op_search_arg vdev_arg; 823 824 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 825 if (!pdev) { 826 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 827 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id)); 828 return false; 829 } 830 831 vdev_arg.current_vdev_id = cur_vdev_id; 832 vdev_arg.sap_go_vdev_id = WLAN_INVALID_VDEV_ID; 833 vdev_arg.sta_cli_vdev_id = WLAN_INVALID_VDEV_ID; 834 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 835 cm_get_vdev_id_with_active_vdev_op, 836 &vdev_arg, 0, 837 WLAN_MLME_CM_ID); 838 839 /* For STA/CLI avoid the fist candidate itself if possible */ 840 if (vdev_arg.sta_cli_vdev_id != WLAN_INVALID_VDEV_ID) { 841 mlme_info(CM_PREFIX_FMT "Abort connection as sta/cli vdev %d is disconnecting", 842 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id), 843 vdev_arg.sta_cli_vdev_id); 844 return true; 845 } 846 847 /* 848 * For SAP/GO ops pending avoid the next candidate, this is to support 849 * wifi sharing etc use case where we need to connect to AP in parallel 850 * to SAP operation, so try atleast one candidate. 851 */ 852 if (cm_req->connect_req.cur_candidate && 853 vdev_arg.sap_go_vdev_id != WLAN_INVALID_VDEV_ID) { 854 mlme_info(CM_PREFIX_FMT "Avoid next candidate as SAP/GO vdev %d has pending vdev op", 855 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id), 856 vdev_arg.sap_go_vdev_id); 857 return true; 858 } 859 860 return false; 861 } 862 863 QDF_STATUS 864 cm_inform_dlm_connect_complete(struct wlan_objmgr_vdev *vdev, 865 struct wlan_cm_connect_resp *resp) 866 { 867 struct wlan_objmgr_pdev *pdev; 868 869 pdev = wlan_vdev_get_pdev(vdev); 870 if (!pdev) { 871 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 872 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id)); 873 return QDF_STATUS_E_FAILURE; 874 } 875 876 if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) 877 wlan_dlm_update_bssid_connect_params(pdev, resp->bssid, 878 DLM_AP_CONNECTED); 879 880 return QDF_STATUS_SUCCESS; 881 } 882 883 /** 884 * cm_is_retry_with_same_candidate() - This API check if reconnect attempt is 885 * required with the same candidate again 886 * @cm_ctx: connection manager context 887 * @req: Connect request. 888 * @resp: connect resp from previous connection attempt 889 * 890 * This function return true if same candidate needs to be tried again 891 * 892 * Return: bool 893 */ 894 static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, 895 struct cm_connect_req *req, 896 struct wlan_cm_connect_resp *resp) 897 { 898 uint8_t max_retry_count = CM_MAX_CANDIDATE_RETRIES; 899 uint32_t key_mgmt; 900 struct wlan_objmgr_psoc *psoc; 901 bool sae_connection; 902 QDF_STATUS status; 903 qdf_freq_t freq; 904 905 psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev)); 906 key_mgmt = req->cur_candidate->entry->neg_sec_info.key_mgmt; 907 freq = req->cur_candidate->entry->channel.chan_freq; 908 909 /* Try once again for the invalid PMKID case without PMKID */ 910 if (resp->status_code == STATUS_INVALID_PMKID) 911 goto use_same_candidate; 912 913 /* Try again for the JOIN timeout if only one candidate */ 914 if (resp->reason == CM_JOIN_TIMEOUT && 915 qdf_list_size(req->candidate_list) == 1) { 916 /* 917 * If there is a interface connected which can lead to MCC, 918 * do not retry as it can lead to beacon miss on that interface. 919 * Coz as part of vdev start mac remain on candidate freq for 3 920 * sec. 921 */ 922 if (policy_mgr_will_freq_lead_to_mcc(psoc, freq)) 923 return false; 924 925 wlan_mlme_get_sae_assoc_retry_count(psoc, &max_retry_count); 926 goto use_same_candidate; 927 } 928 929 /* 930 * Try again for the ASSOC timeout in SAE connection or 931 * AP has reconnect on assoc timeout OUI. 932 */ 933 sae_connection = key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE | 934 1 << WLAN_CRYPTO_KEY_MGMT_FT_SAE | 935 1 << WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY); 936 if (resp->reason == CM_ASSOC_TIMEOUT && (sae_connection || 937 (mlme_get_reconn_after_assoc_timeout_flag(psoc, resp->vdev_id)))) { 938 /* For SAE use max retry count from INI */ 939 if (sae_connection) 940 wlan_mlme_get_sae_assoc_retry_count(psoc, 941 &max_retry_count); 942 goto use_same_candidate; 943 } 944 945 return false; 946 947 use_same_candidate: 948 if (req->cur_candidate_retries >= max_retry_count) 949 return false; 950 951 status = cm_if_mgr_validate_candidate(cm_ctx, 952 req->cur_candidate->entry); 953 if (QDF_IS_STATUS_ERROR(status)) 954 return false; 955 956 mlme_info(CM_PREFIX_FMT "Retry again with " QDF_MAC_ADDR_FMT ", status code %d reason %d key_mgmt 0x%x retry count %d max retry %d", 957 CM_PREFIX_REF(resp->vdev_id, resp->cm_id), 958 QDF_MAC_ADDR_REF(resp->bssid.bytes), resp->status_code, 959 resp->reason, key_mgmt, req->cur_candidate_retries, 960 max_retry_count); 961 962 req->cur_candidate_retries++; 963 964 return true; 965 } 966 967 /* 968 * Do not allow last connect attempt after 25 sec, assuming last attempt will 969 * complete in max 10 sec, total connect time will not be more than 35 sec. 970 * Do not confuse this with active command timeout, that is taken care by 971 * CM_MAX_PER_CANDIDATE_CONNECT_TIMEOUT 972 */ 973 #define CM_CONNECT_MAX_ACTIVE_TIME 25000 974 975 /** 976 * cm_is_time_allowed_for_connect_attempt() - This API check if next connect 977 * attempt can be tried within allocated time. 978 * @cm_ctx: connection manager context 979 * @req: Connect request. 980 * 981 * This function return true if connect attempt can be tried so that total time 982 * taken by connect req do not exceed 30-35 seconds. 983 * 984 * Return: bool 985 */ 986 static bool cm_is_time_allowed_for_connect_attempt(struct cnx_mgr *cm_ctx, 987 struct cm_connect_req *req) 988 { 989 qdf_time_t time_since_connect_active; 990 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 991 992 time_since_connect_active = qdf_mc_timer_get_system_time() - 993 req->connect_active_time; 994 if (time_since_connect_active >= CM_CONNECT_MAX_ACTIVE_TIME) { 995 mlme_info(CM_PREFIX_FMT "Max time allocated (%d ms) for connect completed, cur time %lu, active time %lu and diff %lu", 996 CM_PREFIX_REF(vdev_id, req->cm_id), 997 CM_CONNECT_MAX_ACTIVE_TIME, 998 qdf_mc_timer_get_system_time(), 999 req->connect_active_time, 1000 time_since_connect_active); 1001 return false; 1002 } 1003 1004 return true; 1005 } 1006 1007 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev, 1008 struct cnx_mgr *cm_ctx, 1009 struct scan_filter *filter, 1010 struct cm_connect_req *cm_req) 1011 { 1012 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 1013 1014 /* Select only ESS type */ 1015 filter->bss_type = WLAN_TYPE_BSS; 1016 filter->enable_adaptive_11r = 1017 wlan_mlme_adaptive_11r_enabled(psoc); 1018 if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE) 1019 return; 1020 /* For link vdev, we don't filter any channels. 1021 * Dual STA mode, one link can be disabled in post connection 1022 * if needed. 1023 */ 1024 if (!cm_req->req.is_non_assoc_link) 1025 wlan_cm_dual_sta_roam_update_connect_channels(psoc, filter); 1026 filter->dot11mode = cm_req->req.dot11mode_filter; 1027 cm_update_fils_scan_filter(filter, cm_req); 1028 } 1029 1030 static void cm_update_security_filter(struct scan_filter *filter, 1031 struct wlan_cm_connect_req *req) 1032 { 1033 /* Ignore security match for rsn override, OSEN and WPS connection */ 1034 if (req->force_rsne_override || req->is_wps_connection || 1035 req->is_osen_connection) { 1036 filter->ignore_auth_enc_type = 1; 1037 return; 1038 } 1039 1040 filter->authmodeset = req->crypto.auth_type; 1041 filter->ucastcipherset = req->crypto.ciphers_pairwise; 1042 filter->key_mgmt = req->crypto.akm_suites; 1043 filter->mcastcipherset = req->crypto.group_cipher; 1044 filter->mgmtcipherset = req->crypto.mgmt_ciphers; 1045 cm_set_pmf_caps(req, filter); 1046 } 1047 1048 /** 1049 * cm_set_fils_wep_key() - check and set wep or fils keys if required 1050 * @cm_ctx: connection manager context 1051 * @resp: connect resp 1052 * 1053 * Context: Can be called from any context and to be used only after posting a 1054 * msg to SM (ie holding the SM lock) i.e. on successful connection. 1055 */ 1056 static void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx, 1057 struct wlan_cm_connect_resp *resp) 1058 { 1059 int32_t cipher; 1060 struct qdf_mac_addr broadcast_mac = QDF_MAC_ADDR_BCAST_INIT; 1061 1062 /* Check and set FILS keys */ 1063 if (cm_is_fils_connection(resp)) { 1064 cm_set_fils_key(cm_ctx, resp); 1065 return; 1066 } 1067 /* Check and set WEP keys */ 1068 cipher = wlan_crypto_get_param(cm_ctx->vdev, 1069 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 1070 if (cipher < 0) 1071 return; 1072 1073 if (!(cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40 | 1074 1 << WLAN_CRYPTO_CIPHER_WEP_104))) 1075 return; 1076 1077 cm_set_key(cm_ctx, true, 0, &resp->bssid); 1078 cm_set_key(cm_ctx, false, 0, &broadcast_mac); 1079 } 1080 1081 static void cm_teardown_tdls(struct wlan_objmgr_vdev *vdev) 1082 { 1083 struct wlan_objmgr_psoc *psoc; 1084 1085 psoc = wlan_vdev_get_psoc(vdev); 1086 if (!psoc) 1087 return; 1088 1089 wlan_tdls_teardown_links_sync(psoc); 1090 } 1091 1092 #else 1093 static inline bool 1094 cm_is_any_other_vdev_connecting_disconnecting(struct cnx_mgr *cm_ctx, 1095 struct cm_req *cm_req) 1096 { 1097 return false; 1098 } 1099 1100 static inline 1101 bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, 1102 struct cm_connect_req *req, 1103 struct wlan_cm_connect_resp *resp) 1104 { 1105 return false; 1106 } 1107 1108 static inline 1109 bool cm_is_time_allowed_for_connect_attempt(struct cnx_mgr *cm_ctx, 1110 struct cm_connect_req *req) 1111 { 1112 return true; 1113 } 1114 1115 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev, 1116 struct cnx_mgr *cm_ctx, 1117 struct scan_filter *filter, 1118 struct cm_connect_req *cm_req) 1119 { 1120 struct wlan_objmgr_vdev *vdev = cm_ctx->vdev; 1121 1122 if (cm_ctx->cm_candidate_advance_filter) 1123 cm_ctx->cm_candidate_advance_filter(vdev, filter); 1124 } 1125 1126 static void cm_update_security_filter(struct scan_filter *filter, 1127 struct wlan_cm_connect_req *req) 1128 { 1129 if (!QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WAPI) && 1130 !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_RSNA) && 1131 !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WPA)) { 1132 filter->ignore_auth_enc_type = 1; 1133 return; 1134 } 1135 1136 filter->authmodeset = req->crypto.auth_type; 1137 filter->ucastcipherset = req->crypto.ciphers_pairwise; 1138 filter->key_mgmt = req->crypto.akm_suites; 1139 filter->mcastcipherset = req->crypto.group_cipher; 1140 filter->mgmtcipherset = req->crypto.mgmt_ciphers; 1141 cm_set_pmf_caps(req, filter); 1142 } 1143 1144 static inline void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx, 1145 struct wlan_cm_connect_resp *resp) 1146 {} 1147 1148 QDF_STATUS 1149 cm_peer_create_on_bss_select_ind_resp(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 1150 { 1151 struct cm_req *cm_req; 1152 1153 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 1154 if (!cm_req) 1155 return QDF_STATUS_E_FAILURE; 1156 1157 /* Update vdev mlme mac address based on connection type */ 1158 cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req); 1159 1160 cm_create_bss_peer(cm_ctx, &cm_req->connect_req); 1161 1162 return QDF_STATUS_SUCCESS; 1163 } 1164 1165 QDF_STATUS cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev, 1166 QDF_STATUS status) 1167 { 1168 struct cnx_mgr *cm_ctx; 1169 QDF_STATUS qdf_status; 1170 wlan_cm_id cm_id; 1171 uint32_t prefix; 1172 struct wlan_cm_connect_resp *resp; 1173 1174 cm_ctx = cm_get_cm_ctx(vdev); 1175 if (!cm_ctx) 1176 return QDF_STATUS_E_INVAL; 1177 1178 cm_id = cm_ctx->active_cm_id; 1179 prefix = CM_ID_GET_PREFIX(cm_id); 1180 1181 if (prefix != CONNECT_REQ_PREFIX) { 1182 mlme_err(CM_PREFIX_FMT "active req is not connect req", 1183 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id)); 1184 return QDF_STATUS_E_INVAL; 1185 } 1186 1187 if (QDF_IS_STATUS_SUCCESS(status)) { 1188 qdf_status = 1189 cm_sm_deliver_event(vdev, 1190 WLAN_CM_SM_EV_BSS_SELECT_IND_SUCCESS, 1191 sizeof(wlan_cm_id), &cm_id); 1192 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 1193 return qdf_status; 1194 1195 goto post_err; 1196 } 1197 1198 /* In case of failure try with next candidate */ 1199 resp = qdf_mem_malloc(sizeof(*resp)); 1200 if (!resp) { 1201 qdf_status = QDF_STATUS_E_NOMEM; 1202 goto post_err; 1203 } 1204 1205 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, 1206 CM_BSS_SELECT_IND_FAILED); 1207 qdf_status = 1208 cm_sm_deliver_event(vdev, 1209 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 1210 sizeof(*resp), resp); 1211 qdf_mem_free(resp); 1212 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 1213 return qdf_status; 1214 1215 post_err: 1216 /* 1217 * If there is a event posting error it means the SM state is not in 1218 * JOIN ACTIVE (some new cmd has changed the state of SM), so just 1219 * complete the connect command. 1220 */ 1221 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 1222 return qdf_status; 1223 } 1224 1225 static inline void cm_teardown_tdls(struct wlan_objmgr_vdev *vdev) {} 1226 1227 #endif /* CONN_MGR_ADV_FEATURE */ 1228 1229 static void cm_connect_prepare_scan_filter(struct wlan_objmgr_pdev *pdev, 1230 struct cnx_mgr *cm_ctx, 1231 struct cm_connect_req *cm_req, 1232 struct scan_filter *filter, 1233 bool security_valid_for_6ghz) 1234 { 1235 if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) { 1236 filter->num_of_bssid = 1; 1237 qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid); 1238 } 1239 1240 qdf_copy_macaddr(&filter->bssid_hint, &cm_req->req.bssid_hint); 1241 filter->num_of_ssid = 1; 1242 qdf_mem_copy(&filter->ssid_list[0], &cm_req->req.ssid, 1243 sizeof(struct wlan_ssid)); 1244 1245 if (cm_req->req.chan_freq) { 1246 filter->num_of_channels = 1; 1247 filter->chan_freq_list[0] = cm_req->req.chan_freq; 1248 } 1249 1250 /* Security is not valid for 6Ghz so ignore 6Ghz APs */ 1251 if (!security_valid_for_6ghz) 1252 filter->ignore_6ghz_channel = true; 1253 1254 if (cm_req->req.is_non_assoc_link) 1255 filter->ignore_6ghz_channel = false; 1256 1257 cm_update_security_filter(filter, &cm_req->req); 1258 cm_update_advance_filter(pdev, cm_ctx, filter, cm_req); 1259 } 1260 1261 #ifdef WLAN_FEATURE_11BE_MLO 1262 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 1263 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req) 1264 { 1265 if (cm_req->req.is_non_assoc_link) 1266 return QDF_STATUS_E_FAILURE; 1267 1268 return QDF_STATUS_SUCCESS; 1269 } 1270 #else 1271 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req) 1272 { 1273 if (cm_req->req.ml_parnter_info.num_partner_links) 1274 return QDF_STATUS_E_FAILURE; 1275 1276 return QDF_STATUS_SUCCESS; 1277 } 1278 #endif 1279 #else 1280 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req) 1281 { 1282 return QDF_STATUS_SUCCESS; 1283 } 1284 #endif 1285 1286 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) 1287 #define CFG_MLO_ASSOC_LINK_BAND_MAX 0x70 1288 1289 static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, 1290 struct cm_connect_req *cm_req, 1291 struct scan_filter *filter) 1292 { 1293 struct wlan_objmgr_psoc *psoc; 1294 1295 psoc = wlan_pdev_get_psoc(pdev); 1296 filter->band_bitmap = wlan_mlme_get_sta_mlo_conn_band_bmp(psoc); 1297 /* Apply assoc band filter only for assoc link */ 1298 if (cm_req->req.is_non_assoc_link) { 1299 filter->band_bitmap = filter->band_bitmap | 1300 CFG_MLO_ASSOC_LINK_BAND_MAX; 1301 } 1302 mlme_debug("band bitmap: 0x%x", filter->band_bitmap); 1303 1304 return QDF_STATUS_SUCCESS; 1305 } 1306 #else 1307 static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, 1308 struct cm_connect_req *cm_req, 1309 struct scan_filter *filter) 1310 { 1311 return QDF_STATUS_SUCCESS; 1312 } 1313 #endif 1314 1315 static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev, 1316 struct cnx_mgr *cm_ctx, 1317 struct cm_connect_req *cm_req) 1318 { 1319 struct scan_filter *filter; 1320 uint32_t num_bss = 0; 1321 enum QDF_OPMODE op_mode; 1322 qdf_list_t *candidate_list; 1323 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1324 bool security_valid_for_6ghz; 1325 const uint8_t *rsnxe; 1326 1327 filter = qdf_mem_malloc(sizeof(*filter)); 1328 if (!filter) 1329 return QDF_STATUS_E_NOMEM; 1330 1331 rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, 1332 cm_req->req.assoc_ie.ptr, 1333 cm_req->req.assoc_ie.len); 1334 security_valid_for_6ghz = 1335 wlan_cm_6ghz_allowed_for_akm(wlan_pdev_get_psoc(pdev), 1336 cm_req->req.crypto.akm_suites, 1337 cm_req->req.crypto.rsn_caps, 1338 rsnxe, cm_req->req.sae_pwe, 1339 cm_req->req.is_wps_connection); 1340 1341 /* 1342 * Ignore connect req if the freq is provided and its 6Ghz and 1343 * security is not valid for 6Ghz 1344 */ 1345 if (cm_req->req.chan_freq && !security_valid_for_6ghz && 1346 WLAN_REG_IS_6GHZ_CHAN_FREQ(cm_req->req.chan_freq)) { 1347 mlme_info(CM_PREFIX_FMT "6ghz freq (%d) given and 6Ghz not allowed for the security in connect req", 1348 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1349 cm_req->req.chan_freq); 1350 return QDF_STATUS_E_INVAL; 1351 } 1352 cm_connect_prepare_scan_filter(pdev, cm_ctx, cm_req, filter, 1353 security_valid_for_6ghz); 1354 1355 cm_update_mlo_filter(pdev, cm_req, filter); 1356 1357 candidate_list = wlan_scan_get_result(pdev, filter); 1358 if (candidate_list) { 1359 num_bss = qdf_list_size(candidate_list); 1360 mlme_debug(CM_PREFIX_FMT "num_entries found %d", 1361 CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss); 1362 } 1363 1364 op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev); 1365 if (num_bss && op_mode == QDF_STA_MODE && 1366 !cm_req->req.is_non_assoc_link) 1367 cm_calculate_scores(cm_ctx, pdev, filter, candidate_list); 1368 qdf_mem_free(filter); 1369 1370 if (!candidate_list || !qdf_list_size(candidate_list)) { 1371 QDF_STATUS status; 1372 1373 if (candidate_list) 1374 wlan_scan_purge_results(candidate_list); 1375 mlme_info(CM_PREFIX_FMT "no valid candidate found, num_bss %d scan_id %d", 1376 CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss, 1377 cm_req->scan_id); 1378 1379 /* 1380 * If connect scan was already done OR candidate were found 1381 * but none of them were valid OR if ML link connection 1382 * return QDF_STATUS_E_EMPTY. 1383 */ 1384 if (cm_req->scan_id || num_bss || 1385 QDF_IS_STATUS_ERROR(cm_is_scan_support(cm_req))) 1386 return QDF_STATUS_E_EMPTY; 1387 1388 /* Try connect scan to search for any valid candidate */ 1389 status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_SCAN, 1390 sizeof(*cm_req), cm_req); 1391 /* 1392 * If connect scan is initiated, return pending, so that 1393 * connect start after scan complete 1394 */ 1395 if (QDF_IS_STATUS_SUCCESS(status)) 1396 status = QDF_STATUS_E_PENDING; 1397 1398 return status; 1399 } 1400 cm_req->candidate_list = candidate_list; 1401 1402 return QDF_STATUS_SUCCESS; 1403 } 1404 1405 QDF_STATUS cm_if_mgr_inform_connect_complete(struct wlan_objmgr_vdev *vdev, 1406 QDF_STATUS connect_status) 1407 { 1408 struct if_mgr_event_data *connect_complete; 1409 1410 connect_complete = qdf_mem_malloc(sizeof(*connect_complete)); 1411 if (!connect_complete) 1412 return QDF_STATUS_E_NOMEM; 1413 1414 connect_complete->status = connect_status; 1415 if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_COMPLETE, 1416 connect_complete); 1417 qdf_mem_free(connect_complete); 1418 1419 return QDF_STATUS_SUCCESS; 1420 } 1421 1422 static QDF_STATUS 1423 cm_if_mgr_inform_connect_start(struct wlan_objmgr_vdev *vdev) 1424 { 1425 return if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_START, NULL); 1426 } 1427 1428 QDF_STATUS 1429 cm_handle_connect_req_in_non_init_state(struct cnx_mgr *cm_ctx, 1430 struct cm_connect_req *cm_req, 1431 enum wlan_cm_sm_state cm_state_substate) 1432 { 1433 if (cm_state_substate != WLAN_CM_S_CONNECTED && 1434 cm_is_connect_req_reassoc(&cm_req->req)) { 1435 cm_req->req.reassoc_in_non_connected = true; 1436 mlme_debug(CM_PREFIX_FMT "Reassoc received in %d state", 1437 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 1438 cm_req->cm_id), 1439 cm_state_substate); 1440 } 1441 1442 switch (cm_state_substate) { 1443 case WLAN_CM_S_ROAMING: 1444 /* for FW roam/LFR3 remove the req from the list */ 1445 if (cm_roam_offload_enabled(wlan_vdev_get_psoc(cm_ctx->vdev))) 1446 cm_flush_pending_request(cm_ctx, ROAM_REQ_PREFIX, 1447 false); 1448 fallthrough; 1449 case WLAN_CM_S_CONNECTED: 1450 case WLAN_CM_SS_JOIN_ACTIVE: 1451 /* 1452 * In roaming state, there would be no 1453 * pending command, so for new connect request, queue internal 1454 * disconnect. The preauth and reassoc process will be aborted 1455 * as the state machine will be moved to connecting state and 1456 * preauth/reassoc/roam start event posting will fail. 1457 * 1458 * In connected state, there would be no pending command, so 1459 * for new connect request, queue internal disconnect 1460 * 1461 * In join active state there would be only one active connect 1462 * request in the cm req list, so to abort at certain stages and 1463 * to cleanup after its completion, queue internal disconnect. 1464 */ 1465 cm_initiate_internal_disconnect(cm_ctx); 1466 break; 1467 case WLAN_CM_SS_SCAN: 1468 /* In the scan state abort the ongoing scan */ 1469 cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev), 1470 cm_ctx->vdev); 1471 fallthrough; 1472 case WLAN_CM_SS_JOIN_PENDING: 1473 /* 1474 * In case of scan or join pending there could be 2 scenarios:- 1475 * 1476 * 1. There is a connect request pending, so just remove 1477 * the pending connect req. As we will queue a new connect 1478 * req, all resp for pending connect req will be dropped. 1479 * 2. There is a connect request in active and 1480 * and a internal disconnect followed by a connect req in 1481 * pending. In this case the disconnect will take care of 1482 * cleaning up the active connect request and thus only 1483 * remove the pending connect. 1484 */ 1485 cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, false); 1486 break; 1487 case WLAN_CM_S_DISCONNECTING: 1488 /* 1489 * Flush failed pending connect req as new req is received 1490 * and its no longer the latest one. 1491 */ 1492 if (cm_ctx->connect_count) 1493 cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, 1494 true); 1495 /* 1496 * In case of disconnecting state, there could be 2 scenarios:- 1497 * In both case no state specific action is required. 1498 * 1. There is disconnect request in the cm_req list, no action 1499 * required to cleanup. 1500 * so just add the connect request to the list. 1501 * 2. There is a connect request activated, followed by 1502 * disconnect in pending queue. So keep the disconnect 1503 * to cleanup the active connect and no action required to 1504 * cleanup. 1505 */ 1506 break; 1507 default: 1508 mlme_err("Vdev %d Connect req in invalid state %d", 1509 wlan_vdev_get_id(cm_ctx->vdev), 1510 cm_state_substate); 1511 return QDF_STATUS_E_FAILURE; 1512 }; 1513 1514 /* Queue the new connect request after state specific actions */ 1515 return cm_add_connect_req_to_list(cm_ctx, cm_req); 1516 } 1517 1518 QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx, 1519 struct cm_connect_req *cm_req) 1520 { 1521 struct wlan_objmgr_pdev *pdev; 1522 struct wlan_objmgr_psoc *psoc; 1523 enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE; 1524 QDF_STATUS status; 1525 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1526 1527 /* Interface event */ 1528 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 1529 if (!pdev) { 1530 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 1531 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1532 goto connect_err; 1533 } 1534 1535 psoc = wlan_pdev_get_psoc(pdev); 1536 if (!psoc) { 1537 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 1538 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1539 goto connect_err; 1540 } 1541 1542 /* 1543 * Do not initiate the duplicate ifmanager and connect start ind if 1544 * this is called from Scan for ssid 1545 */ 1546 if (!cm_req->scan_id) { 1547 cm_if_mgr_inform_connect_start(cm_ctx->vdev); 1548 status = mlme_cm_connect_start_ind(cm_ctx->vdev, &cm_req->req); 1549 if (QDF_IS_STATUS_ERROR(status)) { 1550 reason = CM_NO_CANDIDATE_FOUND; 1551 goto connect_err; 1552 } 1553 } 1554 1555 status = cm_connect_get_candidates(pdev, cm_ctx, cm_req); 1556 1557 /* In case of status pending connect will continue after scan */ 1558 if (status == QDF_STATUS_E_PENDING) 1559 return QDF_STATUS_SUCCESS; 1560 if (QDF_IS_STATUS_ERROR(status)) { 1561 reason = CM_NO_CANDIDATE_FOUND; 1562 goto connect_err; 1563 } 1564 1565 status = cm_check_for_hw_mode_change(psoc, cm_req->candidate_list, 1566 vdev_id, cm_req->cm_id); 1567 if (QDF_IS_STATUS_ERROR(status) && status != QDF_STATUS_E_ALREADY) { 1568 reason = CM_HW_MODE_FAILURE; 1569 mlme_err(CM_PREFIX_FMT "Failed to set HW mode change", 1570 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1571 goto connect_err; 1572 } else if (QDF_IS_STATUS_SUCCESS(status)) { 1573 mlme_debug(CM_PREFIX_FMT "Connect will continue after HW mode change", 1574 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1575 return QDF_STATUS_SUCCESS; 1576 } 1577 1578 status = cm_ser_connect_req(pdev, cm_ctx, cm_req); 1579 if (QDF_IS_STATUS_ERROR(status)) { 1580 reason = CM_SER_FAILURE; 1581 goto connect_err; 1582 } 1583 1584 return QDF_STATUS_SUCCESS; 1585 1586 connect_err: 1587 return cm_send_connect_start_fail(cm_ctx, cm_req, reason); 1588 } 1589 1590 /** 1591 * cm_get_valid_candidate() - This API will be called to get the next valid 1592 * candidate 1593 * @cm_ctx: connection manager context 1594 * @cm_req: Connect request. 1595 * @resp: connect resp from previous connection attempt 1596 * @same_candidate_used: this will be set if same candidate used 1597 * 1598 * This function return a valid candidate to try connection. It return failure 1599 * if no valid candidate is present or all valid candidate are tried. 1600 * 1601 * Return: QDF status 1602 */ 1603 static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx, 1604 struct cm_req *cm_req, 1605 struct wlan_cm_connect_resp *resp, 1606 bool *same_candidate_used) 1607 { 1608 struct wlan_objmgr_psoc *psoc; 1609 struct scan_cache_node *scan_node = NULL; 1610 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 1611 struct scan_cache_node *new_candidate = NULL, *prev_candidate; 1612 QDF_STATUS status = QDF_STATUS_SUCCESS; 1613 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1614 bool use_same_candidate = false; 1615 int32_t akm; 1616 1617 psoc = wlan_vdev_get_psoc(cm_ctx->vdev); 1618 if (!psoc) { 1619 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 1620 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1621 return QDF_STATUS_E_FAILURE; 1622 } 1623 1624 prev_candidate = cm_req->connect_req.cur_candidate; 1625 /* 1626 * In case of STA/CLI + STA/CLI, if a STA/CLI is in connecting state and 1627 * a disconnect is received on any other STA/CLI, the disconnect can 1628 * timeout waiting for the connection on first STA/CLI to get completed. 1629 * This is because the connect is a blocking serialization command and 1630 * it can try multiple candidates and thus can take upto 30+ sec to 1631 * complete. 1632 * 1633 * Now osif will proceed with vdev delete after disconnect timeout. 1634 * This can lead to vdev delete sent without vdev down/stop/peer delete 1635 * for the vdev. 1636 * 1637 * Same way if a SAP/GO has start/stop command or peer disconnect in 1638 * pending queue, delay in processing it can cause timeouts and other 1639 * issues. 1640 * 1641 * So abort the next connection attempt if any of the vdev is waiting 1642 * for vdev operation to avoid timeouts 1643 */ 1644 if (cm_is_any_other_vdev_connecting_disconnecting(cm_ctx, cm_req)) { 1645 status = QDF_STATUS_E_FAILURE; 1646 goto flush_single_pmk; 1647 } 1648 1649 if (cm_req->connect_req.connect_attempts >= 1650 cm_ctx->max_connect_attempts) { 1651 mlme_info(CM_PREFIX_FMT "%d attempts tried, max %d", 1652 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1653 cm_req->connect_req.connect_attempts, 1654 cm_ctx->max_connect_attempts); 1655 status = QDF_STATUS_E_FAILURE; 1656 goto flush_single_pmk; 1657 } 1658 1659 /* From 2nd attempt onward, check if time allows for a new attempt */ 1660 if (cm_req->connect_req.connect_attempts && 1661 !cm_is_time_allowed_for_connect_attempt(cm_ctx, 1662 &cm_req->connect_req)) { 1663 status = QDF_STATUS_E_FAILURE; 1664 goto flush_single_pmk; 1665 } 1666 1667 if (prev_candidate && resp && 1668 cm_is_retry_with_same_candidate(cm_ctx, &cm_req->connect_req, 1669 resp)) { 1670 new_candidate = prev_candidate; 1671 use_same_candidate = true; 1672 goto try_same_candidate; 1673 } 1674 1675 /* 1676 * Get next candidate if prev_candidate is not NULL, else get 1677 * the first candidate 1678 */ 1679 if (prev_candidate) 1680 qdf_list_peek_next(cm_req->connect_req.candidate_list, 1681 &prev_candidate->node, &cur_node); 1682 else 1683 qdf_list_peek_front(cm_req->connect_req.candidate_list, 1684 &cur_node); 1685 1686 while (cur_node) { 1687 qdf_list_peek_next(cm_req->connect_req.candidate_list, 1688 cur_node, &next_node); 1689 scan_node = qdf_container_of(cur_node, struct scan_cache_node, 1690 node); 1691 status = cm_if_mgr_validate_candidate(cm_ctx, scan_node->entry); 1692 if (QDF_IS_STATUS_SUCCESS(status)) { 1693 new_candidate = scan_node; 1694 break; 1695 } 1696 1697 cur_node = next_node; 1698 next_node = NULL; 1699 } 1700 1701 /* 1702 * If cur_node is NULL prev candidate was last to be tried so no more 1703 * candidates left for connect now. 1704 */ 1705 if (!cur_node) { 1706 mlme_debug(CM_PREFIX_FMT "No more candidates left", 1707 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1708 cm_req->connect_req.cur_candidate = NULL; 1709 status = QDF_STATUS_E_FAILURE; 1710 goto flush_single_pmk; 1711 } 1712 1713 /* Reset current candidate retries when a new candidate is tried */ 1714 cm_req->connect_req.cur_candidate_retries = 0; 1715 1716 try_same_candidate: 1717 cm_req->connect_req.connect_attempts++; 1718 cm_req->connect_req.cur_candidate = new_candidate; 1719 1720 flush_single_pmk: 1721 akm = wlan_crypto_get_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 1722 /* 1723 * If connection fails with Single PMK bssid (prev candidate), 1724 * clear the pmk entry. Flush only in case if we are not trying again 1725 * with same candidate again. 1726 */ 1727 if (prev_candidate && !use_same_candidate && 1728 util_scan_entry_single_pmk(psoc, prev_candidate->entry) && 1729 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE)) 1730 cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, 1731 &prev_candidate->entry->bssid); 1732 1733 if (same_candidate_used) 1734 *same_candidate_used = use_same_candidate; 1735 1736 return status; 1737 } 1738 1739 static QDF_STATUS 1740 cm_send_bss_select_ind(struct cnx_mgr *cm_ctx, struct cm_connect_req *req) 1741 { 1742 QDF_STATUS status; 1743 struct wlan_cm_vdev_connect_req vdev_req; 1744 struct wlan_cm_connect_resp *resp; 1745 1746 vdev_req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1747 vdev_req.cm_id = req->cm_id; 1748 vdev_req.bss = req->cur_candidate; 1749 1750 status = mlme_cm_bss_select_ind(cm_ctx->vdev, &vdev_req); 1751 if (QDF_IS_STATUS_SUCCESS(status) || 1752 status == QDF_STATUS_E_NOSUPPORT) 1753 return status; 1754 1755 /* In supported and failure try with next candidate */ 1756 mlme_err(CM_PREFIX_FMT "mlme candidate select indication failed %d", 1757 CM_PREFIX_REF(vdev_req.vdev_id, req->cm_id), status); 1758 resp = qdf_mem_malloc(sizeof(*resp)); 1759 if (!resp) 1760 return QDF_STATUS_E_FAILURE; 1761 1762 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, 1763 CM_BSS_SELECT_IND_FAILED); 1764 cm_sm_deliver_event_sync(cm_ctx, 1765 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 1766 sizeof(*resp), resp); 1767 qdf_mem_free(resp); 1768 1769 return QDF_STATUS_SUCCESS; 1770 } 1771 1772 static void cm_update_ser_timer_for_new_candidate(struct cnx_mgr *cm_ctx, 1773 wlan_cm_id cm_id) 1774 { 1775 struct wlan_serialization_command cmd; 1776 1777 cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT; 1778 cmd.cmd_id = cm_id; 1779 cmd.cmd_timeout_duration = cm_ctx->connect_timeout; 1780 cmd.vdev = cm_ctx->vdev; 1781 1782 wlan_serialization_update_timer(&cmd); 1783 } 1784 1785 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx, 1786 struct wlan_cm_connect_resp *resp) 1787 { 1788 QDF_STATUS status; 1789 struct cm_req *cm_req; 1790 bool same_candidate_used = false; 1791 1792 cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id); 1793 if (!cm_req) 1794 return QDF_STATUS_E_FAILURE; 1795 1796 status = cm_get_valid_candidate(cm_ctx, cm_req, resp, 1797 &same_candidate_used); 1798 if (QDF_IS_STATUS_ERROR(status)) 1799 goto connect_err; 1800 1801 /* 1802 * Do not indicate to OSIF if same candidate is used again as we are not 1803 * done with this candidate. So inform once we move to next candidate. 1804 * This will also avoid flush for the scan entry. 1805 */ 1806 if (!same_candidate_used) 1807 mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp); 1808 1809 cm_update_ser_timer_for_new_candidate(cm_ctx, resp->cm_id); 1810 1811 status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req); 1812 1813 /* 1814 * If candidate select indication is not supported continue with bss 1815 * peer create, else peer will be created after resp. 1816 */ 1817 if (status == QDF_STATUS_E_NOSUPPORT) { 1818 /* Update vdev mlme mac address based on connection type */ 1819 cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req); 1820 1821 cm_create_bss_peer(cm_ctx, &cm_req->connect_req); 1822 } else if (QDF_IS_STATUS_ERROR(status)) { 1823 goto connect_err; 1824 } 1825 1826 return QDF_STATUS_SUCCESS; 1827 1828 connect_err: 1829 return cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, 1830 sizeof(*resp), resp); 1831 1832 } 1833 1834 bool cm_connect_resp_cmid_match_list_head(struct cnx_mgr *cm_ctx, 1835 struct wlan_cm_connect_resp *resp) 1836 { 1837 return cm_check_cmid_match_list_head(cm_ctx, &resp->cm_id); 1838 } 1839 1840 void cm_fill_vdev_crypto_params(struct cnx_mgr *cm_ctx, 1841 struct wlan_cm_connect_req *req) 1842 { 1843 /* fill vdev crypto from the connect req */ 1844 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_AUTH_MODE, 1845 req->crypto.auth_type); 1846 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, 1847 req->crypto.akm_suites); 1848 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER, 1849 req->crypto.ciphers_pairwise); 1850 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER, 1851 req->crypto.group_cipher); 1852 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER, 1853 req->crypto.mgmt_ciphers); 1854 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_RSN_CAP, 1855 req->crypto.rsn_caps); 1856 } 1857 1858 QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 1859 { 1860 struct cm_req *cm_req; 1861 QDF_STATUS status; 1862 struct wlan_cm_connect_req *req; 1863 1864 cm_ctx->active_cm_id = *cm_id; 1865 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 1866 if (!cm_req) { 1867 /* 1868 * Remove the command from serialization active queue, if 1869 * connect req was not found, to avoid active cmd timeout. 1870 * This can happen if a thread tried to flush the pending 1871 * connect request and while doing so, it removed the 1872 * CM pending request, but before it tried to remove pending 1873 * command from serialization, the command becomes active in 1874 * another thread. 1875 */ 1876 cm_remove_cmd_from_serialization(cm_ctx, *cm_id); 1877 return QDF_STATUS_E_INVAL; 1878 } 1879 1880 cm_req->connect_req.connect_active_time = 1881 qdf_mc_timer_get_system_time(); 1882 req = &cm_req->connect_req.req; 1883 wlan_vdev_mlme_set_ssid(cm_ctx->vdev, req->ssid.ssid, req->ssid.length); 1884 /* free vdev keys before setting crypto params */ 1885 if (!wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev)) 1886 wlan_crypto_free_vdev_key(cm_ctx->vdev); 1887 cm_fill_vdev_crypto_params(cm_ctx, req); 1888 cm_store_wep_key(cm_ctx, &req->crypto, *cm_id); 1889 1890 status = cm_get_valid_candidate(cm_ctx, cm_req, NULL, NULL); 1891 if (QDF_IS_STATUS_ERROR(status)) 1892 goto connect_err; 1893 1894 status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req); 1895 /* 1896 * If candidate select indication is not supported continue with bss 1897 * peer create, else peer will be created after resp. 1898 */ 1899 if (status == QDF_STATUS_E_NOSUPPORT) { 1900 /* Update vdev mlme mac address based on connection type */ 1901 cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req); 1902 1903 cm_create_bss_peer(cm_ctx, &cm_req->connect_req); 1904 } else if (QDF_IS_STATUS_ERROR(status)) { 1905 goto connect_err; 1906 } 1907 1908 return QDF_STATUS_SUCCESS; 1909 1910 connect_err: 1911 return cm_send_connect_start_fail(cm_ctx, 1912 &cm_req->connect_req, CM_JOIN_FAILED); 1913 } 1914 1915 #ifdef WLAN_FEATURE_FILS_SK 1916 static void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req, 1917 struct cm_req *cm_req) 1918 { 1919 req->fils_info = &cm_req->connect_req.req.fils_info; 1920 } 1921 1922 static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx, 1923 struct wlan_cm_connect_resp *resp) 1924 { 1925 int32_t key_mgmt; 1926 1927 /* 1928 * Check and set only in case of failure and when 1929 * resp->is_fils_connection is not already set, else return. 1930 */ 1931 if (QDF_IS_STATUS_SUCCESS(resp->connect_status) || 1932 resp->is_fils_connection) 1933 return; 1934 1935 key_mgmt = wlan_crypto_get_param(cm_ctx->vdev, 1936 WLAN_CRYPTO_PARAM_KEY_MGMT); 1937 1938 if (key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA256 | 1939 1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA384 | 1940 1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256 | 1941 1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) 1942 resp->is_fils_connection = true; 1943 } 1944 #else 1945 static inline void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req, 1946 struct cm_req *cm_req) 1947 { 1948 } 1949 1950 static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx, 1951 struct wlan_cm_connect_resp *resp) 1952 { 1953 } 1954 #endif 1955 1956 #ifdef WLAN_FEATURE_11BE_MLO 1957 static inline 1958 void cm_update_ml_partner_info(struct wlan_cm_connect_req *req, 1959 struct wlan_cm_vdev_connect_req *connect_req) 1960 { 1961 if (req->ml_parnter_info.num_partner_links) 1962 qdf_mem_copy(&connect_req->ml_parnter_info, 1963 &req->ml_parnter_info, 1964 sizeof(struct mlo_partner_info)); 1965 } 1966 #else 1967 static inline 1968 void cm_update_ml_partner_info(struct wlan_cm_connect_req *req, 1969 struct wlan_cm_vdev_connect_req *connect_req) 1970 { 1971 } 1972 #endif 1973 1974 static 1975 void cm_update_per_peer_key_mgmt_crypto_params(struct wlan_objmgr_vdev *vdev, 1976 struct security_info *neg_sec_info) 1977 { 1978 int32_t key_mgmt = 0; 1979 int32_t neg_akm = neg_sec_info->key_mgmt; 1980 1981 /* 1982 * As there can be multiple AKM present select the most secured AKM 1983 * present 1984 */ 1985 if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE)) 1986 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE); 1987 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) 1988 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY); 1989 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_SAE)) 1990 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE); 1991 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B)) 1992 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B); 1993 else if (QDF_HAS_PARAM(neg_akm, 1994 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192)) 1995 QDF_SET_PARAM(key_mgmt, 1996 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192); 1997 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256)) 1998 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256); 1999 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384)) 2000 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384); 2001 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256)) 2002 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256); 2003 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) 2004 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384); 2005 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OWE)) 2006 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE); 2007 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_DPP)) 2008 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_DPP); 2009 else if (QDF_HAS_PARAM(neg_akm, 2010 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) 2011 QDF_SET_PARAM(key_mgmt, 2012 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384); 2013 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK)) 2014 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK); 2015 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X)) 2016 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X); 2017 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK)) 2018 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK); 2019 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) 2020 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256); 2021 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) 2022 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256); 2023 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384)) 2024 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384); 2025 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384)) 2026 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384); 2027 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK)) 2028 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK); 2029 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT)) 2030 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT); 2031 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) 2032 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_CCKM); 2033 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OSEN)) 2034 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OSEN); 2035 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPS)) 2036 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPS); 2037 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) 2038 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X); 2039 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA)) 2040 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA); 2041 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPA_NONE)) 2042 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPA_NONE); 2043 else /* use original if no akm match */ 2044 key_mgmt = neg_akm; 2045 2046 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt); 2047 /* 2048 * Overwrite the key mgmt with single key_mgmt if multiple are present 2049 */ 2050 neg_sec_info->key_mgmt = key_mgmt; 2051 } 2052 2053 static 2054 void cm_update_per_peer_ucastcipher_crypto_params(struct wlan_objmgr_vdev *vdev, 2055 struct security_info *neg_sec_info) 2056 { 2057 int32_t ucastcipherset = 0; 2058 2059 /* 2060 * As there can be multiple ucastcipher present select the most secured 2061 * ucastcipher present. 2062 */ 2063 if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2064 WLAN_CRYPTO_CIPHER_AES_GCM_256)) 2065 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM_256); 2066 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2067 WLAN_CRYPTO_CIPHER_AES_CCM_256)) 2068 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM_256); 2069 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2070 WLAN_CRYPTO_CIPHER_AES_GCM)) 2071 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM); 2072 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2073 WLAN_CRYPTO_CIPHER_AES_CCM)) 2074 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM); 2075 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2076 WLAN_CRYPTO_CIPHER_TKIP)) 2077 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_TKIP); 2078 else 2079 ucastcipherset = neg_sec_info->ucastcipherset; 2080 2081 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER, 2082 ucastcipherset); 2083 /* 2084 * Overwrite the ucastcipher with single ucast cipher if multiple are 2085 * present 2086 */ 2087 neg_sec_info->ucastcipherset = ucastcipherset; 2088 } 2089 2090 static 2091 void cm_update_per_peer_crypto_params(struct wlan_objmgr_vdev *vdev, 2092 struct cm_connect_req *connect_req) 2093 { 2094 struct security_info *neg_sec_info; 2095 uint16_t rsn_caps; 2096 2097 /* Do only for WPA/WPA2/WPA3 */ 2098 if (!connect_req->req.crypto.wpa_versions) 2099 return; 2100 2101 /* 2102 * Some non PMF AP misbehave if in assoc req RSN IE contain PMF capable 2103 * bit set. Thus only if AP and self are capable, try PMF connection 2104 * else set PMF as 0. The PMF filtering is already taken care in 2105 * get scan results. 2106 */ 2107 neg_sec_info = &connect_req->cur_candidate->entry->neg_sec_info; 2108 rsn_caps = connect_req->req.crypto.rsn_caps; 2109 if (!(neg_sec_info->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED && 2110 rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) { 2111 rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_ENABLED; 2112 rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED; 2113 rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED; 2114 } 2115 2116 /* Update the new rsn caps */ 2117 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP, 2118 rsn_caps); 2119 2120 cm_update_per_peer_key_mgmt_crypto_params(vdev, neg_sec_info); 2121 cm_update_per_peer_ucastcipher_crypto_params(vdev, neg_sec_info); 2122 } 2123 2124 QDF_STATUS 2125 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 2126 { 2127 struct wlan_cm_vdev_connect_req req; 2128 struct cm_req *cm_req; 2129 QDF_STATUS status; 2130 struct security_info *neg_sec_info; 2131 uint8_t country_code[REG_ALPHA2_LEN + 1] = {0}; 2132 struct wlan_objmgr_psoc *psoc; 2133 2134 psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev)); 2135 2136 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 2137 if (!cm_req) 2138 return QDF_STATUS_E_FAILURE; 2139 2140 /* 2141 * As keymgmt and ucast cipher can be multiple. 2142 * Choose one keymgmt and one ucastcipherset based on higher security. 2143 */ 2144 cm_update_per_peer_crypto_params(cm_ctx->vdev, &cm_req->connect_req); 2145 2146 req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 2147 req.cm_id = *cm_id; 2148 req.force_rsne_override = cm_req->connect_req.req.force_rsne_override; 2149 req.is_wps_connection = cm_req->connect_req.req.is_wps_connection; 2150 req.is_osen_connection = cm_req->connect_req.req.is_osen_connection; 2151 req.assoc_ie = cm_req->connect_req.req.assoc_ie; 2152 req.scan_ie = cm_req->connect_req.req.scan_ie; 2153 req.bss = cm_req->connect_req.cur_candidate; 2154 cm_copy_fils_info(&req, cm_req); 2155 req.ht_caps = cm_req->connect_req.req.ht_caps; 2156 req.ht_caps_mask = cm_req->connect_req.req.ht_caps_mask; 2157 req.vht_caps = cm_req->connect_req.req.vht_caps; 2158 req.vht_caps_mask = cm_req->connect_req.req.vht_caps_mask; 2159 req.is_non_assoc_link = cm_req->connect_req.req.is_non_assoc_link; 2160 cm_update_ml_partner_info(&cm_req->connect_req.req, &req); 2161 2162 neg_sec_info = &cm_req->connect_req.cur_candidate->entry->neg_sec_info; 2163 if (util_scan_entry_is_hidden_ap(req.bss->entry) && 2164 QDF_HAS_PARAM(neg_sec_info->key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE)) { 2165 mlme_debug("OWE transition candidate has wildcard ssid"); 2166 req.owe_trans_ssid = cm_req->connect_req.req.ssid; 2167 } 2168 2169 wlan_reg_get_cc_and_src(psoc, country_code); 2170 mlme_nofl_info(CM_PREFIX_FMT "Connecting to " QDF_SSID_FMT " " QDF_MAC_ADDR_FMT " rssi: %d freq: %d akm 0x%x cipher: uc 0x%x mc 0x%x, wps %d osen %d force RSN %d CC: %c%c", 2171 CM_PREFIX_REF(req.vdev_id, req.cm_id), 2172 QDF_SSID_REF(cm_req->connect_req.req.ssid.length, 2173 cm_req->connect_req.req.ssid.ssid), 2174 QDF_MAC_ADDR_REF(req.bss->entry->bssid.bytes), 2175 req.bss->entry->rssi_raw, 2176 req.bss->entry->channel.chan_freq, 2177 neg_sec_info->key_mgmt, neg_sec_info->ucastcipherset, 2178 neg_sec_info->mcastcipherset, req.is_wps_connection, 2179 req.is_osen_connection, req.force_rsne_override, 2180 country_code[0], 2181 country_code[1]); 2182 2183 status = mlme_cm_connect_req(cm_ctx->vdev, &req); 2184 if (QDF_IS_STATUS_ERROR(status)) { 2185 mlme_err(CM_PREFIX_FMT "connect request failed", 2186 CM_PREFIX_REF(req.vdev_id, req.cm_id)); 2187 /* try delete bss peer if req fails */ 2188 mlme_cm_bss_peer_delete_req(cm_ctx->vdev); 2189 status = cm_send_connect_start_fail(cm_ctx, 2190 &cm_req->connect_req, 2191 CM_JOIN_FAILED); 2192 } 2193 2194 return status; 2195 } 2196 2197 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) 2198 static void cm_inform_bcn_probe_handler(struct cnx_mgr *cm_ctx, 2199 struct scan_cache_entry *bss, 2200 wlan_cm_id cm_id) 2201 { 2202 struct element_info *bcn_probe_rsp; 2203 int32_t rssi; 2204 qdf_freq_t freq; 2205 2206 bcn_probe_rsp = &bss->raw_frame; 2207 rssi = bss->rssi_raw; 2208 freq = util_scan_entry_channel_frequency(bss); 2209 2210 cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len, 2211 freq, rssi, cm_id); 2212 } 2213 2214 static void cm_update_partner_link_scan_db(struct cnx_mgr *cm_ctx, 2215 wlan_cm_id cm_id, 2216 qdf_list_t *candidate_list, 2217 struct scan_cache_entry *cur_bss) 2218 { 2219 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 2220 struct scan_cache_node *candidate; 2221 struct scan_cache_entry *bss; 2222 2223 qdf_list_peek_front(candidate_list, &cur_node); 2224 2225 while (cur_node) { 2226 qdf_list_peek_next(candidate_list, cur_node, &next_node); 2227 candidate = qdf_container_of(cur_node, struct scan_cache_node, 2228 node); 2229 bss = candidate->entry; 2230 /* 2231 * If BSS is ML and not current bss and BSS mld mac is same as 2232 * cur bss then inform it to scan cache to avoid scan cache 2233 * ageing out. 2234 */ 2235 if (!qdf_is_macaddr_equal(&bss->bssid, &cur_bss->bssid) && 2236 bss->ml_info.num_links && 2237 cur_bss->ml_info.num_links && 2238 qdf_is_macaddr_equal(&bss->ml_info.mld_mac_addr, 2239 &cur_bss->ml_info.mld_mac_addr)) { 2240 mlme_debug("Inform Partner bssid: " QDF_MAC_ADDR_FMT " to kernel", 2241 QDF_MAC_ADDR_REF(bss->bssid.bytes)); 2242 cm_inform_bcn_probe_handler(cm_ctx, bss, cm_id); 2243 } 2244 cur_node = next_node; 2245 next_node = NULL; 2246 } 2247 } 2248 #else 2249 static 2250 inline void cm_update_partner_link_scan_db(struct cnx_mgr *cm_ctx, 2251 wlan_cm_id cm_id, 2252 qdf_list_t *candidate_list, 2253 struct scan_cache_entry *cur_bss) 2254 { 2255 } 2256 #endif 2257 2258 /** 2259 * cm_update_scan_db_on_connect_success() - update scan db with beacon or 2260 * probe resp 2261 * @cm_ctx: connection manager context 2262 * @resp: connect resp 2263 * 2264 * update scan db, so that kernel and driver do not age out 2265 * the connected AP entry. 2266 * 2267 * Context: Can be called from any context and to be used only if connect 2268 * is successful and SM is in connected state. i.e. SM lock is hold. 2269 * 2270 * Return: void 2271 */ 2272 static void 2273 cm_update_scan_db_on_connect_success(struct cnx_mgr *cm_ctx, 2274 struct wlan_cm_connect_resp *resp) 2275 { 2276 struct element_info *bcn_probe_rsp; 2277 struct cm_req *cm_req; 2278 int32_t rssi; 2279 struct scan_cache_node *cur_candidate; 2280 2281 if (!cm_is_vdev_connected(cm_ctx->vdev)) 2282 return; 2283 2284 cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id); 2285 if (!cm_req) 2286 return; 2287 /* if reassoc get from roam req else from connect req */ 2288 if (resp->is_reassoc) 2289 cur_candidate = cm_req->roam_req.cur_candidate; 2290 else 2291 cur_candidate = cm_req->connect_req.cur_candidate; 2292 2293 if (!cur_candidate) 2294 return; 2295 2296 /* 2297 * Get beacon or probe resp from connect response, and if not present 2298 * use cur candidate to get beacon or probe resp 2299 */ 2300 if (resp->connect_ies.bcn_probe_rsp.ptr) 2301 bcn_probe_rsp = &resp->connect_ies.bcn_probe_rsp; 2302 else 2303 bcn_probe_rsp = &cur_candidate->entry->raw_frame; 2304 2305 rssi = cur_candidate->entry->rssi_raw; 2306 2307 cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len, 2308 resp->freq, rssi, resp->cm_id); 2309 2310 /* 2311 * If vdev is an MLO vdev and not reassoc then use partner link info to 2312 * inform partner link scan entry to kernel. 2313 */ 2314 if (!resp->is_reassoc && wlan_vdev_mlme_is_mlo_vdev(cm_ctx->vdev)) 2315 cm_update_partner_link_scan_db(cm_ctx, resp->cm_id, 2316 cm_req->connect_req.candidate_list, 2317 cur_candidate->entry); 2318 } 2319 2320 #ifdef WLAN_FEATURE_11BE_MLO 2321 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 2322 static inline void 2323 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev) 2324 { 2325 wlan_vdev_mlme_clear_mlo_vdev(vdev); 2326 } 2327 #else /*WLAN_FEATURE_11BE_MLO_ADV_FEATURE*/ 2328 static inline void 2329 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev) 2330 { 2331 /* If the connect req fails on assoc link, reset 2332 * the MLO cap flags. The flags will be updated based 2333 * on next connect req 2334 */ 2335 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 2336 ucfg_mlo_mld_clear_mlo_cap(vdev); 2337 } 2338 #endif /*WLAN_FEATURE_11BE_MLO_ADV_FEATURE*/ 2339 #else /*WLAN_FEATURE_11BE_MLO*/ 2340 static inline void 2341 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev) 2342 { } 2343 #endif /*WLAN_FEATURE_11BE_MLO*/ 2344 2345 /** 2346 * cm_is_connect_id_reassoc_in_non_connected() 2347 * @cm_ctx: connection manager context 2348 * @cm_id: cm id 2349 * 2350 * If connect req is a reassoc req and received in not connected state. 2351 * Caller should take cm_ctx lock. 2352 * 2353 * Return: bool 2354 */ 2355 static bool cm_is_connect_id_reassoc_in_non_connected(struct cnx_mgr *cm_ctx, 2356 wlan_cm_id cm_id) 2357 { 2358 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 2359 struct cm_req *cm_req; 2360 uint32_t prefix = CM_ID_GET_PREFIX(cm_id); 2361 bool is_reassoc = false; 2362 2363 if (prefix != CONNECT_REQ_PREFIX) 2364 return is_reassoc; 2365 2366 qdf_list_peek_front(&cm_ctx->req_list, &cur_node); 2367 while (cur_node) { 2368 qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node); 2369 cm_req = qdf_container_of(cur_node, struct cm_req, node); 2370 2371 if (cm_req->cm_id == cm_id) { 2372 if (cm_req->connect_req.req.reassoc_in_non_connected) 2373 is_reassoc = true; 2374 return is_reassoc; 2375 } 2376 2377 cur_node = next_node; 2378 next_node = NULL; 2379 } 2380 2381 return is_reassoc; 2382 } 2383 2384 QDF_STATUS cm_notify_connect_complete(struct cnx_mgr *cm_ctx, 2385 struct wlan_cm_connect_resp *resp, 2386 bool acquire_lock) 2387 { 2388 enum wlan_cm_sm_state sm_state; 2389 2390 sm_state = cm_get_state(cm_ctx); 2391 2392 mlme_cm_connect_complete_ind(cm_ctx->vdev, resp); 2393 mlo_sta_link_connect_notify(cm_ctx->vdev, resp); 2394 /* 2395 * If connect req was a reassoc req and was received in not connected 2396 * state send disconnect instead of connect resp to kernel to cleanup 2397 * kernel flags 2398 */ 2399 if (QDF_IS_STATUS_ERROR(resp->connect_status) && 2400 sm_state == WLAN_CM_S_INIT) { 2401 if (acquire_lock) 2402 cm_req_lock_acquire(cm_ctx); 2403 if (cm_is_connect_id_reassoc_in_non_connected(cm_ctx, 2404 resp->cm_id)) { 2405 resp->send_disconnect = true; 2406 mlme_debug(CM_PREFIX_FMT "Set send disconnect to true to indicate disconnect instead of connect resp", 2407 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 2408 resp->cm_id)); 2409 } 2410 if (acquire_lock) 2411 cm_req_lock_release(cm_ctx); 2412 } 2413 mlme_cm_osif_connect_complete(cm_ctx->vdev, resp); 2414 cm_if_mgr_inform_connect_complete(cm_ctx->vdev, 2415 resp->connect_status); 2416 cm_inform_dlm_connect_complete(cm_ctx->vdev, resp); 2417 2418 if (QDF_IS_STATUS_ERROR(resp->connect_status) && 2419 sm_state == WLAN_CM_S_INIT) 2420 cm_clear_vdev_mlo_cap(cm_ctx->vdev); 2421 2422 return QDF_STATUS_SUCCESS; 2423 } 2424 2425 QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx, 2426 struct wlan_cm_connect_resp *resp) 2427 { 2428 enum wlan_cm_sm_state sm_state; 2429 struct bss_info bss_info; 2430 struct mlme_info mlme_info; 2431 bool send_ind = true; 2432 2433 /* 2434 * If the entry is not present in the list, it must have been cleared 2435 * already. 2436 */ 2437 if (!cm_get_req_by_cm_id(cm_ctx, resp->cm_id)) 2438 return QDF_STATUS_SUCCESS; 2439 2440 sm_state = cm_get_state(cm_ctx); 2441 cm_set_fils_connection(cm_ctx, resp); 2442 if (QDF_IS_STATUS_SUCCESS(resp->connect_status) && 2443 sm_state == WLAN_CM_S_CONNECTED) { 2444 cm_update_scan_db_on_connect_success(cm_ctx, resp); 2445 /* set WEP and FILS key on success */ 2446 cm_set_fils_wep_key(cm_ctx, resp); 2447 } 2448 2449 /* In case of reassoc failure no need to inform osif/legacy/ifmanager */ 2450 if (resp->is_reassoc && QDF_IS_STATUS_ERROR(resp->connect_status)) 2451 send_ind = false; 2452 2453 if (send_ind) 2454 cm_notify_connect_complete(cm_ctx, resp, 1); 2455 2456 /* Update scan entry in case connect is success or fails with bssid */ 2457 if (!qdf_is_macaddr_zero(&resp->bssid)) { 2458 if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) 2459 mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_ASSOC; 2460 else 2461 mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_NONE; 2462 qdf_copy_macaddr(&bss_info.bssid, &resp->bssid); 2463 bss_info.freq = resp->freq; 2464 bss_info.ssid.length = resp->ssid.length; 2465 qdf_mem_copy(&bss_info.ssid.ssid, resp->ssid.ssid, 2466 bss_info.ssid.length); 2467 wlan_scan_update_mlme_by_bssinfo( 2468 wlan_vdev_get_pdev(cm_ctx->vdev), 2469 &bss_info, &mlme_info); 2470 } 2471 2472 mlme_debug(CM_PREFIX_FMT, 2473 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 2474 resp->cm_id)); 2475 cm_remove_cmd(cm_ctx, &resp->cm_id); 2476 2477 return QDF_STATUS_SUCCESS; 2478 } 2479 2480 QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx, 2481 struct cm_connect_req *req) 2482 { 2483 QDF_STATUS status; 2484 struct cm_req *cm_req; 2485 2486 cm_req = qdf_container_of(req, struct cm_req, connect_req); 2487 req->cm_id = cm_get_cm_id(cm_ctx, req->req.source); 2488 cm_req->cm_id = req->cm_id; 2489 status = cm_add_req_to_list_and_indicate_osif(cm_ctx, cm_req, 2490 req->req.source); 2491 2492 return status; 2493 } 2494 2495 QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev, 2496 struct wlan_cm_connect_resp *resp) 2497 { 2498 struct cnx_mgr *cm_ctx; 2499 QDF_STATUS qdf_status; 2500 wlan_cm_id cm_id; 2501 uint32_t prefix; 2502 2503 cm_ctx = cm_get_cm_ctx(vdev); 2504 if (!cm_ctx) 2505 return QDF_STATUS_E_INVAL; 2506 2507 cm_id = cm_ctx->active_cm_id; 2508 prefix = CM_ID_GET_PREFIX(cm_id); 2509 2510 if (prefix != CONNECT_REQ_PREFIX || cm_id != resp->cm_id) { 2511 mlme_err(CM_PREFIX_FMT " Active cm_id 0x%x is different", 2512 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id), 2513 cm_id); 2514 qdf_status = QDF_STATUS_E_FAILURE; 2515 goto post_err; 2516 } 2517 2518 if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) { 2519 /* 2520 * On successful connection to sae single pmk AP, 2521 * clear all the single pmk AP. 2522 */ 2523 if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id)) 2524 wlan_crypto_selective_clear_sae_single_pmk_entries(vdev, 2525 &resp->bssid); 2526 qdf_status = 2527 cm_sm_deliver_event(vdev, 2528 WLAN_CM_SM_EV_CONNECT_SUCCESS, 2529 sizeof(*resp), resp); 2530 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 2531 return qdf_status; 2532 /* 2533 * failure mean that the new connect/disconnect is received so 2534 * cleanup. 2535 */ 2536 goto post_err; 2537 } 2538 2539 /* 2540 * Delete the PMKID of the BSSID for which the assoc reject is 2541 * received from the AP due to invalid PMKID reason. 2542 * This will avoid the driver trying to connect to same AP with 2543 * the same stale PMKID. when connection is tried again with this AP. 2544 */ 2545 if (resp->status_code == STATUS_INVALID_PMKID) 2546 cm_delete_pmksa_for_bssid(cm_ctx, &resp->bssid); 2547 2548 /* In case of failure try with next candidate */ 2549 qdf_status = 2550 cm_sm_deliver_event(vdev, 2551 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 2552 sizeof(*resp), resp); 2553 2554 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 2555 return qdf_status; 2556 /* 2557 * If connection fails with Single PMK bssid, clear this pmk 2558 * entry in case of post failure. 2559 */ 2560 if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id)) 2561 cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, &resp->bssid); 2562 post_err: 2563 /* 2564 * If there is a event posting error it means the SM state is not in 2565 * JOIN ACTIVE (some new cmd has changed the state of SM), so just 2566 * complete the connect command. 2567 */ 2568 cm_connect_complete(cm_ctx, resp); 2569 2570 return qdf_status; 2571 } 2572 2573 QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev, 2574 QDF_STATUS status, 2575 struct qdf_mac_addr *peer_mac) 2576 { 2577 struct cnx_mgr *cm_ctx; 2578 QDF_STATUS qdf_status; 2579 wlan_cm_id cm_id; 2580 uint32_t prefix; 2581 struct wlan_cm_connect_resp *resp; 2582 2583 cm_ctx = cm_get_cm_ctx(vdev); 2584 if (!cm_ctx) 2585 return QDF_STATUS_E_INVAL; 2586 2587 cm_id = cm_ctx->active_cm_id; 2588 prefix = CM_ID_GET_PREFIX(cm_id); 2589 2590 if (prefix != CONNECT_REQ_PREFIX) { 2591 mlme_err(CM_PREFIX_FMT "active req is not connect req", 2592 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id)); 2593 mlme_cm_bss_peer_delete_req(vdev); 2594 return QDF_STATUS_E_INVAL; 2595 } 2596 2597 if (QDF_IS_STATUS_SUCCESS(status)) { 2598 qdf_status = 2599 cm_sm_deliver_event(vdev, 2600 WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS, 2601 sizeof(wlan_cm_id), &cm_id); 2602 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 2603 return qdf_status; 2604 2605 mlme_cm_bss_peer_delete_req(vdev); 2606 goto post_err; 2607 } 2608 2609 /* In case of failure try with next candidate */ 2610 resp = qdf_mem_malloc(sizeof(*resp)); 2611 if (!resp) { 2612 qdf_status = QDF_STATUS_E_NOMEM; 2613 goto post_err; 2614 } 2615 2616 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, 2617 CM_PEER_CREATE_FAILED); 2618 qdf_status = 2619 cm_sm_deliver_event(vdev, 2620 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 2621 sizeof(*resp), resp); 2622 qdf_mem_free(resp); 2623 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 2624 return qdf_status; 2625 2626 post_err: 2627 /* 2628 * If there is a event posting error it means the SM state is not in 2629 * JOIN ACTIVE (some new cmd has changed the state of SM), so just 2630 * complete the connect command. 2631 */ 2632 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 2633 return qdf_status; 2634 } 2635 2636 static void 2637 cm_copy_crypto_prarams(struct wlan_cm_connect_crypto_info *dst_params, 2638 struct wlan_crypto_params *src_params) 2639 { 2640 /* 2641 * As akm suites and ucast ciphers can be multiple. So, do ORing to 2642 * keep it along with newly added one's (newly added one will anyway 2643 * be part of it) 2644 */ 2645 dst_params->akm_suites |= src_params->key_mgmt; 2646 dst_params->auth_type = src_params->authmodeset; 2647 dst_params->ciphers_pairwise |= src_params->ucastcipherset; 2648 dst_params->group_cipher = src_params->mcastcipherset; 2649 dst_params->mgmt_ciphers = src_params->mgmtcipherset; 2650 dst_params->rsn_caps = src_params->rsn_caps; 2651 } 2652 2653 static void 2654 cm_set_crypto_params_from_ie(struct wlan_cm_connect_req *req) 2655 { 2656 struct wlan_crypto_params crypto_params; 2657 QDF_STATUS status; 2658 uint8_t wsc_oui[OUI_LENGTH]; 2659 uint8_t osen_oui[OUI_LENGTH]; 2660 uint32_t oui_cpu; 2661 2662 if (!req->assoc_ie.ptr) 2663 return; 2664 2665 oui_cpu = qdf_be32_to_cpu(WSC_OUI); 2666 qdf_mem_copy(wsc_oui, &oui_cpu, OUI_LENGTH); 2667 oui_cpu = qdf_be32_to_cpu(OSEN_OUI); 2668 qdf_mem_copy(osen_oui, &oui_cpu, OUI_LENGTH); 2669 if (wlan_get_vendor_ie_ptr_from_oui(osen_oui, OUI_LENGTH, 2670 req->assoc_ie.ptr, 2671 req->assoc_ie.len)) 2672 req->is_osen_connection = true; 2673 2674 if (wlan_get_vendor_ie_ptr_from_oui(wsc_oui, OUI_LENGTH, 2675 req->assoc_ie.ptr, 2676 req->assoc_ie.len)) 2677 req->is_wps_connection = true; 2678 2679 status = wlan_get_crypto_params_from_rsn_ie(&crypto_params, 2680 req->assoc_ie.ptr, 2681 req->assoc_ie.len); 2682 if (QDF_IS_STATUS_SUCCESS(status)) { 2683 cm_copy_crypto_prarams(&req->crypto, &crypto_params); 2684 return; 2685 } 2686 2687 status = wlan_get_crypto_params_from_wpa_ie(&crypto_params, 2688 req->assoc_ie.ptr, 2689 req->assoc_ie.len); 2690 if (QDF_IS_STATUS_SUCCESS(status)) { 2691 cm_copy_crypto_prarams(&req->crypto, &crypto_params); 2692 return; 2693 } 2694 2695 status = wlan_get_crypto_params_from_wapi_ie(&crypto_params, 2696 req->assoc_ie.ptr, 2697 req->assoc_ie.len); 2698 if (QDF_IS_STATUS_SUCCESS(status)) 2699 cm_copy_crypto_prarams(&req->crypto, &crypto_params); 2700 } 2701 2702 static QDF_STATUS 2703 cm_allocate_and_copy_ies_and_keys(struct wlan_cm_connect_req *target, 2704 struct wlan_cm_connect_req *source) 2705 { 2706 /* Reset the copied pointers of target */ 2707 target->assoc_ie.ptr = NULL; 2708 target->crypto.wep_keys.key = NULL; 2709 target->crypto.wep_keys.seq = NULL; 2710 target->scan_ie.ptr = NULL; 2711 2712 if (source->scan_ie.ptr) { 2713 target->scan_ie.ptr = qdf_mem_malloc(source->scan_ie.len); 2714 if (!target->scan_ie.ptr) 2715 target->scan_ie.len = 0; 2716 else 2717 qdf_mem_copy(target->scan_ie.ptr, 2718 source->scan_ie.ptr, source->scan_ie.len); 2719 } 2720 2721 if (source->assoc_ie.ptr) { 2722 target->assoc_ie.ptr = qdf_mem_malloc(source->assoc_ie.len); 2723 if (!target->assoc_ie.ptr) 2724 return QDF_STATUS_E_NOMEM; 2725 2726 qdf_mem_copy(target->assoc_ie.ptr, source->assoc_ie.ptr, 2727 source->assoc_ie.len); 2728 } 2729 2730 if (source->crypto.wep_keys.key) { 2731 target->crypto.wep_keys.key = 2732 qdf_mem_malloc(source->crypto.wep_keys.key_len); 2733 if (!target->crypto.wep_keys.key) 2734 return QDF_STATUS_E_NOMEM; 2735 2736 qdf_mem_copy(target->crypto.wep_keys.key, 2737 source->crypto.wep_keys.key, 2738 source->crypto.wep_keys.key_len); 2739 } 2740 2741 if (source->crypto.wep_keys.seq) { 2742 target->crypto.wep_keys.seq = 2743 qdf_mem_malloc(source->crypto.wep_keys.seq_len); 2744 if (!target->crypto.wep_keys.seq) 2745 return QDF_STATUS_E_NOMEM; 2746 2747 qdf_mem_copy(target->crypto.wep_keys.seq, 2748 source->crypto.wep_keys.seq, 2749 source->crypto.wep_keys.seq_len); 2750 } 2751 2752 return QDF_STATUS_SUCCESS; 2753 } 2754 2755 QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, 2756 struct wlan_cm_connect_req *req) 2757 { 2758 struct cnx_mgr *cm_ctx; 2759 struct cm_req *cm_req; 2760 struct cm_connect_req *connect_req; 2761 QDF_STATUS status; 2762 2763 cm_ctx = cm_get_cm_ctx(vdev); 2764 if (!cm_ctx) 2765 return QDF_STATUS_E_INVAL; 2766 2767 cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev), cm_ctx->vdev); 2768 2769 /* 2770 * This would be freed as part of removal from cm req list if adding 2771 * to list is success after posting WLAN_CM_SM_EV_CONNECT_REQ. 2772 */ 2773 cm_req = qdf_mem_malloc(sizeof(*cm_req)); 2774 if (!cm_req) 2775 return QDF_STATUS_E_NOMEM; 2776 2777 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 2778 wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 2779 req->is_non_assoc_link = 1; 2780 2781 connect_req = &cm_req->connect_req; 2782 connect_req->req = *req; 2783 2784 status = cm_allocate_and_copy_ies_and_keys(&connect_req->req, req); 2785 if (QDF_IS_STATUS_ERROR(status)) 2786 goto err; 2787 2788 cm_set_crypto_params_from_ie(&connect_req->req); 2789 2790 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 2791 cm_teardown_tdls(vdev); 2792 2793 status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_CONNECT_REQ, 2794 sizeof(*connect_req), connect_req); 2795 2796 err: 2797 /* free the req if connect is not handled */ 2798 if (QDF_IS_STATUS_ERROR(status)) { 2799 cm_free_connect_req_mem(connect_req); 2800 qdf_mem_free(cm_req); 2801 } 2802 2803 return status; 2804 } 2805