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