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