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