1  /*
2   * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3   *
4   * Permission to use, copy, modify, and/or distribute this software for any
5   * purpose with or without fee is hereby granted, provided that the above
6   * copyright notice and this permission notice appear in all copies.
7   *
8   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15   */
16  
17  #include "qdf_types.h"
18  #include <net/cfg80211.h>
19  #include "wlan_cfg80211.h"
20  #include "wlan_objmgr_psoc_obj.h"
21  #include "wlan_objmgr_pdev_obj.h"
22  #include "wlan_objmgr_vdev_obj.h"
23  #include "os_if_dp_local_pkt_capture.h"
24  #include "wlan_dp_ucfg_api.h"
25  #include "wlan_dp_main.h"
26  #include "cdp_txrx_mon.h"
27  #include "wlan_policy_mgr_api.h"
28  #include <ol_defines.h>
29  #include "wlan_osif_priv.h"
30  
31  /* Short name for QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE command */
32  #define SET_MONITOR_MODE_CONFIG_MAX \
33  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX
34  #define SET_MONITOR_MODE_INVALID \
35  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID
36  #define SET_MONITOR_MODE_DATA_TX_FRAME_TYPE \
37  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE
38  #define SET_MONITOR_MODE_DATA_RX_FRAME_TYPE \
39  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE
40  #define SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE \
41  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE
42  #define SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE \
43  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE
44  #define SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE \
45  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE
46  #define SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE \
47  	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE
48  
49  /* Short name for QCA_NL80211_VENDOR_SUBCMD_GET_MONITOR_MODE command */
50  #define GET_MONITOR_MODE_CONFIG_MAX \
51  	QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_MAX
52  #define GET_MONITOR_MODE_INVALID \
53  	QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_INVALID
54  #define GET_MONITOR_MODE_STATUS \
55  	QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_STATUS
56  
57  #define MGMT_FRAME_TYPE    0
58  #define DATA_FRAME_TYPE    1
59  #define CTRL_FRAME_TYPE    2
60  
61  const struct nla_policy
62  set_monitor_mode_policy[SET_MONITOR_MODE_CONFIG_MAX + 1] = {
63  	[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] = { .type = NLA_U32 },
64  	[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] = { .type = NLA_U32 },
65  	[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] = { .type = NLA_U32 },
66  	[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] = { .type = NLA_U32 },
67  	[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] = { .type = NLA_U32 },
68  	[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] = { .type = NLA_U32 },
69  };
70  
71  static
os_if_local_pkt_capture_concurrency_allowed(struct wlan_objmgr_psoc * psoc)72  bool os_if_local_pkt_capture_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
73  {
74  	uint32_t num_connections, sta_count;
75  
76  	num_connections = policy_mgr_get_connection_count(psoc);
77  	osif_debug("Total connections %d", num_connections);
78  
79  	/*
80  	 * No connections, local packet capture is allowed
81  	 * Only 1 connection and its STA, then local packet capture is allowed
82  	 * 2+ port concurrency, local packet capture is not allowed
83  	 */
84  	if (!num_connections)
85  		return true;
86  
87  	if (num_connections > 1)
88  		return false;
89  
90  	sta_count = policy_mgr_mode_specific_connection_count(psoc,
91  							      PM_STA_MODE,
92  							      NULL);
93  	osif_debug("sta_count %d", sta_count);
94  	if (sta_count == 1)
95  		return true;
96  
97  	return false;
98  }
99  
os_if_lpc_mon_intf_creation_allowed(struct wlan_objmgr_psoc * psoc)100  bool os_if_lpc_mon_intf_creation_allowed(struct wlan_objmgr_psoc *psoc)
101  {
102  	if (ucfg_dp_is_local_pkt_capture_enabled(psoc)) {
103  		if (policy_mgr_is_mlo_sta_present(psoc)) {
104  			osif_err("MLO STA present, lpc interface creation not allowed");
105  			return false;
106  		}
107  
108  		if (!os_if_local_pkt_capture_concurrency_allowed(psoc)) {
109  			osif_err("Concurrency check failed, lpc interface creation not allowed");
110  			return false;
111  		}
112  	}
113  
114  	return true;
115  }
116  
os_if_start_capture_allowed(struct wlan_objmgr_vdev * vdev)117  static QDF_STATUS os_if_start_capture_allowed(struct wlan_objmgr_vdev *vdev)
118  {
119  	enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev);
120  	struct wlan_objmgr_psoc *psoc;
121  
122  	psoc = wlan_vdev_get_psoc(vdev);
123  	if (!psoc) {
124  		osif_err("NULL psoc");
125  		return QDF_STATUS_E_INVAL;
126  	}
127  
128  	if (!ucfg_dp_is_local_pkt_capture_enabled(psoc)) {
129  		osif_warn("local pkt capture feature not enabled");
130  		return QDF_STATUS_E_NOSUPPORT;
131  	}
132  
133  	if (mode != QDF_MONITOR_MODE) {
134  		osif_err("Operation not permitted in mode: %d", mode);
135  		return QDF_STATUS_E_PERM;
136  	}
137  
138  	/*
139  	 * Whether STA interface is present or not, is already checked
140  	 * while creating monitor interface
141  	 */
142  
143  	if (policy_mgr_is_mlo_sta_present(psoc)) {
144  		osif_err("MLO STA present, start capture is not permitted");
145  		return QDF_STATUS_E_PERM;
146  	}
147  
148  	if (!os_if_local_pkt_capture_concurrency_allowed(psoc)) {
149  		osif_err("Concurrency check failed, start capture not allowed");
150  		return QDF_STATUS_E_PERM;
151  	}
152  
153  	return QDF_STATUS_SUCCESS;
154  }
155  
os_if_stop_capture_allowed(struct wlan_objmgr_vdev * vdev)156  static QDF_STATUS os_if_stop_capture_allowed(struct wlan_objmgr_vdev *vdev)
157  {
158  	enum QDF_OPMODE mode;
159  	struct wlan_objmgr_psoc *psoc;
160  	void *soc;
161  
162  	soc = cds_get_context(QDF_MODULE_ID_SOC);
163  	if (!soc)
164  		return QDF_STATUS_E_INVAL;
165  
166  	psoc = wlan_vdev_get_psoc(vdev);
167  	if (!psoc) {
168  		osif_err("NULL psoc");
169  		return QDF_STATUS_E_INVAL;
170  	}
171  
172  	mode = wlan_vdev_mlme_get_opmode(vdev);
173  	if (mode != QDF_MONITOR_MODE) {
174  		osif_warn("Operation not permitted in mode: %d", mode);
175  		return QDF_STATUS_E_PERM;
176  	}
177  
178  	if (!ucfg_dp_is_local_pkt_capture_enabled(psoc)) {
179  		osif_err("local pkt capture feature not enabled");
180  		return QDF_STATUS_E_NOSUPPORT;
181  	}
182  
183  	if (!cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID)) {
184  		osif_debug("local pkt capture not running, no need to stop");
185  		return QDF_STATUS_E_PERM;
186  	}
187  
188  	return QDF_STATUS_SUCCESS;
189  }
190  
191  static
os_if_dp_local_pkt_capture_start(struct wlan_objmgr_vdev * vdev,struct nlattr ** tb)192  QDF_STATUS os_if_dp_local_pkt_capture_start(struct wlan_objmgr_vdev *vdev,
193  					    struct nlattr **tb)
194  {
195  	QDF_STATUS status;
196  	struct cdp_monitor_filter filter = {0};
197  	uint32_t pkt_type = 0, val;
198  	void *soc;
199  
200  	status = os_if_start_capture_allowed(vdev);
201  	if (QDF_IS_STATUS_ERROR(status))
202  		goto error;
203  
204  	soc = cds_get_context(QDF_MODULE_ID_SOC);
205  	if (!soc)
206  		return QDF_STATUS_E_INVAL;
207  
208  	if (tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]) {
209  		val = nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]);
210  
211  		if (val != QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL) {
212  			osif_err("Invalid value: %d Expected: %d",
213  				val,
214  				QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL);
215  			status = QDF_STATUS_E_INVAL;
216  			goto error;
217  		}
218  		pkt_type |= BIT(MGMT_FRAME_TYPE);
219  	}
220  
221  	if (tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]) {
222  		val = nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]);
223  
224  		if (val != QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL) {
225  			osif_err("Invalid value: %d Expected: %d",
226  				val,
227  				QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL);
228  			status = QDF_STATUS_E_INVAL;
229  			goto error;
230  		}
231  		pkt_type |= BIT(MGMT_FRAME_TYPE);
232  	}
233  
234  	if (tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]) {
235  		val = nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]);
236  
237  		if (val != QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL) {
238  			osif_err("Invalid value: %d Expected: %d",
239  				val,
240  				QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL);
241  			status = QDF_STATUS_E_INVAL;
242  			goto error;
243  		}
244  		pkt_type |= BIT(DATA_FRAME_TYPE);
245  	}
246  
247  	if (tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]) {
248  		val = nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]);
249  
250  		if (val != QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL) {
251  			osif_err("Invalid value: %d Expected: %d",
252  				val,
253  				QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL);
254  			status = QDF_STATUS_E_INVAL;
255  			goto error;
256  		}
257  		pkt_type |= BIT(DATA_FRAME_TYPE);
258  	}
259  
260  	if (tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]) {
261  		val = nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]);
262  
263  		if (val != QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL) {
264  			osif_err("Invalid value: %d Expected: %d",
265  				val,
266  				QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL);
267  			status = QDF_STATUS_E_INVAL;
268  			goto error;
269  		}
270  		pkt_type |= BIT(CTRL_FRAME_TYPE);
271  	}
272  
273  	if (tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]) {
274  		val = nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]);
275  
276  		if (val != QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL) {
277  			osif_err("Invalid value: %d Expected: %d",
278  				val,
279  				QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL);
280  			status = QDF_STATUS_E_INVAL;
281  			goto error;
282  		}
283  		pkt_type |= BIT(CTRL_FRAME_TYPE);
284  	}
285  
286  	if (pkt_type == 0) {
287  		osif_err("Invalid config, pkt_type: %d", pkt_type);
288  		status = QDF_STATUS_E_INVAL;
289  		goto error;
290  	}
291  	osif_debug("start capture config pkt_type:0x%x", pkt_type);
292  
293  	filter.mode = MON_FILTER_PASS;
294  	filter.fp_mgmt = pkt_type & BIT(MGMT_FRAME_TYPE) ? FILTER_MGMT_ALL : 0;
295  	filter.fp_data = pkt_type & BIT(DATA_FRAME_TYPE) ? FILTER_DATA_ALL : 0;
296  	filter.fp_ctrl = pkt_type & BIT(CTRL_FRAME_TYPE) ? FILTER_CTRL_ALL : 0;
297  
298  	status = cdp_start_local_pkt_capture(soc, OL_TXRX_PDEV_ID, &filter);
299  
300  error:
301  	return status;
302  }
303  
os_if_dp_set_lpc_configure(struct wlan_objmgr_vdev * vdev,const void * data,int data_len)304  QDF_STATUS os_if_dp_set_lpc_configure(struct wlan_objmgr_vdev *vdev,
305  				      const void *data, int data_len)
306  {
307  	struct nlattr *tb[SET_MONITOR_MODE_CONFIG_MAX + 1];
308  	QDF_STATUS status = QDF_STATUS_SUCCESS;
309  
310  	if (wlan_cfg80211_nla_parse(tb, SET_MONITOR_MODE_CONFIG_MAX,
311  				    data, data_len, set_monitor_mode_policy)) {
312  		osif_err("Invalid monitor attr");
313  		status = QDF_STATUS_E_INVAL;
314  		goto error;
315  	}
316  
317  	status = os_if_dp_local_pkt_capture_start(vdev, tb);
318  
319  error:
320  	return status;
321  }
322  
os_if_dp_local_pkt_capture_stop(struct wlan_objmgr_vdev * vdev)323  QDF_STATUS os_if_dp_local_pkt_capture_stop(struct wlan_objmgr_vdev *vdev)
324  {
325  	QDF_STATUS status;
326  	void *soc;
327  
328  	soc = cds_get_context(QDF_MODULE_ID_SOC);
329  	if (!soc || !vdev)
330  		return QDF_STATUS_E_INVAL;
331  
332  	status = os_if_stop_capture_allowed(vdev);
333  	if (QDF_IS_STATUS_ERROR(status))
334  		return status;
335  
336  	return cdp_stop_local_pkt_capture(soc, OL_TXRX_PDEV_ID);
337  }
338  
os_if_dp_get_lpc_state(struct wlan_objmgr_vdev * vdev,const void * data,int data_len)339  QDF_STATUS os_if_dp_get_lpc_state(struct wlan_objmgr_vdev *vdev,
340  				  const void *data, int data_len)
341  {
342  	struct wlan_objmgr_psoc *psoc;
343  	struct vdev_osif_priv *osif_priv;
344  	struct sk_buff *reply_skb;
345  	uint32_t skb_len = NLMSG_HDRLEN, val;
346  	QDF_STATUS status = QDF_STATUS_SUCCESS;
347  	struct wireless_dev *wdev;
348  	bool running;
349  	void *soc;
350  
351  	psoc = wlan_vdev_get_psoc(vdev);
352  	if (!psoc)
353  		return QDF_STATUS_E_INVAL;
354  
355  	osif_priv = wlan_vdev_get_ospriv(vdev);
356  	if (!osif_priv) {
357  		osif_err("osif_priv is null");
358  		return QDF_STATUS_E_INVAL;
359  	}
360  
361  	wdev = osif_priv->wdev;
362  	if (!wdev) {
363  		osif_err("wireless dev is null");
364  		return QDF_STATUS_E_INVAL;
365  	}
366  
367  	soc = cds_get_context(QDF_MODULE_ID_SOC);
368  	if (!soc)
369  		return QDF_STATUS_E_INVAL;
370  
371  	/* Length of attribute QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_STATUS */
372  	skb_len += nla_total_size(sizeof(u32));
373  
374  	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wdev->wiphy,
375  							     skb_len);
376  	if (!reply_skb) {
377  		osif_err("alloc reply skb failed");
378  		return QDF_STATUS_E_NOMEM;
379  	}
380  
381  	running = cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID);
382  	val = running ? QCA_WLAN_VENDOR_MONITOR_MODE_CAPTURE_RUNNING :
383  			QCA_WLAN_VENDOR_MONITOR_MODE_NO_CAPTURE_RUNNING;
384  
385  	if (nla_put_u32(reply_skb, GET_MONITOR_MODE_STATUS, val)) {
386  		osif_err("nla put failed");
387  		status = QDF_STATUS_E_INVAL;
388  		goto fail;
389  	}
390  
391  	if (wlan_cfg80211_vendor_cmd_reply(reply_skb))
392  		status = QDF_STATUS_E_INVAL;
393  
394  	return status;
395  fail:
396  	wlan_cfg80211_vendor_free_skb(reply_skb);
397  	return status;
398  }
399  
400