1 /* 2 * Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 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: osif_cm_roam_rsp.c 20 * 21 * This file maintains definitaions of roam response apis. 22 */ 23 24 #include <linux/version.h> 25 #include <linux/nl80211.h> 26 #include <net/cfg80211.h> 27 #include <wlan_osif_priv.h> 28 #include "osif_cm_rsp.h" 29 #include <osif_cm_util.h> 30 #include <wlan_cfg80211.h> 31 #include <wlan_cfg80211_scan.h> 32 #include "wlan_mlo_mgr_sta.h" 33 #ifdef CONN_MGR_ADV_FEATURE 34 #include "wlan_mlme_ucfg_api.h" 35 #endif 36 #include "wlan_crypto_global_api.h" 37 38 #ifdef CONN_MGR_ADV_FEATURE 39 #ifdef WLAN_FEATURE_FILS_SK 40 static inline void osif_update_fils_hlp_data(struct net_device *dev, 41 struct wlan_objmgr_vdev *vdev, 42 struct wlan_cm_connect_resp *rsp) 43 { 44 if (rsp->connect_ies.fils_ie && rsp->connect_ies.fils_ie->hlp_data_len) 45 osif_cm_set_hlp_data(dev, vdev, rsp); 46 } 47 #else 48 static inline void osif_update_fils_hlp_data(struct net_device *dev, 49 struct wlan_objmgr_vdev *vdev, 50 struct wlan_cm_connect_resp *rsp) 51 { 52 } 53 #endif 54 55 /** 56 * osif_roamed_ind() - send roamed indication to cfg80211 57 * @dev: network device 58 * @bss: cfg80211 roamed bss pointer 59 * @req_ie: IEs used in reassociation request 60 * @req_ie_len: Length of the @req_ie 61 * @resp_ie: IEs received in successful reassociation response 62 * @resp_ie_len: Length of @resp_ie 63 * 64 * Return: none 65 */ 66 #if defined CFG80211_ROAMED_API_UNIFIED || \ 67 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) 68 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT 69 static 70 void osif_copy_roamed_info(struct cfg80211_roam_info *info, 71 struct cfg80211_bss *bss) 72 { 73 info->links[0].bss = bss; 74 } 75 #else 76 static 77 void osif_copy_roamed_info(struct cfg80211_roam_info *info, 78 struct cfg80211_bss *bss) 79 { 80 info->bss = bss; 81 } 82 #endif 83 84 #if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 85 static 86 void osif_populate_mlo_info_for_link(struct wlan_objmgr_vdev *vdev, 87 struct cfg80211_roam_info *roam_info_params, 88 uint8_t link_id, 89 struct cfg80211_bss *bss) 90 { 91 osif_debug("Link_id :%d", link_id); 92 roam_info_params->valid_links |= BIT(link_id); 93 roam_info_params->links[link_id].bssid = bss->bssid; 94 roam_info_params->links[link_id].bss = bss; 95 roam_info_params->links[link_id].addr = 96 wlan_vdev_mlme_get_macaddr(vdev); 97 } 98 99 static void 100 osif_populate_partner_links_roam_mlo_params(struct wlan_objmgr_pdev *pdev, 101 struct wlan_cm_connect_resp *rsp, 102 struct cfg80211_roam_info *roam_info_params) 103 { 104 struct wlan_objmgr_vdev *partner_vdev; 105 struct mlo_link_info *rsp_partner_info; 106 struct mlo_partner_info assoc_partner_info = {0}; 107 struct cfg80211_bss *bss = NULL; 108 QDF_STATUS qdf_status; 109 uint8_t link_id = 0, num_links; 110 int i; 111 112 qdf_status = osif_get_partner_info_from_mlie(rsp, &assoc_partner_info); 113 if (QDF_IS_STATUS_ERROR(qdf_status)) 114 return; 115 116 num_links = rsp->ml_parnter_info.num_partner_links; 117 for (i = 0 ; i < num_links; i++) { 118 rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i]; 119 120 qdf_status = osif_get_link_id_from_assoc_ml_ie(rsp_partner_info, 121 &assoc_partner_info, 122 &link_id); 123 if (QDF_IS_STATUS_ERROR(qdf_status)) 124 continue; 125 126 partner_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 127 rsp_partner_info->vdev_id, 128 WLAN_MLO_MGR_ID); 129 if (!partner_vdev) 130 continue; 131 132 bss = osif_get_chan_bss_from_kernel(partner_vdev, 133 rsp_partner_info, rsp); 134 if (!bss) { 135 wlan_objmgr_vdev_release_ref(partner_vdev, 136 WLAN_MLO_MGR_ID); 137 continue; 138 } 139 140 osif_populate_mlo_info_for_link(partner_vdev, 141 roam_info_params, 142 link_id, bss); 143 wlan_objmgr_vdev_release_ref(partner_vdev, WLAN_MLO_MGR_ID); 144 } 145 } 146 147 static QDF_STATUS 148 osif_fill_peer_mld_mac_roam_info(struct wlan_objmgr_vdev *vdev, 149 struct wlan_cm_connect_resp *rsp, 150 struct cfg80211_roam_info *roam_info_params) 151 { 152 struct wlan_objmgr_peer *peer_obj; 153 154 peer_obj = wlan_objmgr_get_peer_by_mac(wlan_vdev_get_psoc(vdev), 155 rsp->bssid.bytes, WLAN_OSIF_ID); 156 if (!peer_obj) 157 return QDF_STATUS_E_INVAL; 158 159 roam_info_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj); 160 161 wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID); 162 163 return QDF_STATUS_SUCCESS; 164 } 165 166 static void osif_fill_mlo_roam_params(struct wlan_objmgr_vdev *vdev, 167 struct wlan_cm_connect_resp *rsp, 168 struct cfg80211_bss *bss, 169 struct cfg80211_roam_info *info) 170 { 171 QDF_STATUS qdf_status; 172 uint8_t assoc_link_id; 173 174 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 175 return; 176 177 qdf_status = osif_fill_peer_mld_mac_roam_info(vdev, rsp, 178 info); 179 if (QDF_IS_STATUS_ERROR(qdf_status)) { 180 osif_err("Unable to fill peer mld address: %d", qdf_status); 181 return; 182 } 183 184 assoc_link_id = wlan_vdev_get_link_id(vdev); 185 osif_populate_mlo_info_for_link(vdev, info, 186 assoc_link_id, bss); 187 188 osif_populate_partner_links_roam_mlo_params(wlan_vdev_get_pdev(vdev), 189 rsp, 190 info); 191 } 192 #else 193 static void osif_fill_mlo_roam_params(struct wlan_objmgr_vdev *vdev, 194 struct wlan_cm_connect_resp *rsp, 195 struct cfg80211_bss *bss, 196 struct cfg80211_roam_info *info) 197 {} 198 #endif 199 static void osif_roamed_ind(struct net_device *dev, 200 struct wlan_objmgr_vdev *vdev, 201 struct wlan_cm_connect_resp *rsp, 202 struct cfg80211_bss *bss, 203 const uint8_t *req_ie, 204 size_t req_ie_len, const uint8_t *resp_ie, 205 size_t resp_ie_len) 206 { 207 struct cfg80211_roam_info info = {0}; 208 209 osif_copy_roamed_info(&info, bss); 210 info.req_ie = req_ie; 211 info.req_ie_len = req_ie_len; 212 info.resp_ie = resp_ie; 213 info.resp_ie_len = resp_ie_len; 214 osif_fill_mlo_roam_params(vdev, rsp, bss, &info); 215 cfg80211_roamed(dev, &info, qdf_mem_malloc_flags()); 216 } 217 #else 218 static inline void osif_roamed_ind(struct net_device *dev, 219 struct wlan_objmgr_vdev *vdev, 220 struct wlan_cm_connect_resp *rsp, 221 struct cfg80211_bss *bss, 222 const uint8_t *req_ie, 223 size_t req_ie_len, const uint8_t *resp_ie, 224 size_t resp_ie_len) 225 226 { 227 cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, resp_ie_len, 228 qdf_mem_malloc_flags()); 229 } 230 #endif 231 232 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 233 #ifdef WLAN_FEATURE_FILS_SK 234 /** 235 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth 236 * @skb: SK buffer 237 * @roam_info: Roam info 238 * 239 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event 240 * 241 * Return: zero on success, error code on failure 242 */ 243 static int 244 osif_add_fils_params_roam_auth_event(struct sk_buff *skb, 245 struct wlan_roam_sync_info *roam_info) 246 { 247 if (roam_info->pmk_len && 248 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK, 249 roam_info->pmk_len, roam_info->pmk)) { 250 osif_err("pmk send fail"); 251 return -EINVAL; 252 } 253 254 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID, 255 PMKID_LEN, roam_info->pmkid)) { 256 osif_err("pmkid send fail"); 257 return -EINVAL; 258 } 259 260 osif_debug("Update ERP Seq Num %d, Next ERP Seq Num %d", 261 roam_info->update_erp_next_seq_num, 262 roam_info->next_erp_seq_num); 263 if (roam_info->update_erp_next_seq_num && 264 nla_put_u16(skb, 265 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM, 266 roam_info->next_erp_seq_num)) { 267 osif_err("ERP seq num send fail"); 268 return -EINVAL; 269 } 270 271 return 0; 272 } 273 #else 274 static inline int 275 osif_add_fils_params_roam_auth_event(struct sk_buff *skb, 276 struct wlan_roam_sync_info *roam_info) 277 { 278 return 0; 279 } 280 #endif 281 282 /** 283 * osif_get_roam_reason() - convert wmi roam reason to 284 * enum qca_roam_reason 285 * @roam_scan_trigger: wmi roam scan trigger ID 286 * 287 * Return: Meaningful qca_roam_reason from enum WMI_ROAM_TRIGGER_REASON_ID 288 */ 289 static enum qca_roam_reason osif_get_roam_reason(uint16_t roam_scan_trigger) 290 { 291 switch (roam_scan_trigger) { 292 case ROAM_TRIGGER_REASON_PER: 293 return QCA_ROAM_REASON_PER; 294 case ROAM_TRIGGER_REASON_BMISS: 295 return QCA_ROAM_REASON_BEACON_MISS; 296 case ROAM_TRIGGER_REASON_LOW_RSSI: 297 case ROAM_TRIGGER_REASON_BACKGROUND: 298 return QCA_ROAM_REASON_POOR_RSSI; 299 case ROAM_TRIGGER_REASON_HIGH_RSSI: 300 return QCA_ROAM_REASON_BETTER_RSSI; 301 case ROAM_TRIGGER_REASON_DENSE: 302 return QCA_ROAM_REASON_CONGESTION; 303 case ROAM_TRIGGER_REASON_FORCED: 304 return QCA_ROAM_REASON_USER_TRIGGER; 305 case ROAM_TRIGGER_REASON_BTM: 306 return QCA_ROAM_REASON_BTM; 307 case ROAM_TRIGGER_REASON_BSS_LOAD: 308 return QCA_ROAM_REASON_BSS_LOAD; 309 default: 310 return QCA_ROAM_REASON_UNKNOWN; 311 } 312 313 return QCA_ROAM_REASON_UNKNOWN; 314 } 315 316 #ifdef WLAN_FEATURE_11BE_MLO 317 318 static uint8_t *osif_get_bss_mac_addr(struct wlan_objmgr_vdev *vdev) 319 { 320 struct wlan_objmgr_peer *peer; 321 322 peer = wlan_vdev_get_bsspeer(vdev); 323 if (peer) 324 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) 325 return wlan_peer_mlme_get_mldaddr(peer); 326 else 327 return wlan_peer_get_macaddr(peer); 328 else 329 return NULL; 330 } 331 332 /** 333 * osif_send_roam_auth_mlo_links_event() - API to send roam auth mlo 334 * links event response to kernel 335 * @skb : sk buffer pointer 336 * @vdev: vdev pointer 337 * @rsp: Connection manager response 338 * 339 * This is called when wlan driver needs to send the mlo links roaming 340 * information after roaming. 341 * 342 * Context: Any context. 343 * Return: int 344 */ 345 static int 346 osif_send_roam_auth_mlo_links_event(struct sk_buff *skb, 347 struct wlan_objmgr_vdev *vdev, 348 struct vdev_osif_priv *osif_priv, 349 struct wlan_cm_connect_resp *rsp) 350 { 351 struct wlan_objmgr_psoc *psoc; 352 bool roam_offload_enable; 353 uint8_t i; 354 struct nlattr *mlo_links; 355 struct nlattr *mlo_links_info; 356 struct wlan_objmgr_vdev *link_vdev; 357 uint8_t link_vdev_id; 358 359 if (!vdev) 360 return -EINVAL; 361 362 psoc = wlan_vdev_get_psoc(vdev); 363 ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable); 364 365 if (!roam_offload_enable) 366 return -EINVAL; 367 368 mlo_links = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MLO_LINKS); 369 if (!mlo_links) { 370 osif_err("nla_nest_start error"); 371 return -EINVAL; 372 } 373 374 for (i = 0; i < rsp->ml_parnter_info.num_partner_links; i++) { 375 mlo_links_info = nla_nest_start(skb, i); 376 if (!mlo_links_info) { 377 osif_err("nla nest start fail"); 378 return -EINVAL; 379 } 380 381 if (nla_put_u8(skb, 382 QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID, 383 rsp->ml_parnter_info.partner_link_info[i].link_id)) { 384 osif_err("nla put fail"); 385 return -EINVAL; 386 } 387 388 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_BSSID, 389 ETH_ALEN, 390 (void *)&rsp->ml_parnter_info.partner_link_info[i].link_addr)) { 391 osif_err("nla put fail"); 392 return -EINVAL; 393 } 394 395 link_vdev_id = rsp->ml_parnter_info.partner_link_info[i].vdev_id; 396 link_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 397 link_vdev_id, 398 WLAN_OSIF_CM_ID); 399 if (!link_vdev) { 400 osif_err("link vdev is null"); 401 return -EINVAL; 402 } 403 404 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAC_ADDR, 405 ETH_ALEN, wlan_vdev_mlme_get_macaddr(link_vdev))) { 406 osif_err("nla put fail"); 407 wlan_objmgr_vdev_release_ref(link_vdev, 408 WLAN_OSIF_CM_ID); 409 return -EINVAL; 410 } 411 wlan_objmgr_vdev_release_ref(link_vdev, WLAN_OSIF_CM_ID); 412 nla_nest_end(skb, mlo_links_info); 413 } 414 415 nla_nest_end(skb, mlo_links); 416 417 return 0; 418 } 419 #else 420 static uint8_t *osif_get_bss_mac_addr(struct wlan_objmgr_vdev *vdev) 421 { 422 struct wlan_objmgr_peer *peer; 423 424 peer = wlan_vdev_get_bsspeer(vdev); 425 if (peer) 426 return wlan_peer_get_macaddr(peer); 427 else 428 return NULL; 429 } 430 431 static inline int 432 osif_send_roam_auth_mlo_links_event(struct sk_buff *skb, 433 struct wlan_objmgr_vdev *vdev, 434 struct vdev_osif_priv *osif_priv, 435 struct wlan_cm_connect_resp *rsp) 436 { 437 return 0; 438 } 439 #endif 440 441 /** 442 * osif_send_roam_auth_event() - API to send roam auth event response to kernel 443 * @vdev: vdev pointer 444 * @osif_priv: OS private structure of vdev 445 * @rsp: Connection manager response 446 * 447 * This is called when wlan driver needs to send the roaming and 448 * authorization information after roaming. 449 * 450 * The information that would be sent is the request RSN IE, response 451 * RSN IE and BSSID of the newly roamed AP. 452 * 453 * If the Authorized status is authenticated, then additional parameters 454 * like PTK's KCK and KEK and Replay Counter would also be passed to the 455 * supplicant. 456 * 457 * The supplicant upon receiving this event would ignore the legacy 458 * cfg80211_roamed call and use the entire information from this event. 459 * The cfg80211_roamed should still co-exist since the kernel will 460 * make use of the parameters even if the supplicant ignores it. 461 * 462 * 463 * Context: Any context. 464 * Return: int 465 */ 466 static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev, 467 struct vdev_osif_priv *osif_priv, 468 struct wlan_cm_connect_resp *rsp, 469 const uint8_t *req_ie, 470 size_t req_ie_len, const uint8_t *resp_ie, 471 size_t resp_ie_len) 472 { 473 struct wlan_objmgr_psoc *psoc; 474 uint32_t fils_params_len; 475 struct sk_buff *skb = NULL; 476 struct wlan_roam_sync_info *roaming_info; 477 int status; 478 int32_t akm; 479 bool roam_offload_enable; 480 uint8_t *bss_mac_addr; 481 uint8_t num_of_links = 0; 482 483 psoc = wlan_vdev_get_psoc(vdev); 484 ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable); 485 486 if (!roam_offload_enable) 487 return 0; 488 489 roaming_info = rsp->roaming_info; 490 491 /* 492 * PMK is sent from FW in Roam Synch Event for FILS Roaming. 493 * In that case, add three more NL attributes.ie. PMK, PMKID 494 * and ERP next sequence number. Add corresponding lengths 495 * with 3 extra NL message headers for each of the 496 * aforementioned params. 497 */ 498 fils_params_len = roaming_info->pmk_len + PMKID_LEN + 499 sizeof(uint16_t) + (3 * NLMSG_HDRLEN); 500 501 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 502 #ifdef WLAN_FEATURE_11BE_MLO 503 num_of_links = rsp->ml_parnter_info.num_partner_links; 504 #endif 505 skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy, 506 osif_priv->wdev, 507 (ETH_ALEN * num_of_links) + 508 (sizeof(uint8_t) * num_of_links) + 509 (ETH_ALEN * num_of_links) + 510 req_ie_len + resp_ie_len + 511 sizeof(uint8_t) + REPLAY_CTR_LEN + 512 roaming_info->kck_len + roaming_info->kek_len + 513 sizeof(uint16_t) + sizeof(uint8_t) + 514 (9 * NLMSG_HDRLEN) + fils_params_len, 515 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX, 516 qdf_mem_malloc_flags()); 517 } else { 518 skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy, 519 osif_priv->wdev, 520 ETH_ALEN + req_ie_len + 521 resp_ie_len + 522 sizeof(uint8_t) + REPLAY_CTR_LEN + 523 roaming_info->kck_len + roaming_info->kek_len + 524 sizeof(uint16_t) + sizeof(uint8_t) + 525 (9 * NLMSG_HDRLEN) + fils_params_len, 526 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX, 527 qdf_mem_malloc_flags()); 528 } 529 if (!skb) { 530 osif_err("cfg80211_vendor_event_alloc failed"); 531 return -1; 532 } 533 534 bss_mac_addr = osif_get_bss_mac_addr(vdev); 535 if (!bss_mac_addr) { 536 osif_err("Invalid bss mac addr"); 537 goto nla_put_failure; 538 } 539 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, 540 ETH_ALEN, bss_mac_addr) || 541 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, 542 req_ie_len, req_ie) || 543 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, 544 resp_ie_len, resp_ie)) { 545 osif_err("nla put fail"); 546 goto nla_put_failure; 547 } 548 549 if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED) { 550 osif_debug("Include Auth Params TLV's"); 551 if (nla_put_u8(skb, 552 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, 553 true)) { 554 osif_err("nla put fail"); 555 goto nla_put_failure; 556 } 557 akm = wlan_crypto_get_param(vdev, 558 WLAN_CRYPTO_PARAM_KEY_MGMT); 559 /* if FT or CCKM connection: dont send replay counter */ 560 if (!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) && 561 !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK) && 562 !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) && 563 !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384) && 564 !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM) && 565 nla_put(skb, 566 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, 567 REPLAY_CTR_LEN, 568 roaming_info->replay_ctr)) { 569 osif_err("non FT/non CCKM connection"); 570 osif_err("failed to send replay counter"); 571 goto nla_put_failure; 572 } 573 if (roaming_info->kek_len > MAX_KEK_LENGTH || 574 roaming_info->kck_len > MAX_KCK_LEN || 575 nla_put(skb, 576 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, 577 roaming_info->kck_len, roaming_info->kck) || 578 nla_put(skb, 579 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, 580 roaming_info->kek_len, roaming_info->kek)) { 581 osif_err("nla put fail, kek_len %d", 582 roaming_info->kek_len); 583 goto nla_put_failure; 584 } 585 586 if (nla_put_u16(skb, 587 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON, 588 osif_get_roam_reason(roaming_info->roam_reason))) { 589 osif_err("roam reason send failure"); 590 goto nla_put_failure; 591 } 592 593 status = osif_add_fils_params_roam_auth_event(skb, 594 roaming_info); 595 if (status) 596 goto nla_put_failure; 597 /* 598 * Save the gtk rekey parameters in HDD STA context. They will 599 * be used next time when host enables GTK offload and goes 600 * into power save state. 601 */ 602 osif_cm_save_gtk(vdev, rsp); 603 osif_debug("replay_ctr 0x%llx kck %d kek %d", 604 *((uint64_t *)roaming_info->replay_ctr), 605 roaming_info->kck_len, 606 roaming_info->kek_len); 607 608 } else { 609 osif_debug("No Auth Params TLV's"); 610 if (nla_put_u8(skb, 611 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, 612 false)) { 613 osif_err("nla put fail"); 614 goto nla_put_failure; 615 } 616 } 617 618 osif_debug("Auth Status = %d Subnet Change Status = %d", 619 roaming_info->auth_status, 620 roaming_info->subnet_change_status); 621 /* 622 * Add subnet change status if subnet has changed 623 * 0 = unchanged 624 * 1 = changed 625 * 2 = unknown 626 */ 627 if (roaming_info->subnet_change_status) { 628 if (nla_put_u8(skb, 629 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS, 630 roaming_info->subnet_change_status)) { 631 osif_err("nla put fail"); 632 goto nla_put_failure; 633 } 634 } 635 636 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 637 status = osif_send_roam_auth_mlo_links_event(skb, vdev, 638 osif_priv, 639 rsp); 640 if (status) { 641 osif_err("Send mlo link fail"); 642 goto nla_put_failure; 643 } 644 } 645 cfg80211_vendor_event(skb, qdf_mem_malloc_flags()); 646 return 0; 647 648 nla_put_failure: 649 kfree_skb(skb); 650 return -1; 651 } 652 #else 653 static inline int 654 osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev, 655 struct vdev_osif_priv *osif_priv, 656 struct wlan_cm_connect_resp *rsp, 657 const uint8_t *req_ie, 658 size_t req_ie_len, const uint8_t *resp_ie, 659 size_t resp_ie_len) 660 { 661 return 0; 662 } 663 #endif 664 665 static void osif_cm_get_reassoc_req_ie_data(struct element_info *assoc_req, 666 size_t *ie_data_len, 667 const uint8_t **ie_data_ptr) 668 { 669 /* Validate IE and length */ 670 if (!assoc_req->len || !assoc_req->ptr || 671 assoc_req->len <= WLAN_REASSOC_REQ_IES_OFFSET) 672 return; 673 674 *ie_data_len = assoc_req->len - WLAN_REASSOC_REQ_IES_OFFSET; 675 *ie_data_ptr = assoc_req->ptr + WLAN_REASSOC_REQ_IES_OFFSET; 676 } 677 678 void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev, 679 struct vdev_osif_priv *osif_priv, 680 struct wlan_cm_connect_resp *rsp) 681 { 682 struct net_device *dev = osif_priv->wdev->netdev; 683 size_t req_len = 0; 684 const uint8_t *req_ie = NULL; 685 size_t rsp_len = 0; 686 const uint8_t *rsp_ie = NULL; 687 struct cfg80211_bss *bss; 688 struct ieee80211_channel *chan; 689 struct wlan_objmgr_psoc *psoc; 690 691 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 692 wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 693 return; 694 695 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) 696 return; 697 698 psoc = wlan_vdev_get_psoc(vdev); 699 if (!psoc) 700 return; 701 702 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 703 rsp->freq); 704 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 705 rsp->bssid.bytes, rsp->ssid.ssid, 706 rsp->ssid.length); 707 if (!bss) 708 osif_warn("not able to find bss"); 709 if (rsp->is_assoc) 710 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 711 &req_len, &req_ie); 712 else 713 osif_cm_get_reassoc_req_ie_data(&rsp->connect_ies.assoc_req, 714 &req_len, &req_ie); 715 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 716 &rsp_len, &rsp_ie); 717 osif_roamed_ind(dev, vdev, rsp, bss, req_ie, req_len, rsp_ie, rsp_len); 718 osif_send_roam_auth_event(vdev, osif_priv, rsp, req_ie, req_len, rsp_ie, 719 rsp_len); 720 721 osif_update_fils_hlp_data(dev, vdev, rsp); 722 } 723 724 QDF_STATUS 725 osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev, 726 struct qdf_mac_addr *bssid, 727 int index, bool preauth) 728 { 729 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 730 struct wireless_dev *wdev; 731 732 if (!osif_priv) { 733 osif_err("Invalid vdev osif priv"); 734 return QDF_STATUS_E_INVAL; 735 } 736 737 wdev = osif_priv->wdev; 738 if (!wdev) { 739 osif_err("wdev is null"); 740 return QDF_STATUS_E_INVAL; 741 } 742 743 osif_debug("is going to notify supplicant of:"); 744 osif_info(QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(bssid->bytes)); 745 746 cfg80211_pmksa_candidate_notify(wdev->netdev, index, 747 bssid->bytes, 748 preauth, qdf_mem_malloc_flags()); 749 return QDF_STATUS_SUCCESS; 750 } 751 #endif /* CONN_MGR_ADV_FEATURE */ 752