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