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