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