xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/mlme/src/osif_cm_roam_rsp.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
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 
370 	for (i = 0; i < rsp->ml_parnter_info.num_partner_links; i++) {
371 		mlo_links_info = nla_nest_start(skb, i);
372 		if (!mlo_links_info) {
373 			osif_err("nla nest start fail");
374 			return -EINVAL;
375 		}
376 
377 		if (nla_put_u8(skb,
378 			       QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID,
379 			       rsp->ml_parnter_info.partner_link_info[i].link_id)) {
380 			osif_err("nla put fail");
381 			return -EINVAL;
382 		}
383 
384 		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_BSSID,
385 			    ETH_ALEN,
386 			    (void *)&rsp->ml_parnter_info.partner_link_info[i].link_addr)) {
387 			osif_err("nla put fail");
388 			return -EINVAL;
389 		}
390 
391 		link_vdev_id = rsp->ml_parnter_info.partner_link_info[i].vdev_id;
392 		link_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
393 								 link_vdev_id,
394 								 WLAN_OSIF_CM_ID);
395 		if (!link_vdev) {
396 			osif_err("link vdev is null");
397 			return -EINVAL;
398 		}
399 
400 		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAC_ADDR,
401 			    ETH_ALEN, wlan_vdev_mlme_get_macaddr(link_vdev))) {
402 			osif_err("nla put fail");
403 			return -EINVAL;
404 		}
405 		nla_nest_end(skb, mlo_links_info);
406 	}
407 
408 	nla_nest_end(skb, mlo_links);
409 
410 	return 0;
411 }
412 #else
413 static uint8_t *osif_get_bss_mac_addr(struct wlan_objmgr_vdev *vdev)
414 {
415 	struct wlan_objmgr_peer *peer;
416 
417 	peer = wlan_vdev_get_bsspeer(vdev);
418 	if (peer)
419 		return wlan_peer_get_macaddr(peer);
420 	else
421 		return NULL;
422 }
423 
424 static inline int
425 osif_send_roam_auth_mlo_links_event(struct sk_buff *skb,
426 				    struct wlan_objmgr_vdev *vdev,
427 				    struct vdev_osif_priv *osif_priv,
428 				    struct wlan_cm_connect_resp *rsp)
429 {
430 	return 0;
431 }
432 #endif
433 
434 /**
435  * osif_send_roam_auth_event() - API to send roam auth event response to kernel
436  * @vdev: vdev pointer
437  * @osif_priv: OS private structure of vdev
438  * @rsp: Connection manager response
439  *
440  * This is called when wlan driver needs to send the roaming and
441  * authorization information after roaming.
442  *
443  * The information that would be sent is the request RSN IE, response
444  * RSN IE and BSSID of the newly roamed AP.
445  *
446  * If the Authorized status is authenticated, then additional parameters
447  * like PTK's KCK and KEK and Replay Counter would also be passed to the
448  * supplicant.
449  *
450  * The supplicant upon receiving this event would ignore the legacy
451  * cfg80211_roamed call and use the entire information from this event.
452  * The cfg80211_roamed should still co-exist since the kernel will
453  * make use of the parameters even if the supplicant ignores it.
454  *
455  *
456  * Context: Any context.
457  * Return: int
458  */
459 static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
460 				     struct vdev_osif_priv *osif_priv,
461 				     struct wlan_cm_connect_resp *rsp,
462 				     const uint8_t *req_ie,
463 				     size_t req_ie_len, const uint8_t *resp_ie,
464 				     size_t resp_ie_len)
465 {
466 	struct wlan_objmgr_psoc *psoc;
467 	uint32_t fils_params_len;
468 	struct sk_buff *skb = NULL;
469 	struct wlan_roam_sync_info *roaming_info;
470 	int status;
471 	int32_t akm;
472 	bool roam_offload_enable;
473 	uint8_t *bss_mac_addr;
474 	uint8_t num_of_links = 0;
475 
476 	psoc = wlan_vdev_get_psoc(vdev);
477 	ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable);
478 
479 	if (!roam_offload_enable)
480 		return 0;
481 
482 	roaming_info = rsp->roaming_info;
483 
484 	/*
485 	 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
486 	 * In that case, add three more NL attributes.ie. PMK, PMKID
487 	 * and ERP next sequence number. Add corresponding lengths
488 	 * with 3 extra NL message headers for each of the
489 	 * aforementioned params.
490 	 */
491 	fils_params_len = roaming_info->pmk_len + PMKID_LEN +
492 			  sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
493 
494 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
495 #ifdef WLAN_FEATURE_11BE_MLO
496 		num_of_links = rsp->ml_parnter_info.num_partner_links;
497 #endif
498 		skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy,
499 				osif_priv->wdev,
500 				(ETH_ALEN * num_of_links) +
501 				(sizeof(uint8_t) * num_of_links) +
502 				(ETH_ALEN * num_of_links) +
503 				req_ie_len + resp_ie_len +
504 				sizeof(uint8_t) + REPLAY_CTR_LEN +
505 				KCK_KEY_LEN + roaming_info->kek_len +
506 				sizeof(uint16_t) + sizeof(uint8_t) +
507 				(9 * NLMSG_HDRLEN) + fils_params_len,
508 				QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
509 				qdf_mem_malloc_flags());
510 	} else {
511 		skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy,
512 				osif_priv->wdev,
513 				ETH_ALEN + req_ie_len +
514 				resp_ie_len +
515 				sizeof(uint8_t) + REPLAY_CTR_LEN +
516 				KCK_KEY_LEN + roaming_info->kek_len +
517 				sizeof(uint16_t) + sizeof(uint8_t) +
518 				(9 * NLMSG_HDRLEN) + fils_params_len,
519 				QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
520 				qdf_mem_malloc_flags());
521 	}
522 	if (!skb) {
523 		osif_err("cfg80211_vendor_event_alloc failed");
524 		return -1;
525 	}
526 
527 	bss_mac_addr = osif_get_bss_mac_addr(vdev);
528 	if (!bss_mac_addr) {
529 		osif_err("Invalid bss mac addr");
530 		goto nla_put_failure;
531 	}
532 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
533 		    ETH_ALEN, bss_mac_addr) ||
534 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
535 		    req_ie_len, req_ie) ||
536 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
537 		    resp_ie_len, resp_ie)) {
538 		osif_err("nla put fail");
539 		goto nla_put_failure;
540 	}
541 
542 	if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED) {
543 		osif_debug("Include Auth Params TLV's");
544 		if (nla_put_u8(skb,
545 			       QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
546 			       true)) {
547 			osif_err("nla put fail");
548 			goto nla_put_failure;
549 		}
550 		akm = wlan_crypto_get_param(vdev,
551 					    WLAN_CRYPTO_PARAM_KEY_MGMT);
552 		/* if FT or CCKM connection: dont send replay counter */
553 		if (!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) &&
554 		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK) &&
555 		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) &&
556 		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384) &&
557 		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM) &&
558 		    nla_put(skb,
559 			    QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
560 			    REPLAY_CTR_LEN,
561 			    roaming_info->replay_ctr)) {
562 			osif_err("non FT/non CCKM connection");
563 			osif_err("failed to send replay counter");
564 			goto nla_put_failure;
565 		}
566 		if (roaming_info->kek_len > MAX_KEK_LENGTH ||
567 		    nla_put(skb,
568 			    QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
569 			    roaming_info->kck_len, roaming_info->kck) ||
570 		    nla_put(skb,
571 			    QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
572 			    roaming_info->kek_len, roaming_info->kek)) {
573 			osif_err("nla put fail, kek_len %d",
574 				 roaming_info->kek_len);
575 			goto nla_put_failure;
576 		}
577 
578 		if (nla_put_u16(skb,
579 				QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON,
580 				osif_get_roam_reason(roaming_info->roam_reason))) {
581 			osif_err("roam reason send failure");
582 			goto nla_put_failure;
583 		}
584 
585 		status = osif_add_fils_params_roam_auth_event(skb,
586 							      roaming_info);
587 		if (status)
588 			goto nla_put_failure;
589 		/*
590 		 * Save the gtk rekey parameters in HDD STA context. They will
591 		 * be used next time when host enables GTK offload and goes
592 		 * into power save state.
593 		 */
594 		osif_cm_save_gtk(vdev, rsp);
595 		osif_debug("roam_info_ptr->replay_ctr 0x%llx",
596 			   *((uint64_t *)roaming_info->replay_ctr));
597 
598 	} else {
599 		osif_debug("No Auth Params TLV's");
600 		if (nla_put_u8(skb,
601 			       QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
602 			       false)) {
603 			osif_err("nla put fail");
604 			goto nla_put_failure;
605 		}
606 	}
607 
608 	osif_debug("Auth Status = %d Subnet Change Status = %d",
609 		   roaming_info->auth_status,
610 		   roaming_info->subnet_change_status);
611 	/*
612 	 * Add subnet change status if subnet has changed
613 	 * 0 = unchanged
614 	 * 1 = changed
615 	 * 2 = unknown
616 	 */
617 	if (roaming_info->subnet_change_status) {
618 		if (nla_put_u8(skb,
619 			       QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
620 			       roaming_info->subnet_change_status)) {
621 			osif_err("nla put fail");
622 			goto nla_put_failure;
623 		}
624 	}
625 
626 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
627 		status = osif_send_roam_auth_mlo_links_event(skb, vdev,
628 							     osif_priv,
629 							     rsp);
630 		if (status) {
631 			osif_err("Send mlo link fail");
632 			goto nla_put_failure;
633 		}
634 	}
635 	cfg80211_vendor_event(skb, qdf_mem_malloc_flags());
636 	return 0;
637 
638 nla_put_failure:
639 	kfree_skb(skb);
640 	return -1;
641 }
642 #else
643 static inline int
644 osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
645 			  struct vdev_osif_priv *osif_priv,
646 			  struct wlan_cm_connect_resp *rsp,
647 			  const uint8_t *req_ie,
648 			  size_t req_ie_len, const uint8_t *resp_ie,
649 			  size_t resp_ie_len)
650 {
651 	return 0;
652 }
653 #endif
654 
655 static void osif_cm_get_reassoc_req_ie_data(struct element_info *assoc_req,
656 					    size_t *ie_data_len,
657 					    const uint8_t **ie_data_ptr)
658 {
659 	/* Validate IE and length */
660 	if (!assoc_req->len || !assoc_req->ptr ||
661 	    assoc_req->len <= WLAN_REASSOC_REQ_IES_OFFSET)
662 		return;
663 
664 	*ie_data_len = assoc_req->len - WLAN_REASSOC_REQ_IES_OFFSET;
665 	*ie_data_ptr = assoc_req->ptr + WLAN_REASSOC_REQ_IES_OFFSET;
666 }
667 
668 void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
669 				   struct vdev_osif_priv *osif_priv,
670 				   struct wlan_cm_connect_resp *rsp)
671 {
672 	struct net_device *dev = osif_priv->wdev->netdev;
673 	size_t req_len = 0;
674 	const uint8_t *req_ie = NULL;
675 	size_t rsp_len = 0;
676 	const uint8_t *rsp_ie = NULL;
677 	struct cfg80211_bss *bss;
678 	struct ieee80211_channel *chan;
679 	struct wlan_objmgr_psoc *psoc;
680 
681 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
682 	    wlan_vdev_mlme_is_mlo_link_vdev(vdev))
683 		return;
684 
685 	if (QDF_IS_STATUS_ERROR(rsp->connect_status))
686 		return;
687 
688 	psoc = wlan_vdev_get_psoc(vdev);
689 	if (!psoc)
690 		return;
691 
692 	chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
693 				     rsp->freq);
694 	bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
695 				    rsp->bssid.bytes, rsp->ssid.ssid,
696 				    rsp->ssid.length);
697 	if (!bss)
698 		osif_warn("not able to find bss");
699 	if (rsp->is_assoc)
700 		osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
701 					      &req_len, &req_ie);
702 	else
703 		osif_cm_get_reassoc_req_ie_data(&rsp->connect_ies.assoc_req,
704 						&req_len, &req_ie);
705 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
706 				      &rsp_len, &rsp_ie);
707 	osif_roamed_ind(dev, vdev, rsp, bss, req_ie, req_len, rsp_ie, rsp_len);
708 	osif_send_roam_auth_event(vdev, osif_priv, rsp, req_ie, req_len, rsp_ie,
709 				  rsp_len);
710 
711 	osif_update_fils_hlp_data(dev, vdev, rsp);
712 }
713 
714 QDF_STATUS
715 osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev,
716 			    struct qdf_mac_addr *bssid,
717 			    int index, bool preauth)
718 {
719 	struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
720 	struct wireless_dev *wdev;
721 
722 	if (!osif_priv) {
723 		osif_err("Invalid vdev osif priv");
724 		return QDF_STATUS_E_INVAL;
725 	}
726 
727 	wdev = osif_priv->wdev;
728 	if (!wdev) {
729 		osif_err("wdev is null");
730 		return QDF_STATUS_E_INVAL;
731 	}
732 
733 	osif_debug("is going to notify supplicant of:");
734 	osif_info(QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(bssid->bytes));
735 
736 	cfg80211_pmksa_candidate_notify(wdev->netdev, index,
737 					bssid->bytes,
738 					preauth, qdf_mem_malloc_flags());
739 	return QDF_STATUS_SUCCESS;
740 }
741 #endif /* CONN_MGR_ADV_FEATURE */
742