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