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