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
osif_update_fils_hlp_data(struct net_device * dev,struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)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
osif_update_fils_hlp_data(struct net_device * dev,struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)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
osif_copy_roamed_info(struct cfg80211_roam_info * info,struct cfg80211_bss * bss)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
osif_copy_roamed_info(struct cfg80211_roam_info * info,struct cfg80211_bss * bss)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
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 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
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 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
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 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
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 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
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 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 */
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 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
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 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
osif_add_fils_params_roam_auth_event(struct sk_buff * skb,struct wlan_roam_sync_info * roam_info)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
osif_add_fils_params_roam_auth_event(struct sk_buff * skb,struct wlan_roam_sync_info * roam_info)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 */
osif_get_roam_reason(uint16_t roam_scan_trigger)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
osif_get_bss_mac_addr(struct wlan_objmgr_vdev * vdev)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
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 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
osif_get_bss_mac_addr(struct wlan_objmgr_vdev * vdev)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
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 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 */
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 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
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 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
osif_cm_get_reassoc_req_ie_data(struct element_info * assoc_req,size_t * ie_data_len,const uint8_t ** ie_data_ptr)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
osif_indicate_reassoc_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)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
osif_pmksa_candidate_notify(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * bssid,int index,bool preauth)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