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