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