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