1 /*
2  * Copyright (c) 2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-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: wlan_cm_host_util.c
20  *
21  * Implements Host roam (LFR2) reassoc specific legacy code for
22  * connection manager
23  */
24 
25 #include "wlan_cm_vdev_api.h"
26 #include "wlan_scan_api.h"
27 #include "wlan_scan_utils_api.h"
28 #include "wlan_policy_mgr_api.h"
29 #include "wlan_roam_debug.h"
30 #include "wni_api.h"
31 #include "wlan_logging_sock_svc.h"
32 #include "connection_mgr/core/src/wlan_cm_roam.h"
33 
34 /*
35  * cm_copy_ssids_from_rso_config_params() - copy SSID from rso_config_params
36  * to scan filter
37  * @rso_usr_cfg: rso user config
38  * @filter: scan filter
39  *
40  * Return void
41  */
42 static void
cm_copy_ssids_from_rso_config_params(struct rso_user_config * rso_usr_cfg,struct scan_filter * filter)43 cm_copy_ssids_from_rso_config_params(struct rso_user_config *rso_usr_cfg,
44 				     struct scan_filter *filter)
45 {
46 	uint8_t i;
47 	uint8_t max_ssid;
48 
49 	if (!rso_usr_cfg->num_ssid_allowed_list)
50 		return;
51 	max_ssid = QDF_MIN(WLAN_SCAN_FILTER_NUM_SSID, MAX_SSID_ALLOWED_LIST);
52 
53 	filter->num_of_ssid = rso_usr_cfg->num_ssid_allowed_list;
54 	if (filter->num_of_ssid > max_ssid)
55 		filter->num_of_ssid = max_ssid;
56 	for  (i = 0; i < filter->num_of_ssid; i++)
57 		qdf_mem_copy(&filter->ssid_list[i],
58 			     &rso_usr_cfg->ssid_allowed_list[i],
59 			     sizeof(struct wlan_ssid));
60 }
61 
cm_update_advance_roam_scan_filter(struct wlan_objmgr_vdev * vdev,struct scan_filter * filter)62 QDF_STATUS cm_update_advance_roam_scan_filter(
63 		struct wlan_objmgr_vdev *vdev, struct scan_filter *filter)
64 {
65 	uint8_t num_ch = 0;
66 	struct wlan_objmgr_psoc *psoc;
67 	struct rso_config *rso_cfg;
68 	struct rso_chan_info *chan_lst;
69 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
70 	struct rso_user_config *rso_usr_cfg;
71 
72 	psoc = wlan_vdev_get_psoc(vdev);
73 	if (!psoc) {
74 		mlme_debug("psoc is NULL");
75 		return QDF_STATUS_E_INVAL;
76 	}
77 
78 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
79 	if (!mlme_obj)
80 		return QDF_STATUS_E_FAILURE;
81 
82 	rso_usr_cfg = wlan_cm_get_rso_user_config(vdev);
83 	if (!rso_usr_cfg)
84 		return QDF_STATUS_E_INVAL;
85 
86 	mlme_debug("No of Allowed SSID List:%d",
87 		   rso_usr_cfg->num_ssid_allowed_list);
88 
89 	if (rso_usr_cfg->num_ssid_allowed_list) {
90 		cm_copy_ssids_from_rso_config_params(rso_usr_cfg, filter);
91 	} else {
92 		filter->num_of_ssid = 1;
93 		wlan_vdev_mlme_get_ssid(vdev, filter->ssid_list[0].ssid,
94 					&filter->ssid_list[0].length);
95 
96 		mlme_debug("Filtering for SSID " QDF_SSID_FMT ",length of SSID = %u",
97 			   QDF_SSID_REF(filter->ssid_list[0].length,
98 					filter->ssid_list[0].ssid),
99 			   filter->ssid_list[0].length);
100 	}
101 
102 	rso_cfg = wlan_cm_get_rso_config(vdev);
103 	if (!rso_cfg)
104 		return QDF_STATUS_E_FAILURE;
105 
106 	chan_lst = &rso_cfg->roam_scan_freq_lst;
107 	num_ch = chan_lst->num_chan;
108 	if (num_ch) {
109 		filter->num_of_channels = num_ch;
110 		if (filter->num_of_channels > NUM_CHANNELS)
111 			filter->num_of_channels = NUM_CHANNELS;
112 		qdf_mem_copy(filter->chan_freq_list, chan_lst->freq_list,
113 			     filter->num_of_channels *
114 			     sizeof(filter->chan_freq_list[0]));
115 	}
116 
117 	if (rso_cfg->is_11r_assoc)
118 		/*
119 		 * MDIE should be added as a part of profile. This should be
120 		 * added as a part of filter as well
121 		 */
122 		filter->mobility_domain = rso_cfg->mdid.mobility_domain;
123 	filter->enable_adaptive_11r =
124 		wlan_mlme_adaptive_11r_enabled(psoc);
125 
126 	if (rso_cfg->orig_sec_info.rsn_caps &
127 	    WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
128 		filter->pmf_cap = WLAN_PMF_REQUIRED;
129 	else if (rso_cfg->orig_sec_info.rsn_caps &
130 		 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
131 		filter->pmf_cap = WLAN_PMF_CAPABLE;
132 
133 	return QDF_STATUS_SUCCESS;
134 }
135 
136 QDF_STATUS
cm_handle_reassoc_req(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_reassoc_req * req)137 cm_handle_reassoc_req(struct wlan_objmgr_vdev *vdev,
138 		      struct wlan_cm_vdev_reassoc_req *req)
139 {
140 	struct cm_vdev_join_req *join_req;
141 	struct scheduler_msg msg;
142 	QDF_STATUS status;
143 	struct wlan_objmgr_pdev *pdev;
144 	struct wlan_objmgr_psoc *psoc;
145 	struct rso_config *rso_cfg;
146 
147 	if (!vdev || !req)
148 		return QDF_STATUS_E_FAILURE;
149 
150 	pdev = wlan_vdev_get_pdev(vdev);
151 	if (!pdev) {
152 		mlme_err(CM_PREFIX_FMT "pdev not found",
153 			 CM_PREFIX_REF(req->vdev_id, req->cm_id));
154 		return QDF_STATUS_E_INVAL;
155 	}
156 	psoc = wlan_pdev_get_psoc(pdev);
157 	if (!psoc) {
158 		mlme_err(CM_PREFIX_FMT "psoc not found",
159 			 CM_PREFIX_REF(req->vdev_id, req->cm_id));
160 		return QDF_STATUS_E_INVAL;
161 	}
162 
163 	rso_cfg = wlan_cm_get_rso_config(vdev);
164 	if (!rso_cfg)
165 		return QDF_STATUS_E_NOSUPPORT;
166 
167 	qdf_mem_zero(&msg, sizeof(msg));
168 	join_req = qdf_mem_malloc(sizeof(*join_req));
169 	if (!join_req)
170 		return QDF_STATUS_E_NOMEM;
171 
172 	wlan_cm_set_disable_hi_rssi(pdev, req->vdev_id, true);
173 	mlme_debug(CM_PREFIX_FMT "Disabling HI_RSSI, AP freq=%d, rssi=%d",
174 		   CM_PREFIX_REF(req->vdev_id, req->cm_id),
175 		   req->bss->entry->channel.chan_freq,
176 		   req->bss->entry->rssi_raw);
177 
178 	if (rso_cfg->assoc_ie.ptr) {
179 		join_req->assoc_ie.ptr = qdf_mem_malloc(rso_cfg->assoc_ie.len);
180 		if (!join_req->assoc_ie.ptr)
181 			return QDF_STATUS_E_NOMEM;
182 		qdf_mem_copy(join_req->assoc_ie.ptr, rso_cfg->assoc_ie.ptr,
183 			     rso_cfg->assoc_ie.len);
184 		join_req->assoc_ie.len = rso_cfg->assoc_ie.len;
185 	}
186 
187 	join_req->entry = util_scan_copy_cache_entry(req->bss->entry);
188 	if (!join_req->entry) {
189 		mlme_err(CM_PREFIX_FMT "Failed to copy scan entry",
190 			 CM_PREFIX_REF(req->vdev_id, req->cm_id));
191 		cm_free_join_req(join_req);
192 		return QDF_STATUS_E_NOMEM;
193 	}
194 	join_req->vdev_id = req->vdev_id;
195 	join_req->cm_id = req->cm_id;
196 
197 	status = cm_csr_handle_join_req(vdev, NULL, join_req, true);
198 	if (QDF_IS_STATUS_ERROR(status)) {
199 		mlme_err(CM_PREFIX_FMT "fail to fill params from legacy",
200 			 CM_PREFIX_REF(req->vdev_id, req->cm_id));
201 		cm_free_join_req(join_req);
202 		return QDF_STATUS_E_FAILURE;
203 	}
204 
205 	wlan_rec_conn_info(req->vdev_id, DEBUG_CONN_CONNECTING,
206 			   req->bss->entry->bssid.bytes,
207 			   req->bss->entry->neg_sec_info.key_mgmt,
208 			   req->bss->entry->channel.chan_freq);
209 
210 	msg.bodyptr = join_req;
211 	msg.type = CM_REASSOC_REQ;
212 	msg.flush_callback = cm_flush_join_req;
213 
214 	status = scheduler_post_message(QDF_MODULE_ID_MLME,
215 					QDF_MODULE_ID_PE,
216 					QDF_MODULE_ID_PE, &msg);
217 	if (QDF_IS_STATUS_ERROR(status)) {
218 		mlme_err(CM_PREFIX_FMT "msg post fail",
219 			 CM_PREFIX_REF(req->vdev_id, req->cm_id));
220 		cm_free_join_req(join_req);
221 	}
222 
223 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
224 		wlan_register_txrx_packetdump(OL_TXRX_PDEV_ID);
225 
226 	return status;
227 }
228 
cm_handle_roam_start(struct wlan_objmgr_vdev * vdev,struct wlan_cm_roam_req * req)229 QDF_STATUS cm_handle_roam_start(struct wlan_objmgr_vdev *vdev,
230 				struct wlan_cm_roam_req *req)
231 {
232 	if (!vdev || !req) {
233 		mlme_err("vdev or req is NULL");
234 		return QDF_STATUS_E_INVAL;
235 	}
236 
237 	if (req->source == CM_ROAMING_HOST)
238 		cm_roam_state_change(wlan_vdev_get_pdev(vdev),
239 				     wlan_vdev_get_id(vdev),
240 				     WLAN_ROAM_RSO_STOPPED,
241 				     REASON_OS_REQUESTED_ROAMING_NOW,
242 				     NULL, false);
243 	return QDF_STATUS_SUCCESS;
244 }
245 
246