1 /* 2 * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: osif_cm_connect_rsp.c 19 * 20 * This file maintains definitaions of connect response apis. 21 */ 22 23 #include <linux/version.h> 24 #include <linux/nl80211.h> 25 #include <net/cfg80211.h> 26 #include "wlan_osif_priv.h" 27 #include "osif_cm_rsp.h" 28 #include "osif_cm_util.h" 29 #include "wlan_cfg80211.h" 30 #include "wlan_cfg80211_scan.h" 31 #include "wlan_mlo_mgr_sta.h" 32 33 #ifdef CONN_MGR_ADV_FEATURE 34 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 35 size_t *ie_data_len, 36 const uint8_t **ie_data_ptr) 37 { 38 /* Validate IE and length */ 39 if (!assoc_req->len || !assoc_req->ptr || 40 assoc_req->len <= WLAN_ASSOC_REQ_IES_OFFSET) 41 return; 42 43 *ie_data_len = assoc_req->len - WLAN_ASSOC_REQ_IES_OFFSET; 44 *ie_data_ptr = assoc_req->ptr + WLAN_ASSOC_REQ_IES_OFFSET; 45 } 46 #else 47 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 48 size_t *ie_data_len, 49 const uint8_t **ie_data_ptr) 50 { 51 /* Validate IE and length */ 52 if (!assoc_req->len || !assoc_req->ptr) 53 return; 54 55 *ie_data_len = assoc_req->len; 56 *ie_data_ptr = assoc_req->ptr; 57 } 58 #endif 59 60 void osif_cm_get_assoc_rsp_ie_data(struct element_info *assoc_rsp, 61 size_t *ie_data_len, 62 const uint8_t **ie_data_ptr) 63 { 64 /* Validate IE and length */ 65 if (!assoc_rsp->len || !assoc_rsp->ptr || 66 assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) 67 return; 68 69 *ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET; 70 *ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET; 71 } 72 73 /** 74 * osif_validate_connect_and_reset_src_id() - Validate connect response and 75 * resets source and id 76 * @osif_priv: Pointer to vdev osif priv 77 * @rsp: Connection manager connect response 78 * 79 * This function validates connect response and if the connect 80 * response is valid, resets the source and id of the command 81 * 82 * Context: Any context. Takes and releases cmd id spinlock. 83 * Return: QDF_STATUS 84 */ 85 static QDF_STATUS 86 osif_validate_connect_and_reset_src_id(struct vdev_osif_priv *osif_priv, 87 struct wlan_cm_connect_resp *rsp) 88 { 89 QDF_STATUS status = QDF_STATUS_SUCCESS; 90 91 /* 92 * Do not send to kernel if last osif cookie doesnt match or 93 * or source is CM_OSIF_CFG_CONNECT with success status. 94 * If cookie matches reset the cookie and source. 95 */ 96 qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock); 97 if (rsp->cm_id != osif_priv->cm_info.last_id || 98 (osif_priv->cm_info.last_source == CM_OSIF_CFG_CONNECT && 99 QDF_IS_STATUS_SUCCESS(rsp->connect_status))) { 100 osif_debug("Ignore as cm_id(0x%x)/src(%d) != cm_id(0x%x)/src(%d) OR source is CFG connect with status %d", 101 rsp->cm_id, CM_OSIF_CONNECT, 102 osif_priv->cm_info.last_id, 103 osif_priv->cm_info.last_source, 104 rsp->connect_status); 105 status = QDF_STATUS_E_INVAL; 106 goto rel_lock; 107 } 108 109 osif_cm_reset_id_and_src_no_lock(osif_priv); 110 rel_lock: 111 qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock); 112 113 return status; 114 } 115 116 static enum ieee80211_statuscode 117 osif_get_statuscode(enum wlan_status_code status) 118 { 119 return (enum ieee80211_statuscode)status; 120 } 121 122 static enum ieee80211_statuscode 123 osif_get_connect_status_code(struct wlan_cm_connect_resp *rsp) 124 { 125 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 126 127 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) { 128 if (rsp->status_code) 129 status = osif_get_statuscode(rsp->status_code); 130 else 131 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 132 } 133 134 return status; 135 } 136 137 /** 138 * osif_convert_timeout_reason() - Convert to kernel specific enum 139 * @timeout_reason: reason for connect timeout 140 * 141 * This function is used to convert host timeout 142 * reason enum to kernel specific enum. 143 * 144 * Context: Any context. 145 * Return: nl timeout enum 146 */ 147 148 static enum nl80211_timeout_reason 149 osif_convert_timeout_reason(enum wlan_cm_connect_fail_reason reason) 150 { 151 switch (reason) { 152 case CM_JOIN_TIMEOUT: 153 return NL80211_TIMEOUT_SCAN; 154 case CM_AUTH_TIMEOUT: 155 return NL80211_TIMEOUT_AUTH; 156 case CM_ASSOC_TIMEOUT: 157 return NL80211_TIMEOUT_ASSOC; 158 default: 159 return NL80211_TIMEOUT_UNSPECIFIED; 160 } 161 } 162 163 #if defined CFG80211_CONNECT_BSS || \ 164 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) 165 166 #if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \ 167 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) 168 /** 169 * osif_connect_timeout() - API to send connection timeout reason 170 * @dev: network device 171 * @bssid: bssid to which we want to associate 172 * @reason: reason for connect timeout 173 * 174 * This API is used to send connection timeout reason to supplicant 175 * 176 * Context: Any context. 177 * Return: Void 178 */ 179 static void 180 osif_connect_timeout(struct net_device *dev, const u8 *bssid, 181 enum wlan_cm_connect_fail_reason reason) 182 { 183 enum nl80211_timeout_reason nl_timeout_reason; 184 185 nl_timeout_reason = osif_convert_timeout_reason(reason); 186 187 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 188 189 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags(), 190 nl_timeout_reason); 191 } 192 193 /** 194 * __osif_connect_bss() - API to send connection status to supplicant 195 * @dev: network device 196 * @bss: bss info 197 * @connect_rsp: Connection manager connect response 198 * 199 * Context: Any context. 200 * Return: void 201 */ 202 static void __osif_connect_bss(struct net_device *dev, 203 struct cfg80211_bss *bss, 204 struct wlan_cm_connect_resp *rsp, 205 enum ieee80211_statuscode status) 206 { 207 enum nl80211_timeout_reason nl_timeout_reason; 208 size_t req_len = 0; 209 const uint8_t *req_ptr = NULL; 210 size_t rsp_len = 0; 211 const uint8_t *rsp_ptr = NULL; 212 213 nl_timeout_reason = osif_convert_timeout_reason(rsp->reason); 214 215 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 216 217 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 218 &req_len, &req_ptr); 219 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 220 &rsp_len, &rsp_ptr); 221 222 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 223 req_ptr, req_len, rsp_ptr, rsp_len, status, 224 qdf_mem_malloc_flags(), nl_timeout_reason); 225 } 226 #else /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 227 228 #if defined CFG80211_CONNECT_TIMEOUT || \ 229 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 230 static void osif_connect_timeout( 231 struct net_device *dev, 232 const u8 *bssid, 233 enum wlan_cm_connect_fail_reason reason) 234 { 235 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags()); 236 } 237 #endif 238 239 static void __osif_connect_bss(struct net_device *dev, 240 struct cfg80211_bss *bss, 241 struct wlan_cm_connect_resp *rsp, 242 ieee80211_statuscode status) 243 { 244 size_t req_len = 0; 245 const uint8_t *req_ptr = NULL; 246 size_t rsp_len = 0; 247 const uint8_t *rsp_ptr = NULL; 248 249 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 250 &req_len, &req_ptr); 251 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 252 &rsp_len, &rsp_ptr); 253 254 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 255 req_ptr, req_len, rsp_ptr, rsp_len, 256 status, qdf_mem_malloc_flags()); 257 } 258 #endif /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 259 260 /** 261 * osif_connect_bss() - API to send connection status to supplicant 262 * @dev: network device 263 * @bss: bss info 264 * @connect_rsp: Connection manager connect response 265 * 266 * The API is a wrapper to send connection status to supplicant 267 * 268 * Context: Any context. 269 * Return: Void 270 */ 271 #if defined CFG80211_CONNECT_TIMEOUT || \ 272 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 273 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 274 struct wlan_cm_connect_resp *rsp) 275 { 276 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 277 278 osif_enter_dev(dev); 279 280 if (rsp->reason == CM_JOIN_TIMEOUT || 281 rsp->reason == CM_AUTH_TIMEOUT || 282 rsp->reason == CM_ASSOC_TIMEOUT) { 283 osif_connect_timeout(dev, rsp->bssid.bytes, 284 rsp->reason); 285 } else { 286 status = osif_get_connect_status_code(rsp); 287 288 __osif_connect_bss(dev, bss, rsp, status); 289 } 290 } 291 #else /* CFG80211_CONNECT_TIMEOUT */ 292 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 293 struct wlan_cm_connect_resp *rsp) 294 { 295 enum ieee80211_statuscode status; 296 297 osif_enter_dev(dev); 298 299 status = osif_get_connect_status_code(rsp); 300 __osif_connect_bss(dev, bss, rsp, status); 301 } 302 #endif /* CFG80211_CONNECT_TIMEOUT */ 303 304 #if defined(WLAN_FEATURE_FILS_SK) 305 306 #if (defined(CFG80211_CONNECT_DONE) || \ 307 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))) && \ 308 (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) 309 310 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \ 311 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) 312 /** 313 * osif_populate_fils_params() - Populate FILS keys to connect response 314 * @conn_rsp_params: connect response to supplicant 315 * @fils_ie: Fils ie information from connection manager 316 * 317 * Context: Any context. 318 * Return: None 319 */ 320 static void 321 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 322 struct fils_connect_rsp_params *fils_ie) 323 { 324 /* Increment seq number to be used for next FILS */ 325 rsp_params->fils_erp_next_seq_num = fils_ie->fils_seq_num + 1; 326 rsp_params->update_erp_next_seq_num = true; 327 rsp_params->fils_kek = fils_ie->kek; 328 rsp_params->fils_kek_len = fils_ie->kek_len; 329 rsp_params->pmk = fils_ie->fils_pmk; 330 rsp_params->pmk_len = fils_ie->fils_pmk_len; 331 rsp_params->pmkid = fils_ie->fils_pmkid; 332 osif_debug("erp_next_seq_num:%d", rsp_params->fils_erp_next_seq_num); 333 } 334 #else /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 335 static inline void 336 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 337 struct fils_connect_rsp_params *fils_ie) 338 339 { } 340 #endif /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 341 342 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 343 /** 344 * osif_populate_fils_params() - Populate FILS keys to connect response 345 * @conn_rsp_params: connect response to supplicant 346 * @fils_ie: Fils ie information from connection manager 347 * 348 * Context: Any context. 349 * Return: None 350 */ 351 static void 352 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 353 struct fils_connect_rsp_params *fils_ie) 354 355 { 356 /* Increament seq number to be used for next FILS */ 357 rsp_params->fils.erp_next_seq_num = fils_ie->fils_seq_num + 1; 358 rsp_params->fils.update_erp_next_seq_num = true; 359 rsp_params->fils.kek = fils_ie->kek; 360 rsp_params->fils.kek_len = fils_ie->kek_len; 361 rsp_params->fils.pmk = fils_ie->fils_pmk; 362 rsp_params->fils.pmk_len = fils_ie->fils_pmk_len; 363 rsp_params->fils.pmkid = fils_ie->fils_pmkid; 364 osif_debug("erp_next_seq_num:%d", rsp_params->fils.erp_next_seq_num); 365 } 366 #endif /* CFG80211_CONNECT_DONE */ 367 368 #if defined(CFG80211_CONNECT_DONE) || \ 369 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) 370 371 /** 372 * osif_connect_done() - Wrapper API to call cfg80211_connect_done 373 * @dev: network device 374 * @bss: bss info 375 * @connect_rsp: Connection manager connect response 376 * @vdev: pointer to vdev 377 * 378 * This API is used as wrapper to send FILS key/sequence number 379 * params etc. to supplicant in case of FILS connection 380 * 381 * Context: Any context. 382 * Return: None 383 */ 384 static void osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 385 struct wlan_cm_connect_resp *rsp, 386 struct wlan_objmgr_vdev *vdev) 387 { 388 struct cfg80211_connect_resp_params conn_rsp_params; 389 enum ieee80211_statuscode status; 390 391 osif_enter_dev(dev); 392 393 status = osif_get_connect_status_code(rsp); 394 qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params)); 395 396 if (!rsp->connect_ies.fils_ie) { 397 conn_rsp_params.status = WLAN_STATUS_UNSPECIFIED_FAILURE; 398 } else { 399 conn_rsp_params.status = status; 400 conn_rsp_params.bssid = rsp->bssid.bytes; 401 conn_rsp_params.timeout_reason = 402 osif_convert_timeout_reason(rsp->reason); 403 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 404 &conn_rsp_params.req_ie_len, 405 &conn_rsp_params.req_ie); 406 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 407 &conn_rsp_params.resp_ie_len, 408 &conn_rsp_params.resp_ie); 409 conn_rsp_params.bss = bss; 410 osif_populate_fils_params(&conn_rsp_params, 411 rsp->connect_ies.fils_ie); 412 osif_cm_save_gtk(vdev, rsp); 413 } 414 415 osif_debug("Connect resp status %d", conn_rsp_params.status); 416 cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags()); 417 if (rsp->connect_ies.fils_ie && rsp->connect_ies.fils_ie->hlp_data_len) 418 osif_cm_set_hlp_data(dev, vdev, rsp); 419 } 420 #else /* CFG80211_CONNECT_DONE */ 421 static inline void 422 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 423 struct wlan_cm_connect_resp *rsp, 424 struct wlan_objmgr_vdev *vdev) 425 { } 426 #endif /* CFG80211_CONNECT_DONE */ 427 #endif /* WLAN_FEATURE_FILS_SK */ 428 429 #if defined(WLAN_FEATURE_FILS_SK) && \ 430 (defined(CFG80211_CONNECT_DONE) || \ 431 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))) 432 /** 433 * osif_fils_update_connect_results() - API to send fils connection status to 434 * supplicant. 435 * @dev: network device 436 * @bss: bss info 437 * @connect_rsp: Connection manager connect response 438 * @vdev: pointer to vdev 439 * 440 * The API is a wrapper to send connection status to supplicant 441 * 442 * Context: Any context. 443 * Return: 0 if success else failure 444 */ 445 static int osif_update_connect_results(struct net_device *dev, 446 struct cfg80211_bss *bss, 447 struct wlan_cm_connect_resp *rsp, 448 struct wlan_objmgr_vdev *vdev) 449 { 450 if (!rsp->is_fils_connection) { 451 osif_debug("fils IE is NULL"); 452 return -EINVAL; 453 } 454 osif_connect_done(dev, bss, rsp, vdev); 455 456 return 0; 457 } 458 #else /* WLAN_FEATURE_FILS_SK && CFG80211_CONNECT_DONE */ 459 460 static inline int osif_update_connect_results(struct net_device *dev, 461 struct cfg80211_bss *bss, 462 struct wlan_cm_connect_resp *rsp, 463 struct wlan_objmgr_vdev *vdev) 464 { 465 return -EINVAL; 466 } 467 #endif /* WLAN_FEATURE_FILS_SK && CFG80211_CONNECT_DONE */ 468 469 #ifdef WLAN_FEATURE_11BE_MLO 470 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 471 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 472 struct vdev_osif_priv *osif_priv, 473 struct wlan_cm_connect_resp *rsp) 474 { 475 struct cfg80211_bss *bss = NULL; 476 struct ieee80211_channel *chan; 477 478 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 479 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 480 rsp->freq); 481 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 482 rsp->bssid.bytes, 483 rsp->ssid.ssid, 484 rsp->ssid.length); 485 } 486 487 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 488 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 489 rsp, vdev)) 490 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 491 return; 492 } 493 494 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { 495 if (osif_update_connect_results( 496 osif_priv->wdev->netdev, bss, 497 rsp, vdev)) 498 osif_connect_bss(osif_priv->wdev->netdev, 499 bss, rsp); 500 } 501 502 } 503 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 504 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 505 struct vdev_osif_priv *osif_priv, 506 struct wlan_cm_connect_resp *rsp) 507 { 508 struct cfg80211_bss *bss = NULL; 509 struct ieee80211_channel *chan; 510 struct wlan_objmgr_vdev *assoc_vdev = NULL; 511 struct vdev_osif_priv *tmp_osif_priv = NULL; 512 qdf_freq_t freq; 513 struct qdf_mac_addr macaddr = {0}; 514 struct wlan_cm_connect_resp resp = {0}; 515 516 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 517 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 518 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 519 rsp->freq); 520 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, 521 chan, 522 rsp->bssid.bytes, 523 rsp->ssid.ssid, 524 rsp->ssid.length); 525 } 526 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 527 rsp, vdev)) 528 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 529 return; 530 } 531 532 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 533 ucfg_mlo_is_mld_connected(vdev)) || 534 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 535 ucfg_mlo_is_mld_disconnected(vdev))) { 536 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 537 if (!assoc_vdev) 538 return; 539 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 540 freq = vdev->vdev_mlme.bss_chan->ch_freq; 541 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 542 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 543 chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy, 544 freq); 545 bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy, 546 chan, 547 macaddr.bytes, 548 rsp->ssid.ssid, 549 rsp->ssid.length); 550 } 551 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, 552 QDF_MAC_ADDR_SIZE); 553 qdf_mem_copy(resp.ssid.ssid, rsp->ssid.ssid, 554 rsp->ssid.length); 555 resp.ssid.length = rsp->ssid.length; 556 resp.freq = freq; 557 resp.connect_status = rsp->connect_status; 558 resp.reason = rsp->reason; 559 resp.status_code = rsp->status_code; 560 resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr; 561 resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len; 562 resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr; 563 resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len; 564 if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss, 565 &resp, vdev)) 566 osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp); 567 } 568 } 569 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 570 #else /* WLAN_FEATURE_11BE_MLO */ 571 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 572 struct vdev_osif_priv *osif_priv, 573 struct wlan_cm_connect_resp *rsp) 574 { 575 struct cfg80211_bss *bss = NULL; 576 struct ieee80211_channel *chan; 577 578 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 579 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 580 rsp->freq); 581 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 582 rsp->bssid.bytes, 583 rsp->ssid.ssid, 584 rsp->ssid.length); 585 } 586 587 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 588 rsp, vdev)) 589 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 590 } 591 #endif /* WLAN_FEATURE_11BE_MLO */ 592 #else /* CFG80211_CONNECT_BSS */ 593 #ifdef WLAN_FEATURE_11BE_MLO 594 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 595 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 596 struct vdev_osif_priv *osif_priv, 597 struct wlan_cm_connect_resp *rsp) 598 { 599 enum ieee80211_statuscode status; 600 size_t req_len = 0; 601 const uint8_t *req_ptr = NULL; 602 size_t rsp_len = 0; 603 const uint8_t *rsp_ptr = NULL; 604 struct wlan_objmgr_vdev *assoc_vdev = NULL; 605 struct vdev_osif_priv *tmp_osif_priv = NULL; 606 607 status = osif_get_connect_status_code(rsp); 608 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 609 &req_len, &req_ptr); 610 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 611 &rsp_len, &rsp_ptr); 612 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 613 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 614 cfg80211_connect_result( 615 osif_priv->wdev->netdev, 616 rsp->bssid.bytes, req_ptr, req_len, 617 rsp_ptr, rsp_len, status, 618 qdf_mem_malloc_flags()); 619 } else { 620 cfg80211_connect_result(osif_priv->wdev->netdev, 621 rsp->bssid.bytes, req_ptr, req_len, 622 rsp_ptr, rsp_len, status, 623 qdf_mem_malloc_flags()); 624 } 625 } 626 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 627 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 628 struct vdev_osif_priv *osif_priv, 629 struct wlan_cm_connect_resp *rsp) 630 { 631 enum ieee80211_statuscode status; 632 size_t req_len = 0; 633 const uint8_t *req_ptr = NULL; 634 size_t rsp_len = 0; 635 const uint8_t *rsp_ptr = NULL; 636 struct wlan_objmgr_vdev *assoc_vdev = NULL; 637 struct vdev_osif_priv *tmp_osif_priv = NULL; 638 struct qdf_mac_addr macaddr = {0}; 639 640 status = osif_get_connect_status_code(rsp); 641 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 642 &req_len, &req_ptr); 643 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 644 &rsp_len, &rsp_ptr); 645 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 646 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 647 ucfg_mlo_is_mld_connected(vdev)) || 648 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 649 ucfg_mlo_is_mld_disconnected(vdev))) { 650 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 651 if (!assoc_vdev) 652 return; 653 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 654 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 655 cfg80211_connect_result(tmp_osif_priv->wdev->netdev, 656 macaddr.bytes, req_ptr, 657 req_len, rsp_ptr, rsp_len, 658 status, qdf_mem_malloc_flags()); 659 } 660 } else { 661 cfg80211_connect_result(osif_priv->wdev->netdev, 662 rsp->bssid.bytes, req_ptr, req_len, 663 rsp_ptr, rsp_len, status, 664 qdf_mem_malloc_flags()); 665 } 666 } 667 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 668 #else /* WLAN_FEATURE_11BE_MLO */ 669 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 670 struct vdev_osif_priv *osif_priv, 671 struct wlan_cm_connect_resp *rsp) 672 { 673 enum ieee80211_statuscode status; 674 size_t req_len = 0; 675 const uint8_t *req_ptr = NULL; 676 size_t rsp_len = 0; 677 const uint8_t *rsp_ptr = NULL; 678 679 status = osif_get_connect_status_code(rsp); 680 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 681 &req_len, &req_ptr); 682 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 683 &rsp_len, &rsp_ptr); 684 cfg80211_connect_result(osif_priv->wdev->netdev, 685 rsp->bssid.bytes, req_ptr, req_len, 686 rsp_ptr, rsp_len, status, 687 qdf_mem_malloc_flags()); 688 } 689 #endif /* WLAN_FEATURE_11BE_MLO */ 690 #endif /* CFG80211_CONNECT_BSS */ 691 692 #ifdef CONN_MGR_ADV_FEATURE 693 static inline 694 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp) 695 { 696 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) 697 return false; 698 699 if (rsp->reason == CM_NO_CANDIDATE_FOUND || 700 rsp->reason == CM_JOIN_TIMEOUT || 701 rsp->reason == CM_AUTH_TIMEOUT || 702 rsp->reason == CM_ASSOC_TIMEOUT) 703 return true; 704 705 return false; 706 } 707 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 708 struct vdev_osif_priv *osif_priv, 709 struct wlan_cm_connect_resp *rsp) 710 { 711 if (osif_cm_is_unlink_bss_required(rsp)) 712 osif_cm_unlink_bss(vdev, osif_priv, &rsp->bssid, rsp->ssid.ssid, 713 rsp->ssid.length); 714 } 715 #else 716 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 717 struct vdev_osif_priv *osif_priv, 718 struct wlan_cm_connect_resp *rsp) 719 {} 720 #endif 721 722 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev, 723 struct wlan_cm_connect_resp *rsp) 724 { 725 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 726 QDF_STATUS status; 727 728 osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " Connect with " QDF_MAC_ADDR_FMT " SSID \"%.*s\" is %s cm_id 0x%x cm_reason %d status_code %d is_reassoc %d", 729 osif_priv->wdev->netdev->name, rsp->vdev_id, 730 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 731 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 732 rsp->ssid.length, rsp->ssid.ssid, 733 rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id, 734 rsp->reason, rsp->status_code, rsp->is_reassoc); 735 736 osif_check_and_unlink_bss(vdev, osif_priv, rsp); 737 738 status = osif_validate_connect_and_reset_src_id(osif_priv, rsp); 739 if (QDF_IS_STATUS_ERROR(status)) { 740 osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED); 741 return status; 742 } 743 744 osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE); 745 if (rsp->is_reassoc) 746 osif_indicate_reassoc_results(vdev, osif_priv, rsp); 747 else 748 osif_indcate_connect_results(vdev, osif_priv, rsp); 749 osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE); 750 751 return QDF_STATUS_SUCCESS; 752 } 753 754 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev, 755 struct wlan_cm_connect_resp *rsp) 756 { 757 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 758 759 osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " Connect with " QDF_MAC_ADDR_FMT " SSID \"%.*s\" FAILED cm_id 0x%x cm_reason %d reason_code %d", 760 osif_priv->wdev->netdev->name, rsp->vdev_id, 761 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 762 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 763 rsp->ssid.length, rsp->ssid.ssid, rsp->cm_id, 764 rsp->reason, rsp->status_code); 765 766 osif_check_and_unlink_bss(vdev, osif_priv, rsp); 767 768 return QDF_STATUS_SUCCESS; 769 } 770