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