1  /*
2   * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4   *
5   * Permission to use, copy, modify, and/or distribute this software for
6   * any purpose with or without fee is hereby granted, provided that the
7   * above copyright notice and this permission notice appear in all
8   * copies.
9   *
10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17   * PERFORMANCE OF THIS SOFTWARE.
18   */
19  
20  #include "osif_sync.h"
21  #include "qdf_str.h"
22  #include "qdf_trace.h"
23  #include "qdf_types.h"
24  #include "wlan_osif_priv.h"
25  #include <net/cfg80211.h>
26  #include "wlan_cfg80211.h"
27  #include "wlan_objmgr_psoc_obj.h"
28  #include "wlan_objmgr_pdev_obj.h"
29  #include "wlan_objmgr_vdev_obj.h"
30  #include "wlan_utility.h"
31  #include "wlan_osif_request_manager.h"
32  #include "wlan_mlme_ucfg_api.h"
33  #include "wlan_pkt_capture_ucfg_api.h"
34  #include "os_if_pkt_capture.h"
35  #include "wlan_hdd_main.h"
36  #include "cfg_ucfg_api.h"
37  #include "wlan_hdd_object_manager.h"
38  
39  #ifdef WLAN_FEATURE_PKT_CAPTURE
40  
41  const struct nla_policy
42  set_monitor_mode_policy[SET_MONITOR_MODE_CONFIG_MAX + 1] = {
43  	[SET_MONITOR_MODE_INVALID] = {
44  		.type = NLA_U32
45  	},
46  	[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] = {
47  		.type = NLA_U32
48  	},
49  	[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] = {
50  		.type = NLA_U32
51  	},
52  	[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] = {
53  		.type = NLA_U32
54  	},
55  	[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] = {
56  		.type = NLA_U32
57  	},
58  	[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] = {
59  		.type = NLA_U32
60  	},
61  	[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] = {
62  		.type = NLA_U32
63  	},
64  	[SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL] = {
65  		.type = NLA_U32
66  	},
67  };
68  
os_if_monitor_mode_configure(struct hdd_adapter * adapter,const void * data,int data_len)69  QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter,
70  					const void *data, int data_len)
71  {
72  	struct pkt_capture_frame_filter frame_filter = {0};
73  	struct wlan_objmgr_vdev *vdev;
74  	struct nlattr *tb[SET_MONITOR_MODE_CONFIG_MAX + 1];
75  	QDF_STATUS status;
76  
77  	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
78  					   WLAN_PKT_CAPTURE_ID);
79  	if (!vdev)
80  		return QDF_STATUS_E_INVAL;
81  
82  	if (wlan_cfg80211_nla_parse(tb, SET_MONITOR_MODE_CONFIG_MAX,
83  				    data, data_len, set_monitor_mode_policy)) {
84  		osif_err("invalid monitor attr");
85  		hdd_objmgr_put_vdev_by_user(vdev, WLAN_PKT_CAPTURE_ID);
86  		return QDF_STATUS_E_INVAL;
87  	}
88  
89  	if (tb[SET_MONITOR_MODE_INVALID]) {
90  		hdd_objmgr_put_vdev_by_user(vdev, WLAN_PKT_CAPTURE_ID);
91  		return QDF_STATUS_E_FAILURE;
92  	}
93  
94  	if (tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] &&
95  	    nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]) <
96  	    PACKET_CAPTURE_DATA_MAX_FILTER) {
97  		frame_filter.data_tx_frame_filter =
98  			nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]);
99  		frame_filter.vendor_attr_to_set =
100  			BIT(SET_MONITOR_MODE_DATA_TX_FRAME_TYPE);
101  	}
102  
103  	if (tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] &&
104  	    nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]) <
105  	    PACKET_CAPTURE_DATA_MAX_FILTER) {
106  		frame_filter.data_rx_frame_filter =
107  			nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]);
108  		frame_filter.vendor_attr_to_set |=
109  			BIT(SET_MONITOR_MODE_DATA_RX_FRAME_TYPE);
110  	}
111  
112  	if (tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] &&
113  	    nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]) <
114  	    PACKET_CAPTURE_MGMT_MAX_FILTER) {
115  		frame_filter.mgmt_tx_frame_filter =
116  			nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]);
117  		frame_filter.vendor_attr_to_set |=
118  			BIT(SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE);
119  	}
120  
121  	if (tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] &&
122  	    nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]) <
123  	    PACKET_CAPTURE_MGMT_MAX_FILTER) {
124  		frame_filter.mgmt_rx_frame_filter =
125  			nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]);
126  		frame_filter.vendor_attr_to_set |=
127  			BIT(SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE);
128  	}
129  
130  	if (tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] &&
131  	    nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]) <
132  	    PACKET_CAPTURE_CTRL_MAX_FILTER) {
133  		frame_filter.ctrl_tx_frame_filter =
134  			nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]);
135  		frame_filter.vendor_attr_to_set |=
136  			BIT(SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE);
137  	}
138  
139  	if (tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] &&
140  	    nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]) <
141  	    PACKET_CAPTURE_CTRL_MAX_FILTER) {
142  		frame_filter.ctrl_rx_frame_filter =
143  			nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]);
144  		frame_filter.vendor_attr_to_set |=
145  			BIT(SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE);
146  	}
147  
148  	if (tb[SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL]) {
149  		frame_filter.connected_beacon_interval =
150  		nla_get_u32(tb[SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL]);
151  		frame_filter.vendor_attr_to_set |=
152  			BIT(SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL);
153  	}
154  
155  	osif_debug("Monitor mode config data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d bi %d\n",
156  		   frame_filter.data_tx_frame_filter,
157  		   frame_filter.data_rx_frame_filter,
158  		   frame_filter.mgmt_tx_frame_filter,
159  		   frame_filter.mgmt_rx_frame_filter,
160  		   frame_filter.ctrl_tx_frame_filter,
161  		   frame_filter.ctrl_rx_frame_filter,
162  		   frame_filter.connected_beacon_interval);
163  
164  	status = ucfg_pkt_capture_set_filter(frame_filter, vdev);
165  	hdd_objmgr_put_vdev_by_user(vdev, WLAN_PKT_CAPTURE_ID);
166  
167  	return status;
168  }
169  
170  #undef SET_MONITOR_MODE_CONFIG_MAX
171  #undef SET_MONITOR_MODE_INVALID
172  #undef SET_MONITOR_MODE_DATA_TX_FRAME_TYPE
173  #undef SET_MONITOR_MODE_DATA_RX_FRAME_TYPE
174  #undef SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE
175  #undef SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE
176  #undef SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE
177  #undef SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE
178  #undef SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL
179  
180  #endif
181