xref: /wlan-dirver/utils/sigma-dut/sniffer.c (revision 69b367b932f3e8e6f908f0c88bac10014c487f1e)
1 /*
2  * Sigma Control API DUT (sniffer)
3  * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
4  * Copyright (c) 2019, The Linux Foundation
5  * All Rights Reserved.
6  * Licensed under the Clear BSD license. See README for more details.
7  */
8 
9 #include "sigma_dut.h"
10 #include <signal.h>
11 #include <sys/stat.h>
12 #include <sys/wait.h>
13 
14 
capture_process(const char * ifname,const char * filename)15 static void capture_process(const char *ifname, const char *filename)
16 {
17 	char *env[] = { NULL };
18 	char *argv[] = { "sigma_dut[capture]", "-i", strdup(ifname),
19 			 "-w", strdup(filename), NULL };
20 	execve("/usr/bin/dumpcap", argv, env);
21 	perror("execve");
22 	exit(EXIT_FAILURE);
23 }
24 
25 
cmd_sniffer_control_start(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)26 static enum sigma_cmd_result cmd_sniffer_control_start(struct sigma_dut *dut,
27 						       struct sigma_conn *conn,
28 						       struct sigma_cmd *cmd)
29 {
30 	const char *filename = get_param(cmd, "filename");
31 	enum sigma_cmd_result res;
32 	pid_t pid;
33 
34 	if (dut->sniffer_pid) {
35 		sigma_dut_print(dut, DUT_MSG_INFO, "Sniffer was already capturing - restart based on new parameters");
36 		sniffer_close(dut);
37 	}
38 
39 	if (filename == NULL) {
40 		send_resp(dut, conn, SIGMA_ERROR,
41 			  "errorCode,Missing filename argument");
42 		return STATUS_SENT;
43 	}
44 	if (strchr(filename, '/')) {
45 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Invalid filename");
46 		return STATUS_SENT;
47 	}
48 
49 	res = cmd_wlantest_set_channel(dut, conn, cmd);
50 	if (res != SUCCESS_SEND_STATUS)
51 		return res;
52 
53 	mkdir("Captures", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
54 
55 	sigma_dut_print(dut, DUT_MSG_INFO, "Starting sniffer process");
56 	snprintf(dut->sniffer_filename, sizeof(dut->sniffer_filename),
57 		 "Captures/%s", filename);
58 	pid = fork();
59 	if (pid < 0) {
60 		send_resp(dut, conn, SIGMA_ERROR,
61 			  "errorCode,Failed to fork sniffer process");
62 		return STATUS_SENT;
63 	}
64 
65 	if (pid == 0) {
66 		capture_process(dut->sniffer_ifname, dut->sniffer_filename);
67 		return SUCCESS_SEND_STATUS;
68 	}
69 
70 	dut->sniffer_pid = pid;
71 
72 	return SUCCESS_SEND_STATUS;
73 }
74 
75 
sniffer_close(struct sigma_dut * dut)76 void sniffer_close(struct sigma_dut *dut)
77 {
78 	if (!dut->sniffer_pid)
79 		return;
80 
81 	if (kill(dut->sniffer_pid, SIGTERM) < 0) {
82 		printf("Failed to kill sniffer process: %s\n", strerror(errno));
83 		dut->sniffer_pid = 0;
84 		return;
85 	}
86 	waitpid(dut->sniffer_pid, NULL, 0);
87 
88 	if (dut->sniffer_filename[0]) {
89 		chmod(dut->sniffer_filename,
90 		      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
91 		dut->sniffer_filename[0] = '\0';
92 	}
93 
94 	dut->sniffer_pid = 0;
95 }
96 
97 
cmd_sniffer_control_stop(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)98 static enum sigma_cmd_result cmd_sniffer_control_stop(struct sigma_dut *dut,
99 						      struct sigma_conn *conn,
100 						      struct sigma_cmd *cmd)
101 {
102 	if (!dut->sniffer_pid) {
103 		send_resp(dut, conn, SIGMA_ERROR,
104 			  "errorCode,Sniffer was not capturing");
105 		return STATUS_SENT;
106 	}
107 
108 	sniffer_close(dut);
109 	return SUCCESS_SEND_STATUS;
110 }
111 
112 
113 static enum sigma_cmd_result
cmd_sniffer_control_field_check(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)114 cmd_sniffer_control_field_check(struct sigma_dut *dut, struct sigma_conn *conn,
115 				struct sigma_cmd *cmd)
116 {
117 	const char *filename = get_param(cmd, "filename");
118 	const char *framename = get_param(cmd, "framename");
119 	const char *srcmac = get_param(cmd, "srcmac");
120 	const char *wsc_state = get_param(cmd, "WSC_State");
121 	const char *pvb_bit = get_param(cmd, "pvb_bit");
122 	const char *moredata_bit = get_param(cmd, "MoreData_bit");
123 	const char *eosp_bit = get_param(cmd, "EOSP_bit");
124 	char buf[2000], *pos;
125 	FILE *f;
126 
127 	if (filename == NULL || srcmac == NULL)
128 		return INVALID_SEND_STATUS;
129 
130 	if (strchr(filename, '/')) {
131 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Invalid filename");
132 		return STATUS_SENT;
133 	}
134 
135 	if (!file_exists("sniffer-control-field-check.py")) {
136 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-control-field-check.py not found");
137 		return STATUS_SENT;
138 	}
139 
140 	snprintf(buf, sizeof(buf),
141 		 "./sniffer-control-field-check.py FileName=Captures/%s SrcMac=%s%s%s%s%s%s%s%s%s%s%s",
142 		 filename, srcmac,
143 		 framename ? " FrameName=" : "", framename ? framename : "",
144 		 wsc_state ? " WSC_State=" : "", wsc_state ? wsc_state : "",
145 		 moredata_bit ? " MoreData_bit=" : "",
146 		 moredata_bit ? moredata_bit : "",
147 		 eosp_bit ? " EOSP_bit=" : "", eosp_bit ? eosp_bit : "",
148 		 pvb_bit ? " pvb_bit=" : "", pvb_bit ? pvb_bit : "");
149 	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
150 	f = popen(buf, "r");
151 	if (f == NULL) {
152 		send_resp(dut, conn, SIGMA_ERROR,
153 			  "errorCode,Failed to run sniffer helper");
154 		return STATUS_SENT;
155 	}
156 
157 	if (!fgets(buf, sizeof(buf), f)) {
158 		pclose(f);
159 		send_resp(dut, conn, SIGMA_ERROR,
160 			  "errorCode,Failed extract response from sniffer helper");
161 		return STATUS_SENT;
162 	}
163 	pos = strchr(buf, '\n');
164 	if (pos)
165 		*pos = '\0';
166 
167 	pclose(f);
168 
169 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
170 	return STATUS_SENT;
171 }
172 
173 
cmd_sniffer_get_info(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)174 static enum sigma_cmd_result cmd_sniffer_get_info(struct sigma_dut *dut,
175 						  struct sigma_conn *conn,
176 						  struct sigma_cmd *cmd)
177 {
178 	char buf[200];
179 
180 	snprintf(buf, sizeof(buf), "WfaSnifferVersion,SigmaSniffer-foo,SnifferSTA,foo,DeviceSwInfo,foo,WiresharkVersion,foo");
181 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
182 	return STATUS_SENT;
183 }
184 
185 
186 static enum sigma_cmd_result
cmd_sniffer_control_filter_capture(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)187 cmd_sniffer_control_filter_capture(struct sigma_dut *dut,
188 				   struct sigma_conn *conn,
189 				   struct sigma_cmd *cmd)
190 {
191 	const char *infile = get_param(cmd, "InFile");
192 	const char *outfile = get_param(cmd, "OutFile");
193 	const char *srcmac = get_param(cmd, "SrcMac");
194 	const char *framename = get_param(cmd, "FrameName");
195 	const char *nframes = get_param(cmd, "Nframes");
196 	const char *hasfield = get_param(cmd, "HasField");
197 	const char *datalen = get_param(cmd, "Datalen");
198 	char buf[500], *pos;
199 	FILE *f;
200 
201 	if (infile == NULL || outfile == NULL || srcmac == NULL ||
202 	    nframes == NULL)
203 		return INVALID_SEND_STATUS;
204 
205 	if (strchr(infile, '/') || strchr(outfile, '/'))
206 		return INVALID_SEND_STATUS;
207 
208 	if (!file_exists("sniffer-control-filter-capture.py")) {
209 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-control-filter-capture.py not found");
210 		return STATUS_SENT;
211 	}
212 
213 	snprintf(buf, sizeof(buf),
214 		 "./sniffer-control-filter-capture.py InFile=Captures/%s OutFile=Captures/%s SrcMac=%s%s%s Nframes=%s%s%s%s%s",
215 		 infile, outfile, srcmac,
216 		 framename ? " FrameName=" : "", framename ? framename : "",
217 		 nframes,
218 		 hasfield ? " HasField=" : "", hasfield ? hasfield : "",
219 		 datalen ? " Datalen=" : "", datalen ? datalen : "");
220 	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
221 	f = popen(buf, "r");
222 	if (f == NULL) {
223 		send_resp(dut, conn, SIGMA_ERROR,
224 			  "errorCode,Failed to run sniffer helper");
225 		return STATUS_SENT;
226 	}
227 
228 	if (!fgets(buf, sizeof(buf), f)) {
229 		pclose(f);
230 		send_resp(dut, conn, SIGMA_ERROR,
231 			  "errorCode,Failed extract response from sniffer helper");
232 		return STATUS_SENT;
233 	}
234 	pos = strchr(buf, '\n');
235 	if (pos)
236 		*pos = '\0';
237 
238 	pclose(f);
239 
240 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
241 	return STATUS_SENT;
242 }
243 
244 
245 static enum sigma_cmd_result
cmd_sniffer_get_field_value(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)246 cmd_sniffer_get_field_value(struct sigma_dut *dut, struct sigma_conn *conn,
247 			    struct sigma_cmd *cmd)
248 {
249 	const char *infile = get_param(cmd, "FileName");
250 	const char *srcmac = get_param(cmd, "SrcMac");
251 	const char *framename = get_param(cmd, "FrameName");
252 	const char *fieldname = get_param(cmd, "FieldName");
253 	char buf[500], *pos;
254 	FILE *f;
255 
256 	if (infile == NULL || srcmac == NULL || framename == NULL ||
257 	    fieldname == NULL)
258 		return INVALID_SEND_STATUS;
259 
260 	if (!file_exists("sniffer-get-field-value.py")) {
261 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-get-field-value.py not found");
262 		return STATUS_SENT;
263 	}
264 
265 	snprintf(buf, sizeof(buf),
266 		 "./sniffer-get-field-value.py FileName=Captures/%s SrcMac=%s FrameName=%s FieldName=%s",
267 		 infile, srcmac, framename, fieldname);
268 	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
269 	f = popen(buf, "r");
270 	if (f == NULL) {
271 		send_resp(dut, conn, SIGMA_ERROR,
272 			  "errorCode,Failed to run sniffer helper");
273 		return STATUS_SENT;
274 	}
275 
276 	if (!fgets(buf, sizeof(buf), f)) {
277 		pclose(f);
278 		send_resp(dut, conn, SIGMA_ERROR,
279 			  "errorCode,Failed extract response from sniffer helper");
280 		return STATUS_SENT;
281 	}
282 	pos = strchr(buf, '\n');
283 	if (pos)
284 		*pos = '\0';
285 
286 	pclose(f);
287 
288 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
289 	return STATUS_SENT;
290 }
291 
292 
293 static enum sigma_cmd_result
cmd_sniffer_check_p2p_noa_duration(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)294 cmd_sniffer_check_p2p_noa_duration(struct sigma_dut *dut,
295 				   struct sigma_conn *conn,
296 				   struct sigma_cmd *cmd)
297 {
298 	FILE *f;
299 	char buf[200], *pos;
300 	const char *infile = get_param(cmd, "FileName");
301 	const char *bssid = get_param(cmd, "bssid");
302 	const char *srcmac = get_param(cmd, "srcmac");
303 	const char *destmac = get_param(cmd, "destmac");
304 
305 	if (infile == NULL || bssid == NULL || srcmac == NULL ||
306 	    destmac == NULL)
307 		return INVALID_SEND_STATUS;
308 
309 	if (!file_exists("sniffer-check-p2p-noa-duration.py")) {
310 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-check-p2p-noa-duration.py not found");
311 		return STATUS_SENT;
312 	}
313 
314 	snprintf(buf, sizeof(buf),
315 		 "./sniffer-check-p2p-noa-duration.py Captures/%s %s %s %s",
316 		 infile, bssid, srcmac, destmac);
317 	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
318 	f = popen(buf, "r");
319 	if (f == NULL) {
320 		send_resp(dut, conn, SIGMA_ERROR,
321 			  "errorCode,Failed to run sniffer check");
322 		return STATUS_SENT;
323 	}
324 
325 	if (!fgets(buf, sizeof(buf), f)) {
326 		pclose(f);
327 		send_resp(dut, conn, SIGMA_ERROR,
328 			  "errorCode,Failed extract response from sniffer check");
329 		return STATUS_SENT;
330 	}
331 	pos = strchr(buf, '\n');
332 	if (pos)
333 		*pos = '\0';
334 
335 	pclose(f);
336 
337 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
338 	return STATUS_SENT;
339 }
340 
341 
342 static enum sigma_cmd_result
cmd_sniffer_check_p2p_opps_client(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)343 cmd_sniffer_check_p2p_opps_client(struct sigma_dut *dut,
344 				  struct sigma_conn *conn,
345 				  struct sigma_cmd *cmd)
346 {
347 	char buf[200];
348 
349 	/* TODO */
350 	snprintf(buf, sizeof(buf), "FilterStatus,SUCCESS");
351 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
352 	return STATUS_SENT;
353 }
354 
355 
356 static enum sigma_cmd_result
cmd_sniffer_check_frame_field(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)357 cmd_sniffer_check_frame_field(struct sigma_dut *dut,
358 			      struct sigma_conn *conn,
359 			      struct sigma_cmd *cmd)
360 {
361 	char buf[200];
362 
363 	/* TODO */
364 	snprintf(buf, sizeof(buf), "FilterStatus,SUCCESS");
365 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
366 	return STATUS_SENT;
367 }
368 
369 
sniffer_register_cmds(void)370 void sniffer_register_cmds(void)
371 {
372 	sigma_dut_reg_cmd("sniffer_control_start", NULL,
373 			  cmd_sniffer_control_start);
374 	sigma_dut_reg_cmd("sniffer_control_stop", NULL,
375 			  cmd_sniffer_control_stop);
376 	sigma_dut_reg_cmd("sniffer_control_field_check", NULL,
377 			  cmd_sniffer_control_field_check);
378 	sigma_dut_reg_cmd("sniffer_get_info", NULL, cmd_sniffer_get_info);
379 	sigma_dut_reg_cmd("sniffer_control_filter_capture", NULL,
380 			  cmd_sniffer_control_filter_capture);
381 	sigma_dut_reg_cmd("wfa_sniffer_control_filter_capture", NULL,
382 			  cmd_sniffer_control_filter_capture);
383 	sigma_dut_reg_cmd("sniffer_get_field_value", NULL,
384 			  cmd_sniffer_get_field_value);
385 	sigma_dut_reg_cmd("sniffer_check_p2p_NoA_duration", NULL,
386 			  cmd_sniffer_check_p2p_noa_duration);
387 	sigma_dut_reg_cmd("sniffer_check_p2p_opps_client", NULL,
388 			  cmd_sniffer_check_p2p_opps_client);
389 	sigma_dut_reg_cmd("sniffer_check_frame_field", NULL,
390 			  cmd_sniffer_check_frame_field);
391 }
392