xref: /wlan-dirver/utils/sigma-dut/dev.c (revision 314b9c65f32c7b1de9faa8bf8dd2bf696922ccc4)
1cd4e3c3eSJouni Malinen /*
2cd4e3c3eSJouni Malinen  * Sigma Control API DUT (station/AP/sniffer)
39c381f59SAmarnath Hullur Subramanyam  * Copyright (c) 2011-2013, 2017, Qualcomm Atheros, Inc.
4a0bf244dSJouni Malinen  * Copyright (c) 2018-2019, The Linux Foundation
5cd4e3c3eSJouni Malinen  * All Rights Reserved.
6cd4e3c3eSJouni Malinen  * Licensed under the Clear BSD license. See README for more details.
7cd4e3c3eSJouni Malinen  */
8cd4e3c3eSJouni Malinen 
9cd4e3c3eSJouni Malinen #include "sigma_dut.h"
100128bf99SKiran Kumar Lokere #include <ctype.h>
119c381f59SAmarnath Hullur Subramanyam #include "miracast.h"
122052daa2SAnurag Das #include <sys/wait.h>
132052daa2SAnurag Das #include "wpa_ctrl.h"
142052daa2SAnurag Das #include "wpa_helpers.h"
15cd4e3c3eSJouni Malinen 
16cd4e3c3eSJouni Malinen 
17fee3c4adSJouni Malinen extern char *sigma_cert_path;
18fee3c4adSJouni Malinen 
19fee3c4adSJouni Malinen 
cmd_dev_send_frame(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)20a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_send_frame(struct sigma_dut *dut,
21a0bf244dSJouni Malinen 						struct sigma_conn *conn,
22cd4e3c3eSJouni Malinen 						struct sigma_cmd *cmd)
23cd4e3c3eSJouni Malinen {
249c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
259c381f59SAmarnath Hullur Subramanyam 	const char *program = get_param(cmd, "Program");
269c381f59SAmarnath Hullur Subramanyam 
279c381f59SAmarnath Hullur Subramanyam 	if (program && (strcasecmp(program, "WFD") == 0 ||
289c381f59SAmarnath Hullur Subramanyam 			strcasecmp(program, "DisplayR2") == 0))
299c381f59SAmarnath Hullur Subramanyam 		return miracast_dev_send_frame(dut, conn, cmd);
309c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
319c381f59SAmarnath Hullur Subramanyam 
32cd4e3c3eSJouni Malinen 	if (dut->mode == SIGMA_MODE_STATION ||
33cd4e3c3eSJouni Malinen 	    dut->mode == SIGMA_MODE_UNKNOWN) {
34cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
35cd4e3c3eSJouni Malinen 				"dev_send_frame to sta_send_frame");
36cd4e3c3eSJouni Malinen 		return cmd_sta_send_frame(dut, conn, cmd);
37cd4e3c3eSJouni Malinen 	}
38cd4e3c3eSJouni Malinen 
39cd4e3c3eSJouni Malinen 	if (dut->mode == SIGMA_MODE_AP) {
40cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
41cd4e3c3eSJouni Malinen 				"dev_send_frame to ap_send_frame");
42cd4e3c3eSJouni Malinen 		return cmd_ap_send_frame(dut, conn, cmd);
43cd4e3c3eSJouni Malinen 	}
44cd4e3c3eSJouni Malinen 
45cd4e3c3eSJouni Malinen #ifdef CONFIG_WLANTEST
46cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert dev_send_frame to "
47cd4e3c3eSJouni Malinen 			"wlantest_send_frame");
48cd4e3c3eSJouni Malinen 	return cmd_wlantest_send_frame(dut, conn, cmd);
49cd4e3c3eSJouni Malinen #else /* CONFIG_WLANTEST */
50cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_ERROR,
51cd4e3c3eSJouni Malinen 		  "errorCode,Unsupported dev_send_frame");
52a0bf244dSJouni Malinen 	return STATUS_SENT;
53cd4e3c3eSJouni Malinen #endif /* CONFIG_WLANTEST */
54cd4e3c3eSJouni Malinen }
55cd4e3c3eSJouni Malinen 
56cd4e3c3eSJouni Malinen 
cmd_dev_set_parameter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)57a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_set_parameter(struct sigma_dut *dut,
58a0bf244dSJouni Malinen 						   struct sigma_conn *conn,
59cd4e3c3eSJouni Malinen 						   struct sigma_cmd *cmd)
60cd4e3c3eSJouni Malinen {
61cd4e3c3eSJouni Malinen 	const char *device = get_param(cmd, "Device");
62cd4e3c3eSJouni Malinen 
63cd4e3c3eSJouni Malinen 	if (device && strcasecmp(device, "STA") == 0) {
64cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
65cd4e3c3eSJouni Malinen 				"dev_set_parameter to sta_set_parameter");
66cd4e3c3eSJouni Malinen 		return cmd_sta_set_parameter(dut, conn, cmd);
67cd4e3c3eSJouni Malinen 	}
68cd4e3c3eSJouni Malinen 
69a0bf244dSJouni Malinen 	return INVALID_SEND_STATUS;
70cd4e3c3eSJouni Malinen }
71cd4e3c3eSJouni Malinen 
72cd4e3c3eSJouni Malinen 
sta_server_cert_trust(struct sigma_dut * dut,struct sigma_conn * conn,const char * val)73134fe3c3SJouni Malinen static enum sigma_cmd_result sta_server_cert_trust(struct sigma_dut *dut,
74134fe3c3SJouni Malinen 						   struct sigma_conn *conn,
75134fe3c3SJouni Malinen 						   const char *val)
76134fe3c3SJouni Malinen {
77fee3c4adSJouni Malinen 	char buf[200];
78134fe3c3SJouni Malinen 	struct wpa_ctrl *ctrl = NULL;
79134fe3c3SJouni Malinen 	int e;
80134fe3c3SJouni Malinen 	char resp[200];
81134fe3c3SJouni Malinen 	int num_disconnected = 0;
821f81e2d4SJouni Malinen 	int tod = -1;
83134fe3c3SJouni Malinen 
84134fe3c3SJouni Malinen 	strlcpy(resp, "ServerCertTrustResult,Accepted", sizeof(resp));
85134fe3c3SJouni Malinen 
866a3005feSJouni Malinen 	if (strcasecmp(val, "Accept") != 0 && strcasecmp(val, "Reject") != 0) {
876a3005feSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO,
886a3005feSJouni Malinen 				"Unknown ServerCertTrust value '%s'", val);
896a3005feSJouni Malinen 		return INVALID_SEND_STATUS;
90134fe3c3SJouni Malinen 	}
91134fe3c3SJouni Malinen 
92fee3c4adSJouni Malinen 	snprintf(buf, sizeof(buf), "%s/uosc-disabled", sigma_cert_path);
93fee3c4adSJouni Malinen 	if (file_exists(buf)) {
94fee3c4adSJouni Malinen 		strlcpy(resp,
95fee3c4adSJouni Malinen 			"ServerCertTrustResult,OverrideNotAllowed,Reason,UOSC disabled on device",
96fee3c4adSJouni Malinen 			sizeof(resp));
97fee3c4adSJouni Malinen 		goto done;
98fee3c4adSJouni Malinen 	}
99fee3c4adSJouni Malinen 
100134fe3c3SJouni Malinen 	if (!dut->server_cert_hash[0]) {
101134fe3c3SJouni Malinen 		strlcpy(resp,
1026a3005feSJouni Malinen 			"ServerCertTrustResult,OverrideNotAllowed,Reason,No server certificate stored",
103134fe3c3SJouni Malinen 			sizeof(resp));
104134fe3c3SJouni Malinen 		goto done;
105134fe3c3SJouni Malinen 	}
106134fe3c3SJouni Malinen 
107134fe3c3SJouni Malinen 	if (dut->sta_tod_policy) {
108134fe3c3SJouni Malinen 		strlcpy(resp,
1096a3005feSJouni Malinen 			"ServerCertTrustResult,OverrideNotAllowed,Reason,TOD policy",
110134fe3c3SJouni Malinen 			sizeof(resp));
111134fe3c3SJouni Malinen 		goto done;
112134fe3c3SJouni Malinen 	}
113134fe3c3SJouni Malinen 
11437d5c69eSJouni Malinen 	if (dut->server_cert_tod == 1) {
11537d5c69eSJouni Malinen 		strlcpy(resp,
11637d5c69eSJouni Malinen 			"ServerCertTrustResult,OverrideNotAllowed,Reason,TOD-STRICT policy in received server certificate",
11737d5c69eSJouni Malinen 			sizeof(resp));
11837d5c69eSJouni Malinen 		goto done;
11937d5c69eSJouni Malinen 	}
12037d5c69eSJouni Malinen 
1216a3005feSJouni Malinen 	if (strcasecmp(val, "Accept") != 0) {
1226a3005feSJouni Malinen 		strlcpy(resp, "ServerCertTrustResult,Rejected", sizeof(resp));
1236a3005feSJouni Malinen 		goto done;
1246a3005feSJouni Malinen 	}
1256a3005feSJouni Malinen 
126134fe3c3SJouni Malinen 	snprintf(buf, sizeof(buf), "hash://server/sha256/%s",
127134fe3c3SJouni Malinen 		 dut->server_cert_hash);
128016ae6c8SJouni Malinen 	if (set_network_quoted(get_station_ifname(dut), dut->infra_network_id,
129134fe3c3SJouni Malinen 			       "ca_cert", buf) < 0) {
130134fe3c3SJouni Malinen 		strlcpy(resp,
1316a3005feSJouni Malinen 			"ServerCertTrustResult,OverrideNotAllowed,Reason,Could not configure server certificate hash for the network profile",
132134fe3c3SJouni Malinen 			sizeof(resp));
133134fe3c3SJouni Malinen 		goto done;
134134fe3c3SJouni Malinen 	}
135134fe3c3SJouni Malinen 
136016ae6c8SJouni Malinen 	if (set_network(get_station_ifname(dut), dut->infra_network_id,
137560e4a97SJouni Malinen 			"domain_match", "NULL") < 0 ||
138016ae6c8SJouni Malinen 	    set_network(get_station_ifname(dut), dut->infra_network_id,
139560e4a97SJouni Malinen 			"domain_suffix_match", "NULL") < 0) {
140560e4a97SJouni Malinen 		strlcpy(resp,
141560e4a97SJouni Malinen 			"ServerCertTrustResult,OverrideNotAllowed,Reason,Could not clear domain matching rules",
142560e4a97SJouni Malinen 			sizeof(resp));
143560e4a97SJouni Malinen 		goto done;
144560e4a97SJouni Malinen 	}
145560e4a97SJouni Malinen 
146016ae6c8SJouni Malinen 	wpa_command(get_station_ifname(dut), "DISCONNECT");
147134fe3c3SJouni Malinen 	snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", dut->infra_network_id);
148016ae6c8SJouni Malinen 	if (wpa_command(get_station_ifname(dut), buf) < 0) {
149134fe3c3SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to select "
150134fe3c3SJouni Malinen 				"network id %d on %s",
151134fe3c3SJouni Malinen 				dut->infra_network_id,
152016ae6c8SJouni Malinen 				get_station_ifname(dut));
153134fe3c3SJouni Malinen 		strlcpy(resp,
154134fe3c3SJouni Malinen 			"ServerCertTrustResult,Accepted,Result,Could not request reconnection",
155134fe3c3SJouni Malinen 			sizeof(resp));
156134fe3c3SJouni Malinen 		goto done;
157134fe3c3SJouni Malinen 	}
158134fe3c3SJouni Malinen 
159016ae6c8SJouni Malinen 	ctrl = open_wpa_mon(get_station_ifname(dut));
160134fe3c3SJouni Malinen 	if (!ctrl)
161134fe3c3SJouni Malinen 		goto done;
162134fe3c3SJouni Malinen 
163134fe3c3SJouni Malinen 	for (e = 0; e < 20; e++) {
164134fe3c3SJouni Malinen 		const char *events[] = {
1651f81e2d4SJouni Malinen 			"CTRL-EVENT-EAP-PEER-CERT",
166134fe3c3SJouni Malinen 			"CTRL-EVENT-EAP-TLS-CERT-ERROR",
167134fe3c3SJouni Malinen 			"CTRL-EVENT-DISCONNECTED",
168134fe3c3SJouni Malinen 			"CTRL-EVENT-CONNECTED",
169134fe3c3SJouni Malinen 			NULL
170134fe3c3SJouni Malinen 		};
171134fe3c3SJouni Malinen 		char buf[1024];
172134fe3c3SJouni Malinen 		int res;
173134fe3c3SJouni Malinen 
174134fe3c3SJouni Malinen 		res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
175134fe3c3SJouni Malinen 		if (res < 0) {
176134fe3c3SJouni Malinen 			strlcpy(resp,
177134fe3c3SJouni Malinen 				"ServerCertTrustResult,Accepted,Result,Association did not complete",
178134fe3c3SJouni Malinen 				sizeof(resp));
179134fe3c3SJouni Malinen 			goto done;
180134fe3c3SJouni Malinen 		}
181134fe3c3SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Connection event: %s",
182134fe3c3SJouni Malinen 				buf);
183134fe3c3SJouni Malinen 
1841f81e2d4SJouni Malinen 
1851f81e2d4SJouni Malinen 		if (strstr(buf, "CTRL-EVENT-EAP-PEER-CERT") &&
1861f81e2d4SJouni Malinen 		    strstr(buf, " depth=0")) {
1871f81e2d4SJouni Malinen 			char *pos = strstr(buf, " hash=");
1881f81e2d4SJouni Malinen 
1891f81e2d4SJouni Malinen 			if (pos) {
1901f81e2d4SJouni Malinen 				if (strstr(buf, " tod=1"))
1911f81e2d4SJouni Malinen 					tod = 1;
1921f81e2d4SJouni Malinen 				else if (strstr(buf, " tod=2"))
1931f81e2d4SJouni Malinen 					tod = 2;
1941f81e2d4SJouni Malinen 				else
1951f81e2d4SJouni Malinen 					tod = 0;
1961f81e2d4SJouni Malinen 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1971f81e2d4SJouni Malinen 						"Server certificate TOD policy: %d",
1981f81e2d4SJouni Malinen 						tod);
1991f81e2d4SJouni Malinen 				dut->server_cert_tod = tod;
2001f81e2d4SJouni Malinen 			}
2011f81e2d4SJouni Malinen 		}
2021f81e2d4SJouni Malinen 
203134fe3c3SJouni Malinen 		if (strstr(buf, "CTRL-EVENT-EAP-TLS-CERT-ERROR")) {
204134fe3c3SJouni Malinen 			strlcpy(resp,
2056a3005feSJouni Malinen 				"ServerCertTrustResult,Accepted,Result,TLS server certificate validation failed with updated profile",
206134fe3c3SJouni Malinen 				sizeof(resp));
207134fe3c3SJouni Malinen 			goto done;
208134fe3c3SJouni Malinen 		}
209134fe3c3SJouni Malinen 
210134fe3c3SJouni Malinen 		if (strstr(buf, "CTRL-EVENT-DISCONNECTED")) {
211134fe3c3SJouni Malinen 			num_disconnected++;
212134fe3c3SJouni Malinen 
213134fe3c3SJouni Malinen 			if (num_disconnected > 2) {
214134fe3c3SJouni Malinen 				strlcpy(resp,
215134fe3c3SJouni Malinen 					"ServerCertTrustResult,Accepted,Result,Connection failed",
216134fe3c3SJouni Malinen 					sizeof(resp));
217134fe3c3SJouni Malinen 				goto done;
218134fe3c3SJouni Malinen 			}
219134fe3c3SJouni Malinen 		}
220134fe3c3SJouni Malinen 
221134fe3c3SJouni Malinen 		if (strstr(buf, "CTRL-EVENT-CONNECTED")) {
2221f81e2d4SJouni Malinen 			if (tod >= 0) {
2231f81e2d4SJouni Malinen 				sigma_dut_print(dut, DUT_MSG_DEBUG,
2241f81e2d4SJouni Malinen 						"Network profile TOD policy update: %d -> %d",
2251f81e2d4SJouni Malinen 						dut->sta_tod_policy, tod);
2261f81e2d4SJouni Malinen 				dut->sta_tod_policy = tod;
2271f81e2d4SJouni Malinen 			}
228134fe3c3SJouni Malinen 			strlcpy(resp,
229134fe3c3SJouni Malinen 				"ServerCertTrustResult,Accepted,Result,Connected",
230134fe3c3SJouni Malinen 				sizeof(resp));
231134fe3c3SJouni Malinen 			break;
232134fe3c3SJouni Malinen 		}
233134fe3c3SJouni Malinen 	}
234134fe3c3SJouni Malinen 
235134fe3c3SJouni Malinen done:
236134fe3c3SJouni Malinen 	if (ctrl) {
237134fe3c3SJouni Malinen 		wpa_ctrl_detach(ctrl);
238134fe3c3SJouni Malinen 		wpa_ctrl_close(ctrl);
239134fe3c3SJouni Malinen 	}
240134fe3c3SJouni Malinen 
241134fe3c3SJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
242134fe3c3SJouni Malinen 	return STATUS_SENT;
243134fe3c3SJouni Malinen }
244134fe3c3SJouni Malinen 
245134fe3c3SJouni Malinen 
dev_exec_key_rotation(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)246*314b9c65SJouni Malinen static enum sigma_cmd_result dev_exec_key_rotation(struct sigma_dut *dut,
247*314b9c65SJouni Malinen 						   struct sigma_conn *conn,
248*314b9c65SJouni Malinen 						   struct sigma_cmd *cmd)
249*314b9c65SJouni Malinen {
250*314b9c65SJouni Malinen 	if (dut->mode == SIGMA_MODE_AP ||
251*314b9c65SJouni Malinen 	    dut->mode == SIGMA_MODE_UNKNOWN) {
252*314b9c65SJouni Malinen 		const char *ifname;
253*314b9c65SJouni Malinen 
254*314b9c65SJouni Malinen 		ifname = get_hostapd_ifname(dut);
255*314b9c65SJouni Malinen 		if (hapd_command(ifname, "REKEY_GTK") < 0) {
256*314b9c65SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
257*314b9c65SJouni Malinen 				  "errorCode,Failed to request hostapd to rekey GTK");
258*314b9c65SJouni Malinen 			return STATUS_SENT_ERROR;
259*314b9c65SJouni Malinen 		}
260*314b9c65SJouni Malinen 		return SUCCESS_SEND_STATUS;
261*314b9c65SJouni Malinen 	} else if (dut->mode == SIGMA_MODE_STATION) {
262*314b9c65SJouni Malinen 		const char *intf = get_param(cmd, "Interface");
263*314b9c65SJouni Malinen 
264*314b9c65SJouni Malinen 		if (!intf)
265*314b9c65SJouni Malinen 			intf = get_main_ifname(dut);
266*314b9c65SJouni Malinen 		if (wpa_command(intf, "KEY_REQUEST 0 0") != 0) {
267*314b9c65SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
268*314b9c65SJouni Malinen 				  "errorCode,Failed to request wpa_supplicant to request AP to rekey GTK");
269*314b9c65SJouni Malinen 			return STATUS_SENT_ERROR;
270*314b9c65SJouni Malinen 		}
271*314b9c65SJouni Malinen 		return SUCCESS_SEND_STATUS;
272*314b9c65SJouni Malinen 	} else {
273*314b9c65SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
274*314b9c65SJouni Malinen 			  "errorCode,Unsupported mode for KeyRotation,1");
275*314b9c65SJouni Malinen 		return STATUS_SENT_ERROR;
276*314b9c65SJouni Malinen 	}
277*314b9c65SJouni Malinen }
278*314b9c65SJouni Malinen 
279*314b9c65SJouni Malinen 
wpa3_dev_exec_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)28019d52a70SJouni Malinen static enum sigma_cmd_result wpa3_dev_exec_action(struct sigma_dut *dut,
28119d52a70SJouni Malinen 						  struct sigma_conn *conn,
28219d52a70SJouni Malinen 						  struct sigma_cmd *cmd)
28319d52a70SJouni Malinen {
28419d52a70SJouni Malinen 	const char *val;
28519d52a70SJouni Malinen 	char buf[4000], buf2[100], *pos, *end;
28619d52a70SJouni Malinen 
28719d52a70SJouni Malinen 	val = get_param(cmd, "Rejected_DH_Groups");
28819d52a70SJouni Malinen 	if (val) {
28919d52a70SJouni Malinen 		val = get_param(cmd, "Dest_MAC");
29019d52a70SJouni Malinen 		if (!val)
29119d52a70SJouni Malinen 			return ERROR_SEND_STATUS;
29219d52a70SJouni Malinen 		snprintf(buf2, sizeof(buf2), "STA %s", val);
29319d52a70SJouni Malinen 		if (wpa_command_resp(dut->hostapd_ifname, buf2,
29419d52a70SJouni Malinen 				     buf, sizeof(buf)) < 0)
29519d52a70SJouni Malinen 			return ERROR_SEND_STATUS;
29619d52a70SJouni Malinen 		pos = buf;
29719d52a70SJouni Malinen 		while (pos) {
29819d52a70SJouni Malinen 			if (strncmp(pos, "sae_rejected_groups=", 20) == 0)
29919d52a70SJouni Malinen 				break;
30019d52a70SJouni Malinen 			pos = strchr(pos, '\n');
30119d52a70SJouni Malinen 			if (pos)
30219d52a70SJouni Malinen 				pos++;
30319d52a70SJouni Malinen 		}
30419d52a70SJouni Malinen 		if (pos) {
30519d52a70SJouni Malinen 			pos += 20;
30619d52a70SJouni Malinen 			end = strchr(pos, '\n');
30719d52a70SJouni Malinen 			if (end)
30819d52a70SJouni Malinen 				*end = '\0';
30919d52a70SJouni Malinen 		}
31019d52a70SJouni Malinen 		snprintf(buf2, sizeof(buf2), "DHGroupVerResult,%s",
31119d52a70SJouni Malinen 			 pos ? pos : "");
31219d52a70SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, buf2);
31319d52a70SJouni Malinen 		return STATUS_SENT;
31419d52a70SJouni Malinen 	}
31519d52a70SJouni Malinen 
316*314b9c65SJouni Malinen 	val = get_param(cmd, "KeyRotation");
317*314b9c65SJouni Malinen 	if (val && atoi(val) == 1)
318*314b9c65SJouni Malinen 		return dev_exec_key_rotation(dut, conn, cmd);
319*314b9c65SJouni Malinen 
32019d52a70SJouni Malinen 	return ERROR_SEND_STATUS;
32119d52a70SJouni Malinen }
32219d52a70SJouni Malinen 
32319d52a70SJouni Malinen 
cmd_dev_exec_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)324a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_exec_action(struct sigma_dut *dut,
325a0bf244dSJouni Malinen 						 struct sigma_conn *conn,
3269c381f59SAmarnath Hullur Subramanyam 						 struct sigma_cmd *cmd)
3279c381f59SAmarnath Hullur Subramanyam {
3289c381f59SAmarnath Hullur Subramanyam 	const char *program = get_param(cmd, "Program");
329134fe3c3SJouni Malinen 	const char *val;
3309c381f59SAmarnath Hullur Subramanyam 
331d86e5828SJouni Malinen #ifdef MIRACAST
3329c381f59SAmarnath Hullur Subramanyam 	if (program && (strcasecmp(program, "WFD") == 0 ||
333d86e5828SJouni Malinen 			strcasecmp(program, "DisplayR2") == 0)) {
334d86e5828SJouni Malinen 		if (get_param(cmd, "interface") == NULL)
335a0bf244dSJouni Malinen 			return INVALID_SEND_STATUS;
3369c381f59SAmarnath Hullur Subramanyam 		return miracast_dev_exec_action(dut, conn, cmd);
337d86e5828SJouni Malinen 	}
3389c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
3399c381f59SAmarnath Hullur Subramanyam 
340d86e5828SJouni Malinen 	if (program && strcasecmp(program, "DPP") == 0)
341d86e5828SJouni Malinen 		return dpp_dev_exec_action(dut, conn, cmd);
342d86e5828SJouni Malinen 
343134fe3c3SJouni Malinen 	val = get_param(cmd, "ServerCertTrust");
344134fe3c3SJouni Malinen 	if (val)
345134fe3c3SJouni Malinen 		return sta_server_cert_trust(dut, conn, val);
346134fe3c3SJouni Malinen 
34719d52a70SJouni Malinen 	if (program && strcasecmp(program, "WPA3") == 0)
34819d52a70SJouni Malinen 		return wpa3_dev_exec_action(dut, conn, cmd);
34919d52a70SJouni Malinen 
350a0bf244dSJouni Malinen 	return ERROR_SEND_STATUS;
3519c381f59SAmarnath Hullur Subramanyam }
3529c381f59SAmarnath Hullur Subramanyam 
3539c381f59SAmarnath Hullur Subramanyam 
cmd_dev_configure_ie(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)354a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_configure_ie(struct sigma_dut *dut,
355a0bf244dSJouni Malinen 						  struct sigma_conn *conn,
3563c367e8dSJouni Malinen 						  struct sigma_cmd *cmd)
3573c367e8dSJouni Malinen {
3583c367e8dSJouni Malinen 	const char *ie_name = get_param(cmd, "IE_Name");
3593c367e8dSJouni Malinen 	const char *contents = get_param(cmd, "Contents");
3603c367e8dSJouni Malinen 
3613c367e8dSJouni Malinen 	if (!ie_name || !contents)
362a0bf244dSJouni Malinen 		return INVALID_SEND_STATUS;
3633c367e8dSJouni Malinen 
3643c367e8dSJouni Malinen 	if (strcasecmp(ie_name, "RSNE") != 0) {
3653c367e8dSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
3663c367e8dSJouni Malinen 			  "errorCode,Unsupported IE_Name value");
367a0bf244dSJouni Malinen 		return STATUS_SENT;
3683c367e8dSJouni Malinen 	}
3693c367e8dSJouni Malinen 
3703c367e8dSJouni Malinen 	free(dut->rsne_override);
3713c367e8dSJouni Malinen 	dut->rsne_override = strdup(contents);
3723c367e8dSJouni Malinen 
373a0bf244dSJouni Malinen 	return dut->rsne_override ? SUCCESS_SEND_STATUS : ERROR_SEND_STATUS;
3743c367e8dSJouni Malinen }
3753c367e8dSJouni Malinen 
3763c367e8dSJouni Malinen 
cmd_dev_ble_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)377a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_ble_action(struct sigma_dut *dut,
378a0bf244dSJouni Malinen 						struct sigma_conn *conn,
3792052daa2SAnurag Das 						struct sigma_cmd *cmd)
3802052daa2SAnurag Das {
3812052daa2SAnurag Das #ifdef ANDROID
3822052daa2SAnurag Das 	const char *ble_op = get_param(cmd, "BLEOp");
3832052daa2SAnurag Das 	const char *prog = get_param(cmd, "Prog");
3842052daa2SAnurag Das 	const char *service_name = get_param(cmd, "ServiceName");
3852052daa2SAnurag Das 	const char *ble_role = get_param(cmd, "BLERole");
3862052daa2SAnurag Das 	const char *discovery_type = get_param(cmd, "DiscoveryType");
3872052daa2SAnurag Das 	const char *msg_type = get_param(cmd, "messagetype");
3882052daa2SAnurag Das 	const char *action = get_param(cmd, "action");
3892052daa2SAnurag Das 	const char *M2Transmit = get_param(cmd, "M2Transmit");
3902052daa2SAnurag Das 	char *argv[17];
3912052daa2SAnurag Das 	pid_t pid;
3922052daa2SAnurag Das 
3932052daa2SAnurag Das 	if (prog && ble_role && action && msg_type) {
3942052daa2SAnurag Das 		send_resp(dut, conn, SIGMA_COMPLETE,
3952052daa2SAnurag Das 			  "OrgID,0x00,TransDataHeader,0x00,BloomFilterElement,NULL");
396a0bf244dSJouni Malinen 		return STATUS_SENT;
3972052daa2SAnurag Das 	}
3982052daa2SAnurag Das 	if (!ble_op || !prog || !service_name || !ble_role || !discovery_type) {
3992052daa2SAnurag Das 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid arguments");
400a0bf244dSJouni Malinen 		return INVALID_SEND_STATUS;
4012052daa2SAnurag Das 	}
4022052daa2SAnurag Das 
4032052daa2SAnurag Das 	if ((strcasecmp(prog, "NAN") != 0)) {
4042052daa2SAnurag Das 		sigma_dut_print(dut, DUT_MSG_ERROR, "Program %s not supported",
4052052daa2SAnurag Das 				prog);
406a0bf244dSJouni Malinen 		return INVALID_SEND_STATUS;
4072052daa2SAnurag Das 	}
4082052daa2SAnurag Das 
4092052daa2SAnurag Das 	if (strcasecmp(ble_role, "seeker") != 0 &&
4102052daa2SAnurag Das 	    strcasecmp(ble_role, "provider") != 0 &&
4112052daa2SAnurag Das 	    strcasecmp(ble_role, "browser") != 0) {
4122052daa2SAnurag Das 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid BLERole: %s",
4132052daa2SAnurag Das 				ble_role);
414a0bf244dSJouni Malinen 		return INVALID_SEND_STATUS;
4152052daa2SAnurag Das 	}
4162052daa2SAnurag Das 
4172052daa2SAnurag Das 	if (strcasecmp(discovery_type, "active") != 0 &&
4182052daa2SAnurag Das 	    strcasecmp(discovery_type, "passive") != 0) {
4192052daa2SAnurag Das 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid DiscoveryType: %s",
4202052daa2SAnurag Das 				discovery_type);
421a0bf244dSJouni Malinen 		return INVALID_SEND_STATUS;
4222052daa2SAnurag Das 	}
4232052daa2SAnurag Das 
4242052daa2SAnurag Das 	if (!M2Transmit)
4252052daa2SAnurag Das 		M2Transmit = "disable";
4262052daa2SAnurag Das 
4272052daa2SAnurag Das 	argv[0] = "am";
4282052daa2SAnurag Das 	argv[1] = "start";
4292052daa2SAnurag Das 	argv[2] = "-n";
4302052daa2SAnurag Das 	argv[3] = "org.codeaurora.nanservicediscovery/org.codeaurora.nanservicediscovery.MainActivity";
4312052daa2SAnurag Das 	argv[4] = "--es";
4322052daa2SAnurag Das 	argv[5] = "service";
4332052daa2SAnurag Das 	argv[6] = (char *) service_name;
4342052daa2SAnurag Das 	argv[7] = "--es";
4352052daa2SAnurag Das 	argv[8] = "role";
4362052daa2SAnurag Das 	argv[9] = (char *) ble_role;
4372052daa2SAnurag Das 	argv[10] = "--es";
4382052daa2SAnurag Das 	argv[11] = "scantype";
4392052daa2SAnurag Das 	argv[12] = (char *) discovery_type;
4402052daa2SAnurag Das 	argv[13] = "--es";
4412052daa2SAnurag Das 	argv[14] = "M2Transmit";
4422052daa2SAnurag Das 	argv[15] = (char *) M2Transmit;
4432052daa2SAnurag Das 	argv[16] = NULL;
4442052daa2SAnurag Das 
4452052daa2SAnurag Das 	pid = fork();
4462052daa2SAnurag Das 	if (pid == -1) {
4472052daa2SAnurag Das 		sigma_dut_print(dut, DUT_MSG_ERROR, "fork: %s",
4482052daa2SAnurag Das 				strerror(errno));
449a0bf244dSJouni Malinen 		return ERROR_SEND_STATUS;
4502052daa2SAnurag Das 	}
4512052daa2SAnurag Das 
4522052daa2SAnurag Das 	if (pid == 0) {
4532052daa2SAnurag Das 		execv("/system/bin/am", argv);
4542052daa2SAnurag Das 		sigma_dut_print(dut, DUT_MSG_ERROR, "execv: %s",
4552052daa2SAnurag Das 				strerror(errno));
4562052daa2SAnurag Das 		exit(0);
457a0bf244dSJouni Malinen 		return ERROR_SEND_STATUS;
4582052daa2SAnurag Das 	}
4592052daa2SAnurag Das 
4602052daa2SAnurag Das 	dut->nanservicediscoveryinprogress = 1;
4612052daa2SAnurag Das #endif /* ANDROID */
4622052daa2SAnurag Das 
463a0bf244dSJouni Malinen 	return SUCCESS_SEND_STATUS;
4642052daa2SAnurag Das }
4652052daa2SAnurag Das 
4662052daa2SAnurag Das 
4670128bf99SKiran Kumar Lokere /* Runtime ID must contain only numbers */
is_runtime_id_valid(struct sigma_dut * dut,const char * val)4680128bf99SKiran Kumar Lokere static int is_runtime_id_valid(struct sigma_dut *dut, const char *val)
4690128bf99SKiran Kumar Lokere {
4700128bf99SKiran Kumar Lokere 	int i;
4710128bf99SKiran Kumar Lokere 
4720128bf99SKiran Kumar Lokere 	for (i = 0; val[i] != '\0'; i++) {
4730128bf99SKiran Kumar Lokere 		if (!isdigit(val[i])) {
4740128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_DEBUG,
4750128bf99SKiran Kumar Lokere 					"Invalid Runtime_ID %s", val);
4760128bf99SKiran Kumar Lokere 			return 0;
4770128bf99SKiran Kumar Lokere 		}
4780128bf99SKiran Kumar Lokere 	}
4790128bf99SKiran Kumar Lokere 
4800128bf99SKiran Kumar Lokere 	return 1;
4810128bf99SKiran Kumar Lokere }
4820128bf99SKiran Kumar Lokere 
4830128bf99SKiran Kumar Lokere 
build_log_dir(struct sigma_dut * dut,char * dir,size_t dir_size)4840128bf99SKiran Kumar Lokere static int build_log_dir(struct sigma_dut *dut, char *dir, size_t dir_size)
4850128bf99SKiran Kumar Lokere {
4860128bf99SKiran Kumar Lokere 	int res;
487ce791a3dSJouni Malinen 	const char *vendor = dut->vendor_name;
4880128bf99SKiran Kumar Lokere 	int i;
4890128bf99SKiran Kumar Lokere 
490ce791a3dSJouni Malinen 	if (!vendor)
491ce791a3dSJouni Malinen 		return -1;
4920128bf99SKiran Kumar Lokere 
4930128bf99SKiran Kumar Lokere 	if (dut->log_file_dir) {
4940128bf99SKiran Kumar Lokere 		res = snprintf(dir, dir_size, "%s/%s", dut->log_file_dir,
4950128bf99SKiran Kumar Lokere 			       vendor);
4960128bf99SKiran Kumar Lokere 	} else {
4970128bf99SKiran Kumar Lokere #ifdef ANDROID
4980128bf99SKiran Kumar Lokere 		res = snprintf(dir, dir_size, "/data/vendor/wifi/%s",
4990128bf99SKiran Kumar Lokere 			       vendor);
5000128bf99SKiran Kumar Lokere #else /* ANDROID */
5010128bf99SKiran Kumar Lokere 		res = snprintf(dir, dir_size, "/var/log/%s", vendor);
5020128bf99SKiran Kumar Lokere #endif /* ANDROID */
5030128bf99SKiran Kumar Lokere 	}
5040128bf99SKiran Kumar Lokere 
5050128bf99SKiran Kumar Lokere 	if (res < 0 || res >= dir_size)
5060128bf99SKiran Kumar Lokere 		return -1;
5070128bf99SKiran Kumar Lokere 
5080128bf99SKiran Kumar Lokere 	/* Check for valid vendor name in log dir path since the log dir
5090128bf99SKiran Kumar Lokere 	 * (/var/log/vendor) is deleted in dev_stop routine. This check is to
5100128bf99SKiran Kumar Lokere 	 * avoid any unintended file deletion.
5110128bf99SKiran Kumar Lokere 	 */
5120128bf99SKiran Kumar Lokere 	for (i = 0; vendor[i] != '\0'; i++) {
5130128bf99SKiran Kumar Lokere 		if (!isalpha(vendor[i])) {
5140128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_DEBUG,
5150128bf99SKiran Kumar Lokere 					"Invalid char %c in vendor name %s",
5160128bf99SKiran Kumar Lokere 					vendor[i], vendor);
5170128bf99SKiran Kumar Lokere 			return -1;
5180128bf99SKiran Kumar Lokere 		}
5190128bf99SKiran Kumar Lokere 	}
5200128bf99SKiran Kumar Lokere 
5210128bf99SKiran Kumar Lokere 	return 0;
5220128bf99SKiran Kumar Lokere }
5230128bf99SKiran Kumar Lokere 
5240128bf99SKiran Kumar Lokere 
5250128bf99SKiran Kumar Lokere /* User has to redirect wpa_supplicant logs to the following file. */
5260128bf99SKiran Kumar Lokere #ifndef WPA_SUPPLICANT_LOG_FILE
5270128bf99SKiran Kumar Lokere #define WPA_SUPPLICANT_LOG_FILE "/var/log/supplicant_log/wpa_log.txt"
5280128bf99SKiran Kumar Lokere #endif /* WPA_SUPPLICANT_LOG_FILE */
5292052daa2SAnurag Das 
cmd_dev_start_test(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)530a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_start_test(struct sigma_dut *dut,
531a0bf244dSJouni Malinen 						struct sigma_conn *conn,
532a7ac56ebSPeng Xu 						struct sigma_cmd *cmd)
533a7ac56ebSPeng Xu {
5340128bf99SKiran Kumar Lokere 	const char *val;
5350128bf99SKiran Kumar Lokere 	char buf[250];
5360128bf99SKiran Kumar Lokere 	char dir[200];
5370128bf99SKiran Kumar Lokere 	FILE *supp_log;
5380128bf99SKiran Kumar Lokere 	int res;
5390128bf99SKiran Kumar Lokere 
5400128bf99SKiran Kumar Lokere 	val = get_param(cmd, "Runtime_ID");
5410128bf99SKiran Kumar Lokere 	if (!(val && is_runtime_id_valid(dut, val)))
5420128bf99SKiran Kumar Lokere 		return INVALID_SEND_STATUS;
5430128bf99SKiran Kumar Lokere 
544ce791a3dSJouni Malinen 	if (!dut->vendor_name) {
545ce791a3dSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO,
546ce791a3dSJouni Malinen 				"Log collection not supported without vendor name specified on the command line (-N)");
547ce791a3dSJouni Malinen 		return SUCCESS_SEND_STATUS;
548ce791a3dSJouni Malinen 	}
549ce791a3dSJouni Malinen 
5500128bf99SKiran Kumar Lokere 	if (build_log_dir(dut, dir, sizeof(dir)) < 0)
5510128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
5520128bf99SKiran Kumar Lokere 
5530128bf99SKiran Kumar Lokere 	supp_log = fopen(WPA_SUPPLICANT_LOG_FILE, "r");
5540128bf99SKiran Kumar Lokere 	if (!supp_log) {
5550128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
5560128bf99SKiran Kumar Lokere 				"Failed to open wpa_log file %s",
5570128bf99SKiran Kumar Lokere 				WPA_SUPPLICANT_LOG_FILE);
5580128bf99SKiran Kumar Lokere 	} else {
5590128bf99SKiran Kumar Lokere 		/* Get the wpa_supplicant log file size */
5600128bf99SKiran Kumar Lokere 		if (fseek(supp_log, 0, SEEK_END))
5610128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_ERROR,
5620128bf99SKiran Kumar Lokere 					"Failed to get file size for read");
5630128bf99SKiran Kumar Lokere 		else
5640128bf99SKiran Kumar Lokere 			dut->wpa_log_size = ftell(supp_log);
5650128bf99SKiran Kumar Lokere 
5660128bf99SKiran Kumar Lokere 		fclose(supp_log);
5670128bf99SKiran Kumar Lokere 	}
5680128bf99SKiran Kumar Lokere 
5690128bf99SKiran Kumar Lokere 	strlcpy(dut->dev_start_test_runtime_id, val,
5700128bf99SKiran Kumar Lokere 		sizeof(dut->dev_start_test_runtime_id));
5710128bf99SKiran Kumar Lokere 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Runtime_ID %s",
5720128bf99SKiran Kumar Lokere 			dut->dev_start_test_runtime_id);
5730128bf99SKiran Kumar Lokere 
5740128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "rm -rf %s", dir);
5750128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "mkdir -p %s", dir);
5760128bf99SKiran Kumar Lokere 
5770128bf99SKiran Kumar Lokere #ifdef ANDROID
5780128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "logcat -v time > %s/logcat_%s.txt &",
5790128bf99SKiran Kumar Lokere 			   dir, dut->dev_start_test_runtime_id);
5800128bf99SKiran Kumar Lokere #else /* ANDROID */
5810128bf99SKiran Kumar Lokere 	/* Open log file for sigma_dut logs. This is not needed for Android, as
5820128bf99SKiran Kumar Lokere 	 * we are already collecting logcat. */
5830128bf99SKiran Kumar Lokere 	res = snprintf(buf, sizeof(buf), "%s/sigma_%s.txt", dir,
5840128bf99SKiran Kumar Lokere 		       dut->dev_start_test_runtime_id);
5850128bf99SKiran Kumar Lokere 	if (res >= 0 && res < sizeof(buf)) {
5860128bf99SKiran Kumar Lokere 		if (dut->log_file_fd)
5870128bf99SKiran Kumar Lokere 			fclose(dut->log_file_fd);
5880128bf99SKiran Kumar Lokere 
5890128bf99SKiran Kumar Lokere 		dut->log_file_fd = fopen(buf, "a");
5900128bf99SKiran Kumar Lokere 		if (!dut->log_file_fd)
5910128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_ERROR,
5920128bf99SKiran Kumar Lokere 					"Failed to create sigma_dut log %s",
5930128bf99SKiran Kumar Lokere 					buf);
5940128bf99SKiran Kumar Lokere 	}
5950128bf99SKiran Kumar Lokere 
5960128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "killall -9 cnss_diag_lite");
5970128bf99SKiran Kumar Lokere 	run_system_wrapper(dut,
5980128bf99SKiran Kumar Lokere 			   "cnss_diag_lite -c -x 31 > %s/cnss_diag_id_%s.txt &",
5990128bf99SKiran Kumar Lokere 			   dir, dut->dev_start_test_runtime_id);
6000128bf99SKiran Kumar Lokere #endif /* ANDROID */
6010128bf99SKiran Kumar Lokere 
602a0bf244dSJouni Malinen 	return SUCCESS_SEND_STATUS;
603a7ac56ebSPeng Xu }
604a7ac56ebSPeng Xu 
605a7ac56ebSPeng Xu 
is_allowed_char(char ch)6060128bf99SKiran Kumar Lokere static int is_allowed_char(char ch)
6070128bf99SKiran Kumar Lokere {
6080128bf99SKiran Kumar Lokere 	return strchr("./-_", ch) != NULL;
6090128bf99SKiran Kumar Lokere }
6100128bf99SKiran Kumar Lokere 
6110128bf99SKiran Kumar Lokere 
is_destpath_valid(struct sigma_dut * dut,const char * val)6120128bf99SKiran Kumar Lokere static int is_destpath_valid(struct sigma_dut *dut, const char *val)
6130128bf99SKiran Kumar Lokere {
6140128bf99SKiran Kumar Lokere 	int i;
6150128bf99SKiran Kumar Lokere 
6160128bf99SKiran Kumar Lokere 	for (i = 0; val[i] != '\0'; i++) {
6170128bf99SKiran Kumar Lokere 		if (!(isalnum(val[i]) || is_allowed_char(val[i]))) {
6180128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_DEBUG,
6190128bf99SKiran Kumar Lokere 					"Invalid char %c in destpath %s",
6200128bf99SKiran Kumar Lokere 					val[i], val);
6210128bf99SKiran Kumar Lokere 			return 0;
6220128bf99SKiran Kumar Lokere 		}
6230128bf99SKiran Kumar Lokere 	}
6240128bf99SKiran Kumar Lokere 
6250128bf99SKiran Kumar Lokere 	return 1;
6260128bf99SKiran Kumar Lokere }
6270128bf99SKiran Kumar Lokere 
6280128bf99SKiran Kumar Lokere 
6290128bf99SKiran Kumar Lokere #ifndef ANDROID
6300128bf99SKiran Kumar Lokere #define SUPP_LOG_BUFF_SIZE 4 * 1024
6310128bf99SKiran Kumar Lokere 
save_supplicant_log(struct sigma_dut * dut)6320128bf99SKiran Kumar Lokere static int save_supplicant_log(struct sigma_dut *dut)
6330128bf99SKiran Kumar Lokere {
6340128bf99SKiran Kumar Lokere 	char dir[200];
6350128bf99SKiran Kumar Lokere 	char buf[300];
6360128bf99SKiran Kumar Lokere 	FILE *wpa_log = NULL;
6370128bf99SKiran Kumar Lokere 	FILE *supp_log;
6380128bf99SKiran Kumar Lokere 	char *buff_ptr = NULL;
6390128bf99SKiran Kumar Lokere 	unsigned int file_size;
6400128bf99SKiran Kumar Lokere 	unsigned int file_size_orig;
6410128bf99SKiran Kumar Lokere 	int status = -1, res;
6420128bf99SKiran Kumar Lokere 
6430128bf99SKiran Kumar Lokere 	if (build_log_dir(dut, dir, sizeof(dir)) < 0)
6440128bf99SKiran Kumar Lokere 		return -1;
6450128bf99SKiran Kumar Lokere 
6460128bf99SKiran Kumar Lokere 	res = snprintf(buf, sizeof(buf), "%s/wpa_supplicant_log_%s.txt", dir,
6470128bf99SKiran Kumar Lokere 		       dut->dev_start_test_runtime_id);
6480128bf99SKiran Kumar Lokere 	if (res < 0 || res >= sizeof(buf))
6490128bf99SKiran Kumar Lokere 		return -1;
6500128bf99SKiran Kumar Lokere 
6510128bf99SKiran Kumar Lokere 	supp_log = fopen(WPA_SUPPLICANT_LOG_FILE, "r");
6520128bf99SKiran Kumar Lokere 	if (!supp_log) {
6530128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
6540128bf99SKiran Kumar Lokere 				"Failed to open wpa_log file %s",
6550128bf99SKiran Kumar Lokere 				WPA_SUPPLICANT_LOG_FILE);
6560128bf99SKiran Kumar Lokere 		return -1;
6570128bf99SKiran Kumar Lokere 	}
6580128bf99SKiran Kumar Lokere 
6590128bf99SKiran Kumar Lokere 	/* Get the wpa_supplicant log file size */
6600128bf99SKiran Kumar Lokere 	if (fseek(supp_log, 0, SEEK_END)) {
6610128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
6620128bf99SKiran Kumar Lokere 				"Failed to get file size for read");
6630128bf99SKiran Kumar Lokere 		goto exit;
6640128bf99SKiran Kumar Lokere 	}
6650128bf99SKiran Kumar Lokere 	file_size_orig = ftell(supp_log);
6660128bf99SKiran Kumar Lokere 
6670128bf99SKiran Kumar Lokere 	if (file_size_orig < dut->wpa_log_size) {
6680128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
6690128bf99SKiran Kumar Lokere 				"file size err, new size %u, old size %u",
6700128bf99SKiran Kumar Lokere 				file_size_orig, dut->wpa_log_size);
6710128bf99SKiran Kumar Lokere 		goto exit;
6720128bf99SKiran Kumar Lokere 	}
6730128bf99SKiran Kumar Lokere 
6740128bf99SKiran Kumar Lokere 	/* Get the wpa_supplicant file size for current test */
6750128bf99SKiran Kumar Lokere 	file_size = file_size_orig - dut->wpa_log_size;
6760128bf99SKiran Kumar Lokere 
6770128bf99SKiran Kumar Lokere 	wpa_log = fopen(buf, "w");
6780128bf99SKiran Kumar Lokere 	if (!wpa_log) {
6790128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
6800128bf99SKiran Kumar Lokere 				"Failed to create tmp wpa_log file %s", buf);
6810128bf99SKiran Kumar Lokere 		goto exit;
6820128bf99SKiran Kumar Lokere 	}
6830128bf99SKiran Kumar Lokere 
6840128bf99SKiran Kumar Lokere 	if (fseek(supp_log, dut->wpa_log_size, SEEK_SET)) {
6850128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
6860128bf99SKiran Kumar Lokere 				"Failed to set wpa_log file ptr for read");
6870128bf99SKiran Kumar Lokere 		goto exit;
6880128bf99SKiran Kumar Lokere 	}
6890128bf99SKiran Kumar Lokere 
6900128bf99SKiran Kumar Lokere 	buff_ptr = malloc(SUPP_LOG_BUFF_SIZE);
6910128bf99SKiran Kumar Lokere 	if (!buff_ptr) {
6920128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
6930128bf99SKiran Kumar Lokere 				"Failed to alloc buffer of size %d",
6940128bf99SKiran Kumar Lokere 				SUPP_LOG_BUFF_SIZE);
6950128bf99SKiran Kumar Lokere 		goto exit;
6960128bf99SKiran Kumar Lokere 	}
6970128bf99SKiran Kumar Lokere 
6980128bf99SKiran Kumar Lokere 	/* Read wpa_supplicant log file in 4K byte chunks */
6990128bf99SKiran Kumar Lokere 	do {
7000128bf99SKiran Kumar Lokere 		unsigned int num_bytes_to_read;
7010128bf99SKiran Kumar Lokere 		unsigned int bytes_read;
7020128bf99SKiran Kumar Lokere 
7030128bf99SKiran Kumar Lokere 		num_bytes_to_read = (file_size > SUPP_LOG_BUFF_SIZE) ?
7040128bf99SKiran Kumar Lokere 			SUPP_LOG_BUFF_SIZE : file_size;
7050128bf99SKiran Kumar Lokere 		bytes_read = fread(buff_ptr, 1, num_bytes_to_read, supp_log);
7060128bf99SKiran Kumar Lokere 		if (!bytes_read) {
7070128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_ERROR,
7080128bf99SKiran Kumar Lokere 					"Failed to read wpa_supplicant log");
7090128bf99SKiran Kumar Lokere 			goto exit;
7100128bf99SKiran Kumar Lokere 		}
7110128bf99SKiran Kumar Lokere 		if (bytes_read != num_bytes_to_read) {
7120128bf99SKiran Kumar Lokere 			sigma_dut_print(dut, DUT_MSG_DEBUG,
7130128bf99SKiran Kumar Lokere 					"wpa_supplicant log read err, read %d, num_bytes_to_read %d",
7140128bf99SKiran Kumar Lokere 					bytes_read, num_bytes_to_read);
7150128bf99SKiran Kumar Lokere 			goto exit;
7160128bf99SKiran Kumar Lokere 		}
7170128bf99SKiran Kumar Lokere 		fwrite(buff_ptr, 1, bytes_read, wpa_log);
7180128bf99SKiran Kumar Lokere 		file_size -= bytes_read;
7190128bf99SKiran Kumar Lokere 	} while (file_size > 0);
7200128bf99SKiran Kumar Lokere 	status = 0;
7210128bf99SKiran Kumar Lokere 
7220128bf99SKiran Kumar Lokere exit:
7230128bf99SKiran Kumar Lokere 	if (wpa_log)
7240128bf99SKiran Kumar Lokere 		fclose(wpa_log);
7250128bf99SKiran Kumar Lokere 	fclose(supp_log);
7260128bf99SKiran Kumar Lokere 	free(buff_ptr);
7270128bf99SKiran Kumar Lokere 
7280128bf99SKiran Kumar Lokere 	return status;
7290128bf99SKiran Kumar Lokere }
7300128bf99SKiran Kumar Lokere #endif /* !ANDROID */
7310128bf99SKiran Kumar Lokere 
7320128bf99SKiran Kumar Lokere 
cmd_dev_stop_test(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)733a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_stop_test(struct sigma_dut *dut,
734a0bf244dSJouni Malinen 					       struct sigma_conn *conn,
735a7ac56ebSPeng Xu 					       struct sigma_cmd *cmd)
736a7ac56ebSPeng Xu {
7370128bf99SKiran Kumar Lokere 	const char *val;
7380128bf99SKiran Kumar Lokere 	char buf[300];
7390128bf99SKiran Kumar Lokere 	char out_file[100];
7400128bf99SKiran Kumar Lokere 	char dir[200];
7410128bf99SKiran Kumar Lokere 	int res;
7420128bf99SKiran Kumar Lokere 
743ce791a3dSJouni Malinen 	if (!dut->vendor_name) {
744ce791a3dSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO,
745ce791a3dSJouni Malinen 				"Log collection not supported without vendor name specified on the command line (-N)");
746ce791a3dSJouni Malinen 		return SUCCESS_SEND_STATUS;
747ce791a3dSJouni Malinen 	}
748ce791a3dSJouni Malinen 
7490128bf99SKiran Kumar Lokere 	val = get_param(cmd, "Runtime_ID");
7500128bf99SKiran Kumar Lokere 	if (!val || strcmp(val, dut->dev_start_test_runtime_id) != 0) {
7510128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid runtime id");
7520128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
7530128bf99SKiran Kumar Lokere 	}
7540128bf99SKiran Kumar Lokere 
7550128bf99SKiran Kumar Lokere 	if (build_log_dir(dut, dir, sizeof(dir)) < 0)
7560128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
7570128bf99SKiran Kumar Lokere 
7580128bf99SKiran Kumar Lokere #ifdef ANDROID
7590128bf99SKiran Kumar Lokere 	/* Copy all cnss_diag logs to dir */
7600128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "cp -a /data/vendor/wifi/wlan_logs/* %s", dir);
7610128bf99SKiran Kumar Lokere #else /* ANDROID */
7620128bf99SKiran Kumar Lokere 	if (dut->log_file_fd) {
7630128bf99SKiran Kumar Lokere 		fclose(dut->log_file_fd);
7640128bf99SKiran Kumar Lokere 		dut->log_file_fd = NULL;
7650128bf99SKiran Kumar Lokere 	}
7660128bf99SKiran Kumar Lokere 	if (save_supplicant_log(dut))
7670128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
7680128bf99SKiran Kumar Lokere 				"Failed to save wpa_supplicant log");
7690128bf99SKiran Kumar Lokere #endif /* ANDROID */
7700128bf99SKiran Kumar Lokere 
7710128bf99SKiran Kumar Lokere 	res = snprintf(out_file, sizeof(out_file), "%s_%s_%s.tar.gz",
772ce791a3dSJouni Malinen 		       dut->vendor_name,
7730128bf99SKiran Kumar Lokere 		       dut->model_name ? dut->model_name : "Unknown",
7740128bf99SKiran Kumar Lokere 		       dut->dev_start_test_runtime_id);
7750128bf99SKiran Kumar Lokere 	if (res < 0 || res >= sizeof(out_file))
7760128bf99SKiran Kumar Lokere 	    return ERROR_SEND_STATUS;
7770128bf99SKiran Kumar Lokere 
7780128bf99SKiran Kumar Lokere 	if (run_system_wrapper(dut, "tar -czvf %s/../%s %s", dir, out_file,
7790128bf99SKiran Kumar Lokere 			       dir) < 0) {
7800128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to create tar: %s",
7810128bf99SKiran Kumar Lokere 				buf);
7820128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
7830128bf99SKiran Kumar Lokere 	}
7840128bf99SKiran Kumar Lokere 
7850128bf99SKiran Kumar Lokere 	val = get_param(cmd, "destpath");
7860128bf99SKiran Kumar Lokere 	if (!(val && is_destpath_valid(dut, val))) {
7870128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Invalid path for TFTP %s",
7880128bf99SKiran Kumar Lokere 				val);
7890128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
7900128bf99SKiran Kumar Lokere 	}
7910128bf99SKiran Kumar Lokere 
7920128bf99SKiran Kumar Lokere 	res = snprintf(buf, sizeof(buf), "tftp %s -c put %s/%s %s/%s",
7930128bf99SKiran Kumar Lokere 		       inet_ntoa(conn->addr.sin_addr), dir, out_file, val,
7940128bf99SKiran Kumar Lokere 		       out_file);
7950128bf99SKiran Kumar Lokere 	if (res < 0 || res >= sizeof(buf))
7960128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
7970128bf99SKiran Kumar Lokere 	if (run_system_wrapper(dut, buf) < 0) {
7980128bf99SKiran Kumar Lokere 		sigma_dut_print(dut, DUT_MSG_ERROR,
7990128bf99SKiran Kumar Lokere 				"TFTP file transfer failed: %s", buf);
8000128bf99SKiran Kumar Lokere 		return ERROR_SEND_STATUS;
8010128bf99SKiran Kumar Lokere 	}
8020128bf99SKiran Kumar Lokere 	sigma_dut_print(dut, DUT_MSG_DEBUG, "TFTP file transfer: %s", buf);
8030128bf99SKiran Kumar Lokere 	snprintf(buf, sizeof(buf), "filename,%s", out_file);
8040128bf99SKiran Kumar Lokere 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
8050128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "rm -f %s/../%s", dir, out_file);
8060128bf99SKiran Kumar Lokere 	run_system_wrapper(dut, "rm -rf %s", dir);
8070128bf99SKiran Kumar Lokere 
808a0bf244dSJouni Malinen 	return SUCCESS_SEND_STATUS;
809a7ac56ebSPeng Xu }
810a7ac56ebSPeng Xu 
811a7ac56ebSPeng Xu 
cmd_dev_get_log(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)812a0bf244dSJouni Malinen static enum sigma_cmd_result cmd_dev_get_log(struct sigma_dut *dut,
813a0bf244dSJouni Malinen 					     struct sigma_conn *conn,
814a7ac56ebSPeng Xu 					     struct sigma_cmd *cmd)
815a7ac56ebSPeng Xu {
816a0bf244dSJouni Malinen 	return SUCCESS_SEND_STATUS;
817a7ac56ebSPeng Xu }
818a7ac56ebSPeng Xu 
819a7ac56ebSPeng Xu 
req_intf(struct sigma_cmd * cmd)8203c367e8dSJouni Malinen static int req_intf(struct sigma_cmd *cmd)
8213c367e8dSJouni Malinen {
8223c367e8dSJouni Malinen 	return get_param(cmd, "interface") == NULL ? -1 : 0;
8233c367e8dSJouni Malinen }
8243c367e8dSJouni Malinen 
8253c367e8dSJouni Malinen 
req_role_svcname(struct sigma_cmd * cmd)8262052daa2SAnurag Das static int req_role_svcname(struct sigma_cmd *cmd)
8272052daa2SAnurag Das {
8282052daa2SAnurag Das 	if (!get_param(cmd, "BLERole"))
8292052daa2SAnurag Das 		 return -1;
8302052daa2SAnurag Das 	if (get_param(cmd, "BLEOp") && !get_param(cmd, "ServiceName"))
8312052daa2SAnurag Das 		return -1;
8322052daa2SAnurag Das 	return 0;
8332052daa2SAnurag Das }
8342052daa2SAnurag Das 
8352052daa2SAnurag Das 
req_intf_prog(struct sigma_cmd * cmd)836cd4e3c3eSJouni Malinen static int req_intf_prog(struct sigma_cmd *cmd)
837cd4e3c3eSJouni Malinen {
838cd4e3c3eSJouni Malinen 	if (get_param(cmd, "interface") == NULL)
839cd4e3c3eSJouni Malinen 		return -1;
840cd4e3c3eSJouni Malinen 	if (get_param(cmd, "program") == NULL)
841cd4e3c3eSJouni Malinen 		return -1;
842cd4e3c3eSJouni Malinen 	return 0;
843cd4e3c3eSJouni Malinen }
844cd4e3c3eSJouni Malinen 
845cd4e3c3eSJouni Malinen 
req_prog(struct sigma_cmd * cmd)846d86e5828SJouni Malinen static int req_prog(struct sigma_cmd *cmd)
847d86e5828SJouni Malinen {
848d86e5828SJouni Malinen 	if (get_param(cmd, "program") == NULL)
849d86e5828SJouni Malinen 		return -1;
850d86e5828SJouni Malinen 	return 0;
851d86e5828SJouni Malinen }
852d86e5828SJouni Malinen 
853d86e5828SJouni Malinen 
dev_register_cmds(void)854cd4e3c3eSJouni Malinen void dev_register_cmds(void)
855cd4e3c3eSJouni Malinen {
8564a3c2f80SAlexei Avshalom Lazar 	sigma_dut_reg_cmd("dev_send_frame", req_prog, cmd_dev_send_frame);
857cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("dev_set_parameter", req_intf_prog,
858cd4e3c3eSJouni Malinen 			  cmd_dev_set_parameter);
859d86e5828SJouni Malinen 	sigma_dut_reg_cmd("dev_exec_action", req_prog,
8609c381f59SAmarnath Hullur Subramanyam 			  cmd_dev_exec_action);
8613c367e8dSJouni Malinen 	sigma_dut_reg_cmd("dev_configure_ie", req_intf, cmd_dev_configure_ie);
862a7ac56ebSPeng Xu 	sigma_dut_reg_cmd("dev_start_test", NULL, cmd_dev_start_test);
863a7ac56ebSPeng Xu 	sigma_dut_reg_cmd("dev_stop_test", NULL, cmd_dev_stop_test);
864a7ac56ebSPeng Xu 	sigma_dut_reg_cmd("dev_get_log", NULL, cmd_dev_get_log);
8652052daa2SAnurag Das 	sigma_dut_reg_cmd("dev_ble_action", req_role_svcname,
8662052daa2SAnurag Das 			  cmd_dev_ble_action);
867cd4e3c3eSJouni Malinen }
868