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