1 /*
2 * Sigma Control API DUT (station/AP/sniffer)
3 * Copyright (c) 2011-2013, 2017, Qualcomm Atheros, Inc.
4 * Copyright (c) 2018-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 <ctype.h>
11 #include "miracast.h"
12 #include <sys/wait.h>
13 #include "wpa_ctrl.h"
14 #include "wpa_helpers.h"
15
16
17 extern char *sigma_cert_path;
18
19
cmd_dev_send_frame(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)20 static enum sigma_cmd_result cmd_dev_send_frame(struct sigma_dut *dut,
21 struct sigma_conn *conn,
22 struct sigma_cmd *cmd)
23 {
24 #ifdef MIRACAST
25 const char *program = get_param(cmd, "Program");
26
27 if (program && (strcasecmp(program, "WFD") == 0 ||
28 strcasecmp(program, "DisplayR2") == 0))
29 return miracast_dev_send_frame(dut, conn, cmd);
30 #endif /* MIRACAST */
31
32 if (dut->mode == SIGMA_MODE_STATION ||
33 dut->mode == SIGMA_MODE_UNKNOWN) {
34 sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
35 "dev_send_frame to sta_send_frame");
36 return cmd_sta_send_frame(dut, conn, cmd);
37 }
38
39 if (dut->mode == SIGMA_MODE_AP) {
40 sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
41 "dev_send_frame to ap_send_frame");
42 return cmd_ap_send_frame(dut, conn, cmd);
43 }
44
45 #ifdef CONFIG_WLANTEST
46 sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert dev_send_frame to "
47 "wlantest_send_frame");
48 return cmd_wlantest_send_frame(dut, conn, cmd);
49 #else /* CONFIG_WLANTEST */
50 send_resp(dut, conn, SIGMA_ERROR,
51 "errorCode,Unsupported dev_send_frame");
52 return STATUS_SENT;
53 #endif /* CONFIG_WLANTEST */
54 }
55
56
cmd_dev_set_parameter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)57 static enum sigma_cmd_result cmd_dev_set_parameter(struct sigma_dut *dut,
58 struct sigma_conn *conn,
59 struct sigma_cmd *cmd)
60 {
61 const char *device = get_param(cmd, "Device");
62
63 if (device && strcasecmp(device, "STA") == 0) {
64 sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
65 "dev_set_parameter to sta_set_parameter");
66 return cmd_sta_set_parameter(dut, conn, cmd);
67 }
68
69 return INVALID_SEND_STATUS;
70 }
71
72
sta_server_cert_trust(struct sigma_dut * dut,struct sigma_conn * conn,const char * val)73 static enum sigma_cmd_result sta_server_cert_trust(struct sigma_dut *dut,
74 struct sigma_conn *conn,
75 const char *val)
76 {
77 char buf[200];
78 struct wpa_ctrl *ctrl = NULL;
79 int e;
80 char resp[200];
81 int num_disconnected = 0;
82 int tod = -1;
83
84 strlcpy(resp, "ServerCertTrustResult,Accepted", sizeof(resp));
85
86 if (strcasecmp(val, "Accept") != 0 && strcasecmp(val, "Reject") != 0) {
87 sigma_dut_print(dut, DUT_MSG_INFO,
88 "Unknown ServerCertTrust value '%s'", val);
89 return INVALID_SEND_STATUS;
90 }
91
92 snprintf(buf, sizeof(buf), "%s/uosc-disabled", sigma_cert_path);
93 if (file_exists(buf)) {
94 strlcpy(resp,
95 "ServerCertTrustResult,OverrideNotAllowed,Reason,UOSC disabled on device",
96 sizeof(resp));
97 goto done;
98 }
99
100 if (!dut->server_cert_hash[0]) {
101 strlcpy(resp,
102 "ServerCertTrustResult,OverrideNotAllowed,Reason,No server certificate stored",
103 sizeof(resp));
104 goto done;
105 }
106
107 if (dut->sta_tod_policy) {
108 strlcpy(resp,
109 "ServerCertTrustResult,OverrideNotAllowed,Reason,TOD policy",
110 sizeof(resp));
111 goto done;
112 }
113
114 if (dut->server_cert_tod == 1) {
115 strlcpy(resp,
116 "ServerCertTrustResult,OverrideNotAllowed,Reason,TOD-STRICT policy in received server certificate",
117 sizeof(resp));
118 goto done;
119 }
120
121 if (strcasecmp(val, "Accept") != 0) {
122 strlcpy(resp, "ServerCertTrustResult,Rejected", sizeof(resp));
123 goto done;
124 }
125
126 snprintf(buf, sizeof(buf), "hash://server/sha256/%s",
127 dut->server_cert_hash);
128 if (set_network_quoted(get_station_ifname(dut), dut->infra_network_id,
129 "ca_cert", buf) < 0) {
130 strlcpy(resp,
131 "ServerCertTrustResult,OverrideNotAllowed,Reason,Could not configure server certificate hash for the network profile",
132 sizeof(resp));
133 goto done;
134 }
135
136 if (set_network(get_station_ifname(dut), dut->infra_network_id,
137 "domain_match", "NULL") < 0 ||
138 set_network(get_station_ifname(dut), dut->infra_network_id,
139 "domain_suffix_match", "NULL") < 0) {
140 strlcpy(resp,
141 "ServerCertTrustResult,OverrideNotAllowed,Reason,Could not clear domain matching rules",
142 sizeof(resp));
143 goto done;
144 }
145
146 wpa_command(get_station_ifname(dut), "DISCONNECT");
147 snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", dut->infra_network_id);
148 if (wpa_command(get_station_ifname(dut), buf) < 0) {
149 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to select "
150 "network id %d on %s",
151 dut->infra_network_id,
152 get_station_ifname(dut));
153 strlcpy(resp,
154 "ServerCertTrustResult,Accepted,Result,Could not request reconnection",
155 sizeof(resp));
156 goto done;
157 }
158
159 ctrl = open_wpa_mon(get_station_ifname(dut));
160 if (!ctrl)
161 goto done;
162
163 for (e = 0; e < 20; e++) {
164 const char *events[] = {
165 "CTRL-EVENT-EAP-PEER-CERT",
166 "CTRL-EVENT-EAP-TLS-CERT-ERROR",
167 "CTRL-EVENT-DISCONNECTED",
168 "CTRL-EVENT-CONNECTED",
169 NULL
170 };
171 char buf[1024];
172 int res;
173
174 res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
175 if (res < 0) {
176 strlcpy(resp,
177 "ServerCertTrustResult,Accepted,Result,Association did not complete",
178 sizeof(resp));
179 goto done;
180 }
181 sigma_dut_print(dut, DUT_MSG_DEBUG, "Connection event: %s",
182 buf);
183
184
185 if (strstr(buf, "CTRL-EVENT-EAP-PEER-CERT") &&
186 strstr(buf, " depth=0")) {
187 char *pos = strstr(buf, " hash=");
188
189 if (pos) {
190 if (strstr(buf, " tod=1"))
191 tod = 1;
192 else if (strstr(buf, " tod=2"))
193 tod = 2;
194 else
195 tod = 0;
196 sigma_dut_print(dut, DUT_MSG_DEBUG,
197 "Server certificate TOD policy: %d",
198 tod);
199 dut->server_cert_tod = tod;
200 }
201 }
202
203 if (strstr(buf, "CTRL-EVENT-EAP-TLS-CERT-ERROR")) {
204 strlcpy(resp,
205 "ServerCertTrustResult,Accepted,Result,TLS server certificate validation failed with updated profile",
206 sizeof(resp));
207 goto done;
208 }
209
210 if (strstr(buf, "CTRL-EVENT-DISCONNECTED")) {
211 num_disconnected++;
212
213 if (num_disconnected > 2) {
214 strlcpy(resp,
215 "ServerCertTrustResult,Accepted,Result,Connection failed",
216 sizeof(resp));
217 goto done;
218 }
219 }
220
221 if (strstr(buf, "CTRL-EVENT-CONNECTED")) {
222 if (tod >= 0) {
223 sigma_dut_print(dut, DUT_MSG_DEBUG,
224 "Network profile TOD policy update: %d -> %d",
225 dut->sta_tod_policy, tod);
226 dut->sta_tod_policy = tod;
227 }
228 strlcpy(resp,
229 "ServerCertTrustResult,Accepted,Result,Connected",
230 sizeof(resp));
231 break;
232 }
233 }
234
235 done:
236 if (ctrl) {
237 wpa_ctrl_detach(ctrl);
238 wpa_ctrl_close(ctrl);
239 }
240
241 send_resp(dut, conn, SIGMA_COMPLETE, resp);
242 return STATUS_SENT;
243 }
244
245
dev_exec_key_rotation(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)246 static enum sigma_cmd_result dev_exec_key_rotation(struct sigma_dut *dut,
247 struct sigma_conn *conn,
248 struct sigma_cmd *cmd)
249 {
250 if (dut->mode == SIGMA_MODE_AP ||
251 dut->mode == SIGMA_MODE_UNKNOWN) {
252 const char *ifname;
253
254 ifname = get_hostapd_ifname(dut);
255 if (hapd_command(ifname, "REKEY_GTK") < 0) {
256 send_resp(dut, conn, SIGMA_ERROR,
257 "errorCode,Failed to request hostapd to rekey GTK");
258 return STATUS_SENT_ERROR;
259 }
260 return SUCCESS_SEND_STATUS;
261 } else if (dut->mode == SIGMA_MODE_STATION) {
262 const char *intf = get_param(cmd, "Interface");
263
264 if (!intf)
265 intf = get_main_ifname(dut);
266 if (wpa_command(intf, "KEY_REQUEST 0 0") != 0) {
267 send_resp(dut, conn, SIGMA_ERROR,
268 "errorCode,Failed to request wpa_supplicant to request AP to rekey GTK");
269 return STATUS_SENT_ERROR;
270 }
271 return SUCCESS_SEND_STATUS;
272 } else {
273 send_resp(dut, conn, SIGMA_ERROR,
274 "errorCode,Unsupported mode for KeyRotation,1");
275 return STATUS_SENT_ERROR;
276 }
277 }
278
279
wpa3_dev_exec_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)280 static enum sigma_cmd_result wpa3_dev_exec_action(struct sigma_dut *dut,
281 struct sigma_conn *conn,
282 struct sigma_cmd *cmd)
283 {
284 const char *val;
285 char buf[4000], buf2[100], *pos, *end;
286
287 val = get_param(cmd, "Rejected_DH_Groups");
288 if (val) {
289 val = get_param(cmd, "Dest_MAC");
290 if (!val)
291 return ERROR_SEND_STATUS;
292 snprintf(buf2, sizeof(buf2), "STA %s", val);
293 if (wpa_command_resp(dut->hostapd_ifname, buf2,
294 buf, sizeof(buf)) < 0)
295 return ERROR_SEND_STATUS;
296 pos = buf;
297 while (pos) {
298 if (strncmp(pos, "sae_rejected_groups=", 20) == 0)
299 break;
300 pos = strchr(pos, '\n');
301 if (pos)
302 pos++;
303 }
304 if (pos) {
305 pos += 20;
306 end = strchr(pos, '\n');
307 if (end)
308 *end = '\0';
309 }
310 snprintf(buf2, sizeof(buf2), "DHGroupVerResult,%s",
311 pos ? pos : "");
312 send_resp(dut, conn, SIGMA_COMPLETE, buf2);
313 return STATUS_SENT;
314 }
315
316 val = get_param(cmd, "KeyRotation");
317 if (val && atoi(val) == 1)
318 return dev_exec_key_rotation(dut, conn, cmd);
319
320 return ERROR_SEND_STATUS;
321 }
322
323
cmd_dev_exec_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)324 static enum sigma_cmd_result cmd_dev_exec_action(struct sigma_dut *dut,
325 struct sigma_conn *conn,
326 struct sigma_cmd *cmd)
327 {
328 const char *program = get_param(cmd, "Program");
329 const char *val;
330
331 #ifdef MIRACAST
332 if (program && (strcasecmp(program, "WFD") == 0 ||
333 strcasecmp(program, "DisplayR2") == 0)) {
334 if (get_param(cmd, "interface") == NULL)
335 return INVALID_SEND_STATUS;
336 return miracast_dev_exec_action(dut, conn, cmd);
337 }
338 #endif /* MIRACAST */
339
340 if (program && strcasecmp(program, "DPP") == 0)
341 return dpp_dev_exec_action(dut, conn, cmd);
342
343 val = get_param(cmd, "ServerCertTrust");
344 if (val)
345 return sta_server_cert_trust(dut, conn, val);
346
347 if (program && strcasecmp(program, "WPA3") == 0)
348 return wpa3_dev_exec_action(dut, conn, cmd);
349
350 return ERROR_SEND_STATUS;
351 }
352
353
cmd_dev_configure_ie(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)354 static enum sigma_cmd_result cmd_dev_configure_ie(struct sigma_dut *dut,
355 struct sigma_conn *conn,
356 struct sigma_cmd *cmd)
357 {
358 const char *ie_name = get_param(cmd, "IE_Name");
359 const char *contents = get_param(cmd, "Contents");
360
361 if (!ie_name || !contents)
362 return INVALID_SEND_STATUS;
363
364 if (strcasecmp(ie_name, "RSNE") != 0) {
365 send_resp(dut, conn, SIGMA_ERROR,
366 "errorCode,Unsupported IE_Name value");
367 return STATUS_SENT;
368 }
369
370 free(dut->rsne_override);
371 dut->rsne_override = strdup(contents);
372
373 return dut->rsne_override ? SUCCESS_SEND_STATUS : ERROR_SEND_STATUS;
374 }
375
376
cmd_dev_ble_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)377 static enum sigma_cmd_result cmd_dev_ble_action(struct sigma_dut *dut,
378 struct sigma_conn *conn,
379 struct sigma_cmd *cmd)
380 {
381 #ifdef ANDROID
382 const char *ble_op = get_param(cmd, "BLEOp");
383 const char *prog = get_param(cmd, "Prog");
384 const char *service_name = get_param(cmd, "ServiceName");
385 const char *ble_role = get_param(cmd, "BLERole");
386 const char *discovery_type = get_param(cmd, "DiscoveryType");
387 const char *msg_type = get_param(cmd, "messagetype");
388 const char *action = get_param(cmd, "action");
389 const char *M2Transmit = get_param(cmd, "M2Transmit");
390 char *argv[17];
391 pid_t pid;
392
393 if (prog && ble_role && action && msg_type) {
394 send_resp(dut, conn, SIGMA_COMPLETE,
395 "OrgID,0x00,TransDataHeader,0x00,BloomFilterElement,NULL");
396 return STATUS_SENT;
397 }
398 if (!ble_op || !prog || !service_name || !ble_role || !discovery_type) {
399 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid arguments");
400 return INVALID_SEND_STATUS;
401 }
402
403 if ((strcasecmp(prog, "NAN") != 0)) {
404 sigma_dut_print(dut, DUT_MSG_ERROR, "Program %s not supported",
405 prog);
406 return INVALID_SEND_STATUS;
407 }
408
409 if (strcasecmp(ble_role, "seeker") != 0 &&
410 strcasecmp(ble_role, "provider") != 0 &&
411 strcasecmp(ble_role, "browser") != 0) {
412 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid BLERole: %s",
413 ble_role);
414 return INVALID_SEND_STATUS;
415 }
416
417 if (strcasecmp(discovery_type, "active") != 0 &&
418 strcasecmp(discovery_type, "passive") != 0) {
419 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid DiscoveryType: %s",
420 discovery_type);
421 return INVALID_SEND_STATUS;
422 }
423
424 if (!M2Transmit)
425 M2Transmit = "disable";
426
427 argv[0] = "am";
428 argv[1] = "start";
429 argv[2] = "-n";
430 argv[3] = "org.codeaurora.nanservicediscovery/org.codeaurora.nanservicediscovery.MainActivity";
431 argv[4] = "--es";
432 argv[5] = "service";
433 argv[6] = (char *) service_name;
434 argv[7] = "--es";
435 argv[8] = "role";
436 argv[9] = (char *) ble_role;
437 argv[10] = "--es";
438 argv[11] = "scantype";
439 argv[12] = (char *) discovery_type;
440 argv[13] = "--es";
441 argv[14] = "M2Transmit";
442 argv[15] = (char *) M2Transmit;
443 argv[16] = NULL;
444
445 pid = fork();
446 if (pid == -1) {
447 sigma_dut_print(dut, DUT_MSG_ERROR, "fork: %s",
448 strerror(errno));
449 return ERROR_SEND_STATUS;
450 }
451
452 if (pid == 0) {
453 execv("/system/bin/am", argv);
454 sigma_dut_print(dut, DUT_MSG_ERROR, "execv: %s",
455 strerror(errno));
456 exit(0);
457 return ERROR_SEND_STATUS;
458 }
459
460 dut->nanservicediscoveryinprogress = 1;
461 #endif /* ANDROID */
462
463 return SUCCESS_SEND_STATUS;
464 }
465
466
467 /* Runtime ID must contain only numbers */
is_runtime_id_valid(struct sigma_dut * dut,const char * val)468 static int is_runtime_id_valid(struct sigma_dut *dut, const char *val)
469 {
470 int i;
471
472 for (i = 0; val[i] != '\0'; i++) {
473 if (!isdigit(val[i])) {
474 sigma_dut_print(dut, DUT_MSG_DEBUG,
475 "Invalid Runtime_ID %s", val);
476 return 0;
477 }
478 }
479
480 return 1;
481 }
482
483
build_log_dir(struct sigma_dut * dut,char * dir,size_t dir_size)484 static int build_log_dir(struct sigma_dut *dut, char *dir, size_t dir_size)
485 {
486 int res;
487 const char *vendor = dut->vendor_name;
488 int i;
489
490 if (!vendor)
491 return -1;
492
493 if (dut->log_file_dir) {
494 res = snprintf(dir, dir_size, "%s/%s", dut->log_file_dir,
495 vendor);
496 } else {
497 #ifdef ANDROID
498 res = snprintf(dir, dir_size, "/data/vendor/wifi/%s",
499 vendor);
500 #else /* ANDROID */
501 res = snprintf(dir, dir_size, "/var/log/%s", vendor);
502 #endif /* ANDROID */
503 }
504
505 if (res < 0 || res >= dir_size)
506 return -1;
507
508 /* Check for valid vendor name in log dir path since the log dir
509 * (/var/log/vendor) is deleted in dev_stop routine. This check is to
510 * avoid any unintended file deletion.
511 */
512 for (i = 0; vendor[i] != '\0'; i++) {
513 if (!isalpha(vendor[i])) {
514 sigma_dut_print(dut, DUT_MSG_DEBUG,
515 "Invalid char %c in vendor name %s",
516 vendor[i], vendor);
517 return -1;
518 }
519 }
520
521 return 0;
522 }
523
524
525 /* User has to redirect wpa_supplicant logs to the following file. */
526 #ifndef WPA_SUPPLICANT_LOG_FILE
527 #define WPA_SUPPLICANT_LOG_FILE "/var/log/supplicant_log/wpa_log.txt"
528 #endif /* WPA_SUPPLICANT_LOG_FILE */
529
cmd_dev_start_test(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)530 static enum sigma_cmd_result cmd_dev_start_test(struct sigma_dut *dut,
531 struct sigma_conn *conn,
532 struct sigma_cmd *cmd)
533 {
534 const char *val;
535 char buf[250];
536 char dir[200];
537 FILE *supp_log;
538 int res;
539
540 val = get_param(cmd, "Runtime_ID");
541 if (!(val && is_runtime_id_valid(dut, val)))
542 return INVALID_SEND_STATUS;
543
544 if (!dut->vendor_name) {
545 sigma_dut_print(dut, DUT_MSG_INFO,
546 "Log collection not supported without vendor name specified on the command line (-N)");
547 return SUCCESS_SEND_STATUS;
548 }
549
550 if (build_log_dir(dut, dir, sizeof(dir)) < 0)
551 return ERROR_SEND_STATUS;
552
553 supp_log = fopen(WPA_SUPPLICANT_LOG_FILE, "r");
554 if (!supp_log) {
555 sigma_dut_print(dut, DUT_MSG_ERROR,
556 "Failed to open wpa_log file %s",
557 WPA_SUPPLICANT_LOG_FILE);
558 } else {
559 /* Get the wpa_supplicant log file size */
560 if (fseek(supp_log, 0, SEEK_END))
561 sigma_dut_print(dut, DUT_MSG_ERROR,
562 "Failed to get file size for read");
563 else
564 dut->wpa_log_size = ftell(supp_log);
565
566 fclose(supp_log);
567 }
568
569 strlcpy(dut->dev_start_test_runtime_id, val,
570 sizeof(dut->dev_start_test_runtime_id));
571 sigma_dut_print(dut, DUT_MSG_DEBUG, "Runtime_ID %s",
572 dut->dev_start_test_runtime_id);
573
574 run_system_wrapper(dut, "rm -rf %s", dir);
575 run_system_wrapper(dut, "mkdir -p %s", dir);
576
577 #ifdef ANDROID
578 run_system_wrapper(dut, "logcat -v time > %s/logcat_%s.txt &",
579 dir, dut->dev_start_test_runtime_id);
580 #else /* ANDROID */
581 /* Open log file for sigma_dut logs. This is not needed for Android, as
582 * we are already collecting logcat. */
583 res = snprintf(buf, sizeof(buf), "%s/sigma_%s.txt", dir,
584 dut->dev_start_test_runtime_id);
585 if (res >= 0 && res < sizeof(buf)) {
586 if (dut->log_file_fd)
587 fclose(dut->log_file_fd);
588
589 dut->log_file_fd = fopen(buf, "a");
590 if (!dut->log_file_fd)
591 sigma_dut_print(dut, DUT_MSG_ERROR,
592 "Failed to create sigma_dut log %s",
593 buf);
594 }
595
596 run_system_wrapper(dut, "killall -9 cnss_diag_lite");
597 run_system_wrapper(dut,
598 "cnss_diag_lite -c -x 31 > %s/cnss_diag_id_%s.txt &",
599 dir, dut->dev_start_test_runtime_id);
600 #endif /* ANDROID */
601
602 return SUCCESS_SEND_STATUS;
603 }
604
605
is_allowed_char(char ch)606 static int is_allowed_char(char ch)
607 {
608 return strchr("./-_", ch) != NULL;
609 }
610
611
is_destpath_valid(struct sigma_dut * dut,const char * val)612 static int is_destpath_valid(struct sigma_dut *dut, const char *val)
613 {
614 int i;
615
616 for (i = 0; val[i] != '\0'; i++) {
617 if (!(isalnum(val[i]) || is_allowed_char(val[i]))) {
618 sigma_dut_print(dut, DUT_MSG_DEBUG,
619 "Invalid char %c in destpath %s",
620 val[i], val);
621 return 0;
622 }
623 }
624
625 return 1;
626 }
627
628
629 #ifndef ANDROID
630 #define SUPP_LOG_BUFF_SIZE 4 * 1024
631
save_supplicant_log(struct sigma_dut * dut)632 static int save_supplicant_log(struct sigma_dut *dut)
633 {
634 char dir[200];
635 char buf[300];
636 FILE *wpa_log = NULL;
637 FILE *supp_log;
638 char *buff_ptr = NULL;
639 unsigned int file_size;
640 unsigned int file_size_orig;
641 int status = -1, res;
642
643 if (build_log_dir(dut, dir, sizeof(dir)) < 0)
644 return -1;
645
646 res = snprintf(buf, sizeof(buf), "%s/wpa_supplicant_log_%s.txt", dir,
647 dut->dev_start_test_runtime_id);
648 if (res < 0 || res >= sizeof(buf))
649 return -1;
650
651 supp_log = fopen(WPA_SUPPLICANT_LOG_FILE, "r");
652 if (!supp_log) {
653 sigma_dut_print(dut, DUT_MSG_ERROR,
654 "Failed to open wpa_log file %s",
655 WPA_SUPPLICANT_LOG_FILE);
656 return -1;
657 }
658
659 /* Get the wpa_supplicant log file size */
660 if (fseek(supp_log, 0, SEEK_END)) {
661 sigma_dut_print(dut, DUT_MSG_ERROR,
662 "Failed to get file size for read");
663 goto exit;
664 }
665 file_size_orig = ftell(supp_log);
666
667 if (file_size_orig < dut->wpa_log_size) {
668 sigma_dut_print(dut, DUT_MSG_ERROR,
669 "file size err, new size %u, old size %u",
670 file_size_orig, dut->wpa_log_size);
671 goto exit;
672 }
673
674 /* Get the wpa_supplicant file size for current test */
675 file_size = file_size_orig - dut->wpa_log_size;
676
677 wpa_log = fopen(buf, "w");
678 if (!wpa_log) {
679 sigma_dut_print(dut, DUT_MSG_ERROR,
680 "Failed to create tmp wpa_log file %s", buf);
681 goto exit;
682 }
683
684 if (fseek(supp_log, dut->wpa_log_size, SEEK_SET)) {
685 sigma_dut_print(dut, DUT_MSG_ERROR,
686 "Failed to set wpa_log file ptr for read");
687 goto exit;
688 }
689
690 buff_ptr = malloc(SUPP_LOG_BUFF_SIZE);
691 if (!buff_ptr) {
692 sigma_dut_print(dut, DUT_MSG_ERROR,
693 "Failed to alloc buffer of size %d",
694 SUPP_LOG_BUFF_SIZE);
695 goto exit;
696 }
697
698 /* Read wpa_supplicant log file in 4K byte chunks */
699 do {
700 unsigned int num_bytes_to_read;
701 unsigned int bytes_read;
702
703 num_bytes_to_read = (file_size > SUPP_LOG_BUFF_SIZE) ?
704 SUPP_LOG_BUFF_SIZE : file_size;
705 bytes_read = fread(buff_ptr, 1, num_bytes_to_read, supp_log);
706 if (!bytes_read) {
707 sigma_dut_print(dut, DUT_MSG_ERROR,
708 "Failed to read wpa_supplicant log");
709 goto exit;
710 }
711 if (bytes_read != num_bytes_to_read) {
712 sigma_dut_print(dut, DUT_MSG_DEBUG,
713 "wpa_supplicant log read err, read %d, num_bytes_to_read %d",
714 bytes_read, num_bytes_to_read);
715 goto exit;
716 }
717 fwrite(buff_ptr, 1, bytes_read, wpa_log);
718 file_size -= bytes_read;
719 } while (file_size > 0);
720 status = 0;
721
722 exit:
723 if (wpa_log)
724 fclose(wpa_log);
725 fclose(supp_log);
726 free(buff_ptr);
727
728 return status;
729 }
730 #endif /* !ANDROID */
731
732
cmd_dev_stop_test(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)733 static enum sigma_cmd_result cmd_dev_stop_test(struct sigma_dut *dut,
734 struct sigma_conn *conn,
735 struct sigma_cmd *cmd)
736 {
737 const char *val;
738 char buf[300];
739 char out_file[100];
740 char dir[200];
741 int res;
742
743 if (!dut->vendor_name) {
744 sigma_dut_print(dut, DUT_MSG_INFO,
745 "Log collection not supported without vendor name specified on the command line (-N)");
746 return SUCCESS_SEND_STATUS;
747 }
748
749 val = get_param(cmd, "Runtime_ID");
750 if (!val || strcmp(val, dut->dev_start_test_runtime_id) != 0) {
751 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid runtime id");
752 return ERROR_SEND_STATUS;
753 }
754
755 if (build_log_dir(dut, dir, sizeof(dir)) < 0)
756 return ERROR_SEND_STATUS;
757
758 #ifdef ANDROID
759 /* Copy all cnss_diag logs to dir */
760 run_system_wrapper(dut, "cp -a /data/vendor/wifi/wlan_logs/* %s", dir);
761 #else /* ANDROID */
762 if (dut->log_file_fd) {
763 fclose(dut->log_file_fd);
764 dut->log_file_fd = NULL;
765 }
766 if (save_supplicant_log(dut))
767 sigma_dut_print(dut, DUT_MSG_ERROR,
768 "Failed to save wpa_supplicant log");
769 #endif /* ANDROID */
770
771 res = snprintf(out_file, sizeof(out_file), "%s_%s_%s.tar.gz",
772 dut->vendor_name,
773 dut->model_name ? dut->model_name : "Unknown",
774 dut->dev_start_test_runtime_id);
775 if (res < 0 || res >= sizeof(out_file))
776 return ERROR_SEND_STATUS;
777
778 if (run_system_wrapper(dut, "tar -czvf %s/../%s %s", dir, out_file,
779 dir) < 0) {
780 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to create tar: %s",
781 buf);
782 return ERROR_SEND_STATUS;
783 }
784
785 val = get_param(cmd, "destpath");
786 if (!(val && is_destpath_valid(dut, val))) {
787 sigma_dut_print(dut, DUT_MSG_DEBUG, "Invalid path for TFTP %s",
788 val);
789 return ERROR_SEND_STATUS;
790 }
791
792 res = snprintf(buf, sizeof(buf), "tftp %s -c put %s/%s %s/%s",
793 inet_ntoa(conn->addr.sin_addr), dir, out_file, val,
794 out_file);
795 if (res < 0 || res >= sizeof(buf))
796 return ERROR_SEND_STATUS;
797 if (run_system_wrapper(dut, buf) < 0) {
798 sigma_dut_print(dut, DUT_MSG_ERROR,
799 "TFTP file transfer failed: %s", buf);
800 return ERROR_SEND_STATUS;
801 }
802 sigma_dut_print(dut, DUT_MSG_DEBUG, "TFTP file transfer: %s", buf);
803 snprintf(buf, sizeof(buf), "filename,%s", out_file);
804 send_resp(dut, conn, SIGMA_COMPLETE, buf);
805 run_system_wrapper(dut, "rm -f %s/../%s", dir, out_file);
806 run_system_wrapper(dut, "rm -rf %s", dir);
807
808 return SUCCESS_SEND_STATUS;
809 }
810
811
cmd_dev_get_log(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)812 static enum sigma_cmd_result cmd_dev_get_log(struct sigma_dut *dut,
813 struct sigma_conn *conn,
814 struct sigma_cmd *cmd)
815 {
816 return SUCCESS_SEND_STATUS;
817 }
818
819
req_intf(struct sigma_cmd * cmd)820 static int req_intf(struct sigma_cmd *cmd)
821 {
822 return get_param(cmd, "interface") == NULL ? -1 : 0;
823 }
824
825
req_role_svcname(struct sigma_cmd * cmd)826 static int req_role_svcname(struct sigma_cmd *cmd)
827 {
828 if (!get_param(cmd, "BLERole"))
829 return -1;
830 if (get_param(cmd, "BLEOp") && !get_param(cmd, "ServiceName"))
831 return -1;
832 return 0;
833 }
834
835
req_intf_prog(struct sigma_cmd * cmd)836 static int req_intf_prog(struct sigma_cmd *cmd)
837 {
838 if (get_param(cmd, "interface") == NULL)
839 return -1;
840 if (get_param(cmd, "program") == NULL)
841 return -1;
842 return 0;
843 }
844
845
req_prog(struct sigma_cmd * cmd)846 static int req_prog(struct sigma_cmd *cmd)
847 {
848 if (get_param(cmd, "program") == NULL)
849 return -1;
850 return 0;
851 }
852
853
dev_register_cmds(void)854 void dev_register_cmds(void)
855 {
856 sigma_dut_reg_cmd("dev_send_frame", req_prog, cmd_dev_send_frame);
857 sigma_dut_reg_cmd("dev_set_parameter", req_intf_prog,
858 cmd_dev_set_parameter);
859 sigma_dut_reg_cmd("dev_exec_action", req_prog,
860 cmd_dev_exec_action);
861 sigma_dut_reg_cmd("dev_configure_ie", req_intf, cmd_dev_configure_ie);
862 sigma_dut_reg_cmd("dev_start_test", NULL, cmd_dev_start_test);
863 sigma_dut_reg_cmd("dev_stop_test", NULL, cmd_dev_stop_test);
864 sigma_dut_reg_cmd("dev_get_log", NULL, cmd_dev_get_log);
865 sigma_dut_reg_cmd("dev_ble_action", req_role_svcname,
866 cmd_dev_ble_action);
867 }
868