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