xref: /wlan-dirver/utils/sigma-dut/sigma_dut.c (revision d06f100ba12f942f15c84858ddb94f76c6990181)
1cd4e3c3eSJouni Malinen /*
2cd4e3c3eSJouni Malinen  * Sigma Control API DUT (station/AP)
3cd4e3c3eSJouni Malinen  * Copyright (c) 2010-2011, Atheros Communications, Inc.
49c381f59SAmarnath Hullur Subramanyam  * Copyright (c) 2011-2017, Qualcomm Atheros, Inc.
55404f5fdSJouni Malinen  * Copyright (c) 2018-2019, The Linux Foundation
6cd4e3c3eSJouni Malinen  * All Rights Reserved.
7cd4e3c3eSJouni Malinen  * Licensed under the Clear BSD license. See README for more details.
8cd4e3c3eSJouni Malinen  */
9cd4e3c3eSJouni Malinen 
10cd4e3c3eSJouni Malinen #include "sigma_dut.h"
11cd4e3c3eSJouni Malinen #ifdef __linux__
12cd4e3c3eSJouni Malinen #include <signal.h>
13cd4e3c3eSJouni Malinen #include <netinet/tcp.h>
14cd4e3c3eSJouni Malinen #endif /* __linux__ */
15f2af39bfSDanny Segal #include "wpa_ctrl.h"
16cd4e3c3eSJouni Malinen #include "wpa_helpers.h"
179c381f59SAmarnath Hullur Subramanyam #include "miracast.h"
18cd4e3c3eSJouni Malinen 
19cd4e3c3eSJouni Malinen #define SIGMA_DUT_PORT 9000
20cd4e3c3eSJouni Malinen #define MAX_CONNECTIONS 4
21cd4e3c3eSJouni Malinen 
22cd4e3c3eSJouni Malinen extern enum driver_type wifi_chip_type;
23cd4e3c3eSJouni Malinen 
24cd4e3c3eSJouni Malinen static struct sigma_dut sigma_dut;
25cd4e3c3eSJouni Malinen 
26cd4e3c3eSJouni Malinen char *sigma_main_ifname = NULL;
27cd4e3c3eSJouni Malinen char *sigma_radio_ifname[MAX_RADIO] = {};
28cd4e3c3eSJouni Malinen char *sigma_station_ifname = NULL;
29f2af39bfSDanny Segal char *sigma_p2p_ifname = NULL;
30f2af39bfSDanny Segal static char *sigma_p2p_ifname_buf = NULL;
31cd4e3c3eSJouni Malinen char *sigma_wpas_ctrl = "/var/run/wpa_supplicant/";
32cd4e3c3eSJouni Malinen char *sigma_hapd_ctrl = NULL;
33525dbfd1SRajiv Ranjan char *client_socket_path = NULL;
34cd4e3c3eSJouni Malinen char *ap_inet_addr = "192.168.43.1";
35cd4e3c3eSJouni Malinen char *ap_inet_mask = "255.255.255.0";
36cd4e3c3eSJouni Malinen char *sigma_cert_path = "/etc/wpa_supplicant";
37cd4e3c3eSJouni Malinen 
38cd4e3c3eSJouni Malinen /* For WMM-AC testing this set to 1 through argument,
39cd4e3c3eSJouni Malinen  * otherwise default WMM-PS 0 */
40cd4e3c3eSJouni Malinen int sigma_wmm_ac = 0;
41cd4e3c3eSJouni Malinen 
42cd4e3c3eSJouni Malinen 
43cd4e3c3eSJouni Malinen #ifdef ANDROID
44cd4e3c3eSJouni Malinen #include <android/log.h>
45cd4e3c3eSJouni Malinen 
46cd4e3c3eSJouni Malinen static enum android_LogPriority level_to_android_priority(int level)
47cd4e3c3eSJouni Malinen {
48cd4e3c3eSJouni Malinen 	switch (level) {
49cd4e3c3eSJouni Malinen 	case DUT_MSG_ERROR:
50cd4e3c3eSJouni Malinen 		return ANDROID_LOG_ERROR;
51cd4e3c3eSJouni Malinen 	case DUT_MSG_INFO:
52cd4e3c3eSJouni Malinen 		return ANDROID_LOG_INFO;
53cd4e3c3eSJouni Malinen 	case DUT_MSG_DEBUG:
54cd4e3c3eSJouni Malinen 		return ANDROID_LOG_DEBUG;
55cd4e3c3eSJouni Malinen 	default:
56cd4e3c3eSJouni Malinen 		return ANDROID_LOG_VERBOSE;
57cd4e3c3eSJouni Malinen 	}
58cd4e3c3eSJouni Malinen }
59cd4e3c3eSJouni Malinen #endif /* ANDROID */
60cd4e3c3eSJouni Malinen 
61cd4e3c3eSJouni Malinen 
62cd4e3c3eSJouni Malinen void sigma_dut_print(struct sigma_dut *dut, int level, const char *fmt, ...)
63cd4e3c3eSJouni Malinen {
64cd4e3c3eSJouni Malinen 	va_list ap;
65cd4e3c3eSJouni Malinen 	struct timeval tv;
66cd4e3c3eSJouni Malinen 
67cd4e3c3eSJouni Malinen 	if (level < dut->debug_level)
68cd4e3c3eSJouni Malinen 		return;
69cd4e3c3eSJouni Malinen 
70cd4e3c3eSJouni Malinen #ifdef ANDROID
71cd4e3c3eSJouni Malinen 	va_start(ap, fmt);
72cd4e3c3eSJouni Malinen 	__android_log_vprint(level_to_android_priority(level),
73cd4e3c3eSJouni Malinen 			     "sigma_dut", fmt, ap);
74cd4e3c3eSJouni Malinen 	va_end(ap);
75cd4e3c3eSJouni Malinen 	if (!dut->stdout_debug)
76cd4e3c3eSJouni Malinen 		return;
77cd4e3c3eSJouni Malinen #endif /* ANDROID */
78cd4e3c3eSJouni Malinen 
79cd4e3c3eSJouni Malinen 	va_start(ap, fmt);
80cd4e3c3eSJouni Malinen 	gettimeofday(&tv, NULL);
81cd4e3c3eSJouni Malinen 	printf("%ld.%06u: ", (long) tv.tv_sec,
82cd4e3c3eSJouni Malinen 	       (unsigned int) tv.tv_usec);
83cd4e3c3eSJouni Malinen 	vprintf(fmt, ap);
84cd4e3c3eSJouni Malinen 	printf("\n");
85cd4e3c3eSJouni Malinen 	va_end(ap);
86cd4e3c3eSJouni Malinen }
87cd4e3c3eSJouni Malinen 
88cd4e3c3eSJouni Malinen 
89cd4e3c3eSJouni Malinen void sigma_dut_summary(struct sigma_dut *dut, const char *fmt, ...)
90cd4e3c3eSJouni Malinen {
91cd4e3c3eSJouni Malinen 	va_list ap;
92cd4e3c3eSJouni Malinen 	FILE *f;
93cd4e3c3eSJouni Malinen 
94cd4e3c3eSJouni Malinen 	if (!dut->summary_log)
95cd4e3c3eSJouni Malinen 		return;
96cd4e3c3eSJouni Malinen 
97cd4e3c3eSJouni Malinen 	f = fopen(dut->summary_log, "a");
98cd4e3c3eSJouni Malinen 	if (f == NULL)
99cd4e3c3eSJouni Malinen 		return;
100cd4e3c3eSJouni Malinen 
101cd4e3c3eSJouni Malinen 	va_start(ap, fmt);
102cd4e3c3eSJouni Malinen 	vfprintf(f, fmt, ap);
103cd4e3c3eSJouni Malinen 	fprintf(f, "\n");
104cd4e3c3eSJouni Malinen 	va_end(ap);
105cd4e3c3eSJouni Malinen 	fclose(f);
106cd4e3c3eSJouni Malinen }
107cd4e3c3eSJouni Malinen 
108cd4e3c3eSJouni Malinen 
109cd4e3c3eSJouni Malinen int sigma_dut_reg_cmd(const char *cmd,
110cd4e3c3eSJouni Malinen 		      int (*validate)(struct sigma_cmd *cmd),
11126a5b76dSJouni Malinen 		      enum sigma_cmd_result (*process)(struct sigma_dut *dut,
112cd4e3c3eSJouni Malinen 						       struct sigma_conn *conn,
113cd4e3c3eSJouni Malinen 						       struct sigma_cmd *cmd))
114cd4e3c3eSJouni Malinen {
115cd4e3c3eSJouni Malinen 	struct sigma_cmd_handler *h;
116cd4e3c3eSJouni Malinen 	size_t clen, len;
117cd4e3c3eSJouni Malinen 
1185404f5fdSJouni Malinen 	for (h = sigma_dut.cmds; h; h = h->next) {
1195404f5fdSJouni Malinen 		if (strcmp(h->cmd, cmd) == 0) {
1205404f5fdSJouni Malinen 			printf("ERROR: Duplicate sigma_dut command registration for '%s'\n",
1215404f5fdSJouni Malinen 			       cmd);
1225404f5fdSJouni Malinen 			return -1;
1235404f5fdSJouni Malinen 		}
1245404f5fdSJouni Malinen 	}
1255404f5fdSJouni Malinen 
126cd4e3c3eSJouni Malinen 	clen = strlen(cmd);
127cd4e3c3eSJouni Malinen 	len = sizeof(*h) + clen + 1;
128cd4e3c3eSJouni Malinen 	h = malloc(len);
129cd4e3c3eSJouni Malinen 	if (h == NULL)
130cd4e3c3eSJouni Malinen 		return -1;
131cd4e3c3eSJouni Malinen 	memset(h, 0, len);
132cd4e3c3eSJouni Malinen 	h->cmd = (char *) (h + 1); /* include in same allocation */
133cd4e3c3eSJouni Malinen 	memcpy(h->cmd, cmd, clen);
134cd4e3c3eSJouni Malinen 	h->validate = validate;
135cd4e3c3eSJouni Malinen 	h->process= process;
136cd4e3c3eSJouni Malinen 
137cd4e3c3eSJouni Malinen 	h->next = sigma_dut.cmds;
138cd4e3c3eSJouni Malinen 	sigma_dut.cmds = h;
139cd4e3c3eSJouni Malinen 
140cd4e3c3eSJouni Malinen 	return 0;
141cd4e3c3eSJouni Malinen }
142cd4e3c3eSJouni Malinen 
143cd4e3c3eSJouni Malinen 
144cd4e3c3eSJouni Malinen static void sigma_dut_unreg_cmds(struct sigma_dut *dut)
145cd4e3c3eSJouni Malinen {
146cd4e3c3eSJouni Malinen 	struct sigma_cmd_handler *cmd, *prev;
147cd4e3c3eSJouni Malinen 	cmd = dut->cmds;
148cd4e3c3eSJouni Malinen 	dut->cmds = NULL;
149cd4e3c3eSJouni Malinen 	while (cmd) {
150cd4e3c3eSJouni Malinen 		prev = cmd;
151cd4e3c3eSJouni Malinen 		cmd = cmd->next;
152cd4e3c3eSJouni Malinen 		free(prev);
153cd4e3c3eSJouni Malinen 	}
154cd4e3c3eSJouni Malinen }
155cd4e3c3eSJouni Malinen 
156cd4e3c3eSJouni Malinen 
157cd4e3c3eSJouni Malinen static int open_socket(struct sigma_dut *dut, int port)
158cd4e3c3eSJouni Malinen {
159cd4e3c3eSJouni Malinen 	struct sockaddr_in addr;
160cd4e3c3eSJouni Malinen #ifndef __QNXNTO__
161cd4e3c3eSJouni Malinen 	int val;
162cd4e3c3eSJouni Malinen #endif /* !__QNXNTO__ */
163cd4e3c3eSJouni Malinen 
164cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
165cd4e3c3eSJouni Malinen 	dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
166cd4e3c3eSJouni Malinen #else /* __QNXNTO__ */
167cd4e3c3eSJouni Malinen 	dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
168cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
169cd4e3c3eSJouni Malinen 	if (dut->s < 0) {
170cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "socket: %s",
171cd4e3c3eSJouni Malinen 				strerror(errno));
172cd4e3c3eSJouni Malinen 		return -1;
173cd4e3c3eSJouni Malinen 	}
174cd4e3c3eSJouni Malinen 
175cd4e3c3eSJouni Malinen #ifndef __QNXNTO__
176cd4e3c3eSJouni Malinen 	val = 1;
177cd4e3c3eSJouni Malinen 	if (setsockopt(dut->s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) <
178cd4e3c3eSJouni Malinen 	    0)
179cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt SO_REUSEADDR: "
180cd4e3c3eSJouni Malinen 				"%s", strerror(errno));
181cd4e3c3eSJouni Malinen #endif /* !__QNXNTO__ */
182cd4e3c3eSJouni Malinen 
183cd4e3c3eSJouni Malinen #ifdef __linux__
184cd4e3c3eSJouni Malinen 	val = 1;
185cd4e3c3eSJouni Malinen 	if (setsockopt(dut->s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) <
186cd4e3c3eSJouni Malinen 	    0)
187cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt TCP_NODELAY: "
188cd4e3c3eSJouni Malinen 				"%s", strerror(errno));
189cd4e3c3eSJouni Malinen #endif /* __linux__ */
190cd4e3c3eSJouni Malinen 
191cd4e3c3eSJouni Malinen 	memset(&addr, 0, sizeof(addr));
192cd4e3c3eSJouni Malinen 	addr.sin_family = AF_INET;
193cd4e3c3eSJouni Malinen 	addr.sin_port = htons(port);
194cd4e3c3eSJouni Malinen 
195cd4e3c3eSJouni Malinen 	if (bind(dut->s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
196cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "bind: %s",
197cd4e3c3eSJouni Malinen 				strerror(errno));
198cd4e3c3eSJouni Malinen 		goto fail;
199cd4e3c3eSJouni Malinen 	}
200cd4e3c3eSJouni Malinen 
201cd4e3c3eSJouni Malinen 	if (listen(dut->s, 5) < 0) {
202cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "listen: %s",
203cd4e3c3eSJouni Malinen 				strerror(errno));
204cd4e3c3eSJouni Malinen 		goto fail;
205cd4e3c3eSJouni Malinen 	}
206cd4e3c3eSJouni Malinen 
207cd4e3c3eSJouni Malinen 	return 0;
208cd4e3c3eSJouni Malinen 
209cd4e3c3eSJouni Malinen fail:
210cd4e3c3eSJouni Malinen 	shutdown(dut->s, SHUT_RDWR);
211cd4e3c3eSJouni Malinen 	close(dut->s);
212cd4e3c3eSJouni Malinen 	dut->s = -1;
213cd4e3c3eSJouni Malinen 	return -1;
214cd4e3c3eSJouni Malinen }
215cd4e3c3eSJouni Malinen 
216cd4e3c3eSJouni Malinen 
217cd4e3c3eSJouni Malinen static void close_socket(struct sigma_dut *dut)
218cd4e3c3eSJouni Malinen {
219cd4e3c3eSJouni Malinen 	shutdown(dut->s, SHUT_RDWR);
220cd4e3c3eSJouni Malinen 	close(dut->s);
221cd4e3c3eSJouni Malinen 	dut->s = -1;
222cd4e3c3eSJouni Malinen }
223cd4e3c3eSJouni Malinen 
224cd4e3c3eSJouni Malinen 
225cd4e3c3eSJouni Malinen void send_resp(struct sigma_dut *dut, struct sigma_conn *conn,
22676401f50SJouni Malinen 	       enum sigma_status status, const char *buf)
227cd4e3c3eSJouni Malinen {
228cd4e3c3eSJouni Malinen 	struct msghdr msg;
229cd4e3c3eSJouni Malinen 	struct iovec iov[4];
230cd4e3c3eSJouni Malinen 	size_t elems;
231cd4e3c3eSJouni Malinen 
232a326d7b5SJouni Malinen 	if (!conn)
233a326d7b5SJouni Malinen 		return;
234a326d7b5SJouni Malinen 
235cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "resp: status=%d buf=%s",
236cd4e3c3eSJouni Malinen 			status, buf ? buf : "N/A");
237cd4e3c3eSJouni Malinen 
238cd4e3c3eSJouni Malinen 	iov[0].iov_base = "status,";
239cd4e3c3eSJouni Malinen 	iov[0].iov_len = 7;
240cd4e3c3eSJouni Malinen 	switch (status) {
241cd4e3c3eSJouni Malinen 	case SIGMA_RUNNING:
242cd4e3c3eSJouni Malinen 		iov[1].iov_base = "RUNNING,";
243cd4e3c3eSJouni Malinen 		iov[1].iov_len = 8;
244cd4e3c3eSJouni Malinen 		break;
245cd4e3c3eSJouni Malinen 	case SIGMA_INVALID:
246cd4e3c3eSJouni Malinen 		iov[1].iov_base = "INVALID,";
247cd4e3c3eSJouni Malinen 		iov[1].iov_len = 8;
248cd4e3c3eSJouni Malinen 		break;
249cd4e3c3eSJouni Malinen 	case SIGMA_ERROR:
250cd4e3c3eSJouni Malinen 		iov[1].iov_base = "ERROR,";
251cd4e3c3eSJouni Malinen 		iov[1].iov_len = 6;
252cd4e3c3eSJouni Malinen 		break;
253cd4e3c3eSJouni Malinen 	case SIGMA_COMPLETE:
254cd4e3c3eSJouni Malinen 		iov[1].iov_base = "COMPLETE,";
255cd4e3c3eSJouni Malinen 		iov[1].iov_len = 9;
256cd4e3c3eSJouni Malinen 		break;
257cd4e3c3eSJouni Malinen 	}
258cd4e3c3eSJouni Malinen 	if (status != SIGMA_RUNNING) {
259cd4e3c3eSJouni Malinen 		sigma_dut_summary(dut, "CAPI resp: status,%s%s",
260cd4e3c3eSJouni Malinen 				  (char *) iov[1].iov_base, buf ? buf : "");
261cd4e3c3eSJouni Malinen 	}
262cd4e3c3eSJouni Malinen 	if (buf) {
26376401f50SJouni Malinen 		iov[2].iov_base = (void *) buf;
264cd4e3c3eSJouni Malinen 		iov[2].iov_len = strlen(buf);
265cd4e3c3eSJouni Malinen 		iov[3].iov_base = "\r\n";
266cd4e3c3eSJouni Malinen 		iov[3].iov_len = 2;
267cd4e3c3eSJouni Malinen 		elems = 4;
268cd4e3c3eSJouni Malinen 	} else {
269cd4e3c3eSJouni Malinen 		iov[1].iov_len--;
270cd4e3c3eSJouni Malinen 		iov[2].iov_base = "\r\n";
271cd4e3c3eSJouni Malinen 		iov[2].iov_len = 2;
272cd4e3c3eSJouni Malinen 		elems = 3;
273cd4e3c3eSJouni Malinen 	}
274cd4e3c3eSJouni Malinen 
275cd4e3c3eSJouni Malinen 	memset(&msg, 0, sizeof(msg));
276cd4e3c3eSJouni Malinen 	msg.msg_iov = iov;
277cd4e3c3eSJouni Malinen 	msg.msg_iovlen = elems;
278cd4e3c3eSJouni Malinen 	if (sendmsg(conn->s, &msg, 0) < 0)
279cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "sendmsg: %s",
280cd4e3c3eSJouni Malinen 				strerror(errno));
2810fee701cSJouni Malinen 	dut->response_sent++;
282cd4e3c3eSJouni Malinen }
283cd4e3c3eSJouni Malinen 
284cd4e3c3eSJouni Malinen 
285cd4e3c3eSJouni Malinen const char * get_param(struct sigma_cmd *cmd, const char *name)
286cd4e3c3eSJouni Malinen {
287cd4e3c3eSJouni Malinen 	int i;
288cd4e3c3eSJouni Malinen 	for (i = 0; i < cmd->count; i++) {
289cd4e3c3eSJouni Malinen 		if (strcasecmp(name, cmd->params[i]) == 0)
290cd4e3c3eSJouni Malinen 			return cmd->values[i];
291cd4e3c3eSJouni Malinen 	}
292cd4e3c3eSJouni Malinen 	return NULL;
293cd4e3c3eSJouni Malinen }
294cd4e3c3eSJouni Malinen 
295cd4e3c3eSJouni Malinen 
296bc180dc5SAlexei Avshalom Lazar const char * get_param_indexed(struct sigma_cmd *cmd, const char *name,
297bc180dc5SAlexei Avshalom Lazar 			       int index)
298bc180dc5SAlexei Avshalom Lazar {
299bc180dc5SAlexei Avshalom Lazar 	int i, j;
300bc180dc5SAlexei Avshalom Lazar 
301bc180dc5SAlexei Avshalom Lazar 	for (i = 0, j = 0; i < cmd->count; i++) {
302bc180dc5SAlexei Avshalom Lazar 		if (strcasecmp(name, cmd->params[i]) == 0) {
303bc180dc5SAlexei Avshalom Lazar 			j++;
304bc180dc5SAlexei Avshalom Lazar 			if (j > index)
305bc180dc5SAlexei Avshalom Lazar 				return cmd->values[i];
306bc180dc5SAlexei Avshalom Lazar 		}
307bc180dc5SAlexei Avshalom Lazar 	}
308bc180dc5SAlexei Avshalom Lazar 
309bc180dc5SAlexei Avshalom Lazar 	return NULL;
310bc180dc5SAlexei Avshalom Lazar }
311bc180dc5SAlexei Avshalom Lazar 
312bc180dc5SAlexei Avshalom Lazar 
313cd4e3c3eSJouni Malinen static void process_cmd(struct sigma_dut *dut, struct sigma_conn *conn,
314cd4e3c3eSJouni Malinen 			char *buf)
315cd4e3c3eSJouni Malinen {
316cd4e3c3eSJouni Malinen 	struct sigma_cmd_handler *h;
317cd4e3c3eSJouni Malinen 	struct sigma_cmd c;
318cd4e3c3eSJouni Malinen 	char *cmd, *pos, *pos2;
319cd4e3c3eSJouni Malinen 	int len;
3205fdd8650SAlexei Avshalom Lazar 	char txt[300];
32126a5b76dSJouni Malinen 	enum sigma_cmd_result res;
322cd4e3c3eSJouni Malinen 
323cd4e3c3eSJouni Malinen 	while (*buf == '\r' || *buf == '\n' || *buf == '\t' || *buf == ' ')
324cd4e3c3eSJouni Malinen 		buf++;
325cd4e3c3eSJouni Malinen 	len = strlen(buf);
326cd4e3c3eSJouni Malinen 	while (len > 0 && buf[len - 1] == ' ') {
327cd4e3c3eSJouni Malinen 		buf[len - 1] = '\0';
328cd4e3c3eSJouni Malinen 		len--;
329cd4e3c3eSJouni Malinen 	}
330cd4e3c3eSJouni Malinen 
331cd4e3c3eSJouni Malinen 	if (dut->debug_level < DUT_MSG_INFO) {
332cd4e3c3eSJouni Malinen 		pos = strchr(buf, ',');
333cd4e3c3eSJouni Malinen 		if (pos == NULL)
334cd4e3c3eSJouni Malinen 			pos = buf + len;
335cd4e3c3eSJouni Malinen 		if (pos - buf > 50)
336cd4e3c3eSJouni Malinen 			pos = buf + 50;
337cd4e3c3eSJouni Malinen 		memcpy(txt, "/====[ ", 7);
338cd4e3c3eSJouni Malinen 		pos2 = txt + 7;
339cd4e3c3eSJouni Malinen 		memcpy(pos2, buf, pos - buf);
340cd4e3c3eSJouni Malinen 		pos2 += pos - buf;
341cd4e3c3eSJouni Malinen 		*pos2++ = ' ';
342cd4e3c3eSJouni Malinen 		*pos2++ = ']';
343cd4e3c3eSJouni Malinen 		while (pos2 - txt < 70)
344cd4e3c3eSJouni Malinen 			*pos2++ = '=';
345cd4e3c3eSJouni Malinen 		*pos2++ = '\\';
346cd4e3c3eSJouni Malinen 		*pos2 = '\0';
347cd4e3c3eSJouni Malinen 		printf("\n%s\n\n", txt);
348cd4e3c3eSJouni Malinen 	}
349cd4e3c3eSJouni Malinen 
350cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "cmd: %s", buf);
351cd4e3c3eSJouni Malinen 	sigma_dut_summary(dut, "CAPI cmd: %s", buf);
352cd4e3c3eSJouni Malinen 	snprintf(txt, sizeof(txt), "NOTE CAPI:%s", buf);
353cd4e3c3eSJouni Malinen 	txt[sizeof(txt) - 1] = '\0';
354cd4e3c3eSJouni Malinen 	wpa_command(get_main_ifname(), txt);
355cd4e3c3eSJouni Malinen 
356cd4e3c3eSJouni Malinen 	memset(&c, 0, sizeof(c));
357cd4e3c3eSJouni Malinen 	cmd = buf;
358cd4e3c3eSJouni Malinen 	pos = strchr(cmd, ',');
359cd4e3c3eSJouni Malinen 	if (pos) {
360cd4e3c3eSJouni Malinen 		*pos++ = '\0';
361cd4e3c3eSJouni Malinen 		if (strcasecmp(cmd, "AccessPoint") == 0 ||
362cd4e3c3eSJouni Malinen 		    strcasecmp(cmd, "PowerSwitch") == 0) {
363cd4e3c3eSJouni Malinen 			pos2 = strchr(pos, ',');
364cd4e3c3eSJouni Malinen 			if (pos2 == NULL)
365cd4e3c3eSJouni Malinen 				goto invalid_params;
366cd4e3c3eSJouni Malinen 			c.params[c.count] = pos;
367cd4e3c3eSJouni Malinen 			c.values[c.count] = pos2;
368cd4e3c3eSJouni Malinen 			c.count++;
369cd4e3c3eSJouni Malinen 			pos = strchr(pos2, ',');
370cd4e3c3eSJouni Malinen 			if (pos)
371cd4e3c3eSJouni Malinen 				*pos++ = '\0';
372cd4e3c3eSJouni Malinen 		}
373cd4e3c3eSJouni Malinen 		while (pos) {
374cd4e3c3eSJouni Malinen 			pos2 = strchr(pos, ',');
375cd4e3c3eSJouni Malinen 			if (pos2 == NULL)
376cd4e3c3eSJouni Malinen 				goto invalid_params;
377cd4e3c3eSJouni Malinen 			*pos2++ = '\0';
378cd4e3c3eSJouni Malinen 			if (c.count == MAX_PARAMS) {
379cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_INFO, "Too many "
380cd4e3c3eSJouni Malinen 						"parameters");
381cd4e3c3eSJouni Malinen 				goto invalid_params;
382cd4e3c3eSJouni Malinen 			}
383cd4e3c3eSJouni Malinen 			c.params[c.count] = pos;
384cd4e3c3eSJouni Malinen 			c.values[c.count] = pos2;
385cd4e3c3eSJouni Malinen 			c.count++;
386cd4e3c3eSJouni Malinen 			pos = strchr(pos2, ',');
387cd4e3c3eSJouni Malinen 			if (pos)
388cd4e3c3eSJouni Malinen 				*pos++ = '\0';
389cd4e3c3eSJouni Malinen 		}
390cd4e3c3eSJouni Malinen 	}
391cd4e3c3eSJouni Malinen 	h = dut->cmds;
392cd4e3c3eSJouni Malinen 	while (h) {
393cd4e3c3eSJouni Malinen 		if (strcasecmp(cmd, h->cmd) == 0)
394cd4e3c3eSJouni Malinen 			break;
395cd4e3c3eSJouni Malinen 		h = h->next;
396cd4e3c3eSJouni Malinen 	}
397cd4e3c3eSJouni Malinen 
398cd4e3c3eSJouni Malinen 	if (h == NULL) {
399cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Unknown command: '%s'",
400cd4e3c3eSJouni Malinen 				cmd);
401cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID,
402cd4e3c3eSJouni Malinen 			  "errorCode,Unknown command");
403cd4e3c3eSJouni Malinen 		goto out;
404cd4e3c3eSJouni Malinen 	}
405cd4e3c3eSJouni Malinen 
406cd4e3c3eSJouni Malinen 	if (h->validate && h->validate(&c) < 0) {
407cd4e3c3eSJouni Malinen 	invalid_params:
408cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Invalid parameters");
409cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid "
410cd4e3c3eSJouni Malinen 			  "parameters");
411cd4e3c3eSJouni Malinen 		goto out;
412cd4e3c3eSJouni Malinen 	}
413cd4e3c3eSJouni Malinen 
4140fee701cSJouni Malinen 	dut->response_sent = 0;
415cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_RUNNING, NULL);
416cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "Run command: %s", cmd);
417cd4e3c3eSJouni Malinen 	res = h->process(dut, conn, &c);
41826a5b76dSJouni Malinen 	switch (res) {
41926a5b76dSJouni Malinen 	case ERROR_SEND_STATUS:
420cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, NULL);
42126a5b76dSJouni Malinen 		break;
42226a5b76dSJouni Malinen 	case INVALID_SEND_STATUS:
423cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, NULL);
42426a5b76dSJouni Malinen 		break;
42526a5b76dSJouni Malinen 	case STATUS_SENT:
42626a5b76dSJouni Malinen 		break;
42726a5b76dSJouni Malinen 	case SUCCESS_SEND_STATUS:
428cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, NULL);
42926a5b76dSJouni Malinen 		break;
43026a5b76dSJouni Malinen 	}
431cd4e3c3eSJouni Malinen 
4320fee701cSJouni Malinen 	if (!conn->waiting_completion && dut->response_sent != 2) {
4330fee701cSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR,
4340fee701cSJouni Malinen 				"ERROR: Unexpected number of status lines sent (%d) for command '%s'",
4350fee701cSJouni Malinen 				dut->response_sent, cmd);
4360fee701cSJouni Malinen 	}
4370fee701cSJouni Malinen 
438cd4e3c3eSJouni Malinen out:
439cd4e3c3eSJouni Malinen 	if (dut->debug_level < DUT_MSG_INFO) {
440cd4e3c3eSJouni Malinen 		pos2 = txt;
441cd4e3c3eSJouni Malinen 		*pos2++ = '\\';
442cd4e3c3eSJouni Malinen 		memset(pos2, '-', 69);
443cd4e3c3eSJouni Malinen 		pos2 += 69;
444cd4e3c3eSJouni Malinen 		*pos2++ = '/';
445cd4e3c3eSJouni Malinen 		*pos2 = '\0';
446cd4e3c3eSJouni Malinen 		printf("\n%s\n\n", txt);
447cd4e3c3eSJouni Malinen 	}
448cd4e3c3eSJouni Malinen }
449cd4e3c3eSJouni Malinen 
450cd4e3c3eSJouni Malinen 
451cd4e3c3eSJouni Malinen static void process_conn(struct sigma_dut *dut, struct sigma_conn *conn)
452cd4e3c3eSJouni Malinen {
453cd4e3c3eSJouni Malinen 	ssize_t res;
454cd4e3c3eSJouni Malinen 	int i;
455cd4e3c3eSJouni Malinen 
456cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Read from %s:%d",
457cd4e3c3eSJouni Malinen 			inet_ntoa(conn->addr.sin_addr),
458cd4e3c3eSJouni Malinen 			ntohs(conn->addr.sin_port));
459cd4e3c3eSJouni Malinen 
460cd4e3c3eSJouni Malinen 	res = recv(conn->s, conn->buf + conn->pos, MAX_CMD_LEN + 5 - conn->pos,
461cd4e3c3eSJouni Malinen 		   0);
462cd4e3c3eSJouni Malinen 	if (res < 0) {
463cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "recv: %s",
464cd4e3c3eSJouni Malinen 				strerror(errno));
465cd4e3c3eSJouni Malinen 	}
466cd4e3c3eSJouni Malinen 	if (res <= 0) {
467cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Close connection from "
468cd4e3c3eSJouni Malinen 				"%s:%d",
469cd4e3c3eSJouni Malinen 				inet_ntoa(conn->addr.sin_addr),
470cd4e3c3eSJouni Malinen 				ntohs(conn->addr.sin_port));
471cd4e3c3eSJouni Malinen 		shutdown(conn->s, SHUT_RDWR);
472cd4e3c3eSJouni Malinen 		close(conn->s);
473cd4e3c3eSJouni Malinen 		conn->s = -1;
474cd4e3c3eSJouni Malinen 		return;
475cd4e3c3eSJouni Malinen 	}
476cd4e3c3eSJouni Malinen 
477cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Received %d bytes",
478cd4e3c3eSJouni Malinen 			(int) res);
479cd4e3c3eSJouni Malinen 
480cd4e3c3eSJouni Malinen 	for (;;) {
481cd4e3c3eSJouni Malinen 		for (i = conn->pos; i < conn->pos + res; i++) {
482cd4e3c3eSJouni Malinen 			if (conn->buf[i] == '\r' || conn->buf[i] == '\n')
483cd4e3c3eSJouni Malinen 				break;
484cd4e3c3eSJouni Malinen 		}
485cd4e3c3eSJouni Malinen 
486cd4e3c3eSJouni Malinen 		if (i == conn->pos + res) {
487cd4e3c3eSJouni Malinen 			/* Full command not yet received */
488cd4e3c3eSJouni Malinen 			conn->pos += res;
489cd4e3c3eSJouni Malinen 			if (conn->pos >= MAX_CMD_LEN + 5) {
490cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_INFO, "Too long "
491cd4e3c3eSJouni Malinen 						"command dropped");
492cd4e3c3eSJouni Malinen 				conn->pos = 0;
493cd4e3c3eSJouni Malinen 			}
494cd4e3c3eSJouni Malinen 			break;
495cd4e3c3eSJouni Malinen 		}
496cd4e3c3eSJouni Malinen 
497cd4e3c3eSJouni Malinen 		/* Full command received */
498cd4e3c3eSJouni Malinen 		conn->buf[i++] = '\0';
499cd4e3c3eSJouni Malinen 		process_cmd(dut, conn, conn->buf);
500cd4e3c3eSJouni Malinen 		while (i < conn->pos + res &&
501cd4e3c3eSJouni Malinen 		       (conn->buf[i] == '\r' || conn->buf[i] == '\n'))
502cd4e3c3eSJouni Malinen 			i++;
503cd4e3c3eSJouni Malinen 		memmove(conn->buf, &conn->buf[i], conn->pos + res - i);
504cd4e3c3eSJouni Malinen 		res = conn->pos + res - i;
505cd4e3c3eSJouni Malinen 		conn->pos = 0;
506cd4e3c3eSJouni Malinen 	}
507cd4e3c3eSJouni Malinen }
508cd4e3c3eSJouni Malinen 
509cd4e3c3eSJouni Malinen 
510cd4e3c3eSJouni Malinen static int stop_loop = 0;
511cd4e3c3eSJouni Malinen 
512cd4e3c3eSJouni Malinen #ifdef __linux__
513cd4e3c3eSJouni Malinen static void handle_term(int sig)
514cd4e3c3eSJouni Malinen {
515cd4e3c3eSJouni Malinen 	stop_loop = 1;
516091e253dSPurushottam Kushwaha 	stop_event_thread();
517cd4e3c3eSJouni Malinen 	printf("sigma_dut terminating\n");
518cd4e3c3eSJouni Malinen }
519cd4e3c3eSJouni Malinen #endif /* __linux__ */
520cd4e3c3eSJouni Malinen 
521cd4e3c3eSJouni Malinen static void run_loop(struct sigma_dut *dut)
522cd4e3c3eSJouni Malinen {
523cd4e3c3eSJouni Malinen 	struct sigma_conn conn[MAX_CONNECTIONS];
524cd4e3c3eSJouni Malinen 	int i, res, maxfd, can_accept;
525cd4e3c3eSJouni Malinen 	fd_set rfds;
526cd4e3c3eSJouni Malinen 
527cd4e3c3eSJouni Malinen 	memset(&conn, 0, sizeof(conn));
528cd4e3c3eSJouni Malinen 	for (i = 0; i < MAX_CONNECTIONS; i++)
529cd4e3c3eSJouni Malinen 		conn[i].s = -1;
530cd4e3c3eSJouni Malinen 
531cd4e3c3eSJouni Malinen #ifdef __linux__
532cd4e3c3eSJouni Malinen 	signal(SIGINT, handle_term);
533cd4e3c3eSJouni Malinen 	signal(SIGTERM, handle_term);
534cd4e3c3eSJouni Malinen 	signal(SIGPIPE, SIG_IGN);
535cd4e3c3eSJouni Malinen #endif /* __linux__ */
536cd4e3c3eSJouni Malinen 
537cd4e3c3eSJouni Malinen 	while (!stop_loop) {
538cd4e3c3eSJouni Malinen 		FD_ZERO(&rfds);
539cd4e3c3eSJouni Malinen 		maxfd = -1;
540cd4e3c3eSJouni Malinen 		can_accept = 0;
541cd4e3c3eSJouni Malinen 		for (i = 0; i < MAX_CONNECTIONS; i++) {
542cd4e3c3eSJouni Malinen 			if (conn[i].s >= 0) {
543cd4e3c3eSJouni Malinen 				FD_SET(conn[i].s, &rfds);
544cd4e3c3eSJouni Malinen 				if (conn[i].s > maxfd)
545cd4e3c3eSJouni Malinen 					maxfd = conn[i].s;
546cd4e3c3eSJouni Malinen 			} else if (!conn[i].waiting_completion)
547cd4e3c3eSJouni Malinen 				can_accept = 1;
548cd4e3c3eSJouni Malinen 		}
549cd4e3c3eSJouni Malinen 
550cd4e3c3eSJouni Malinen 		if (can_accept) {
551cd4e3c3eSJouni Malinen 			FD_SET(dut->s, &rfds);
552cd4e3c3eSJouni Malinen 			if (dut->s > maxfd)
553cd4e3c3eSJouni Malinen 				maxfd = dut->s;
554cd4e3c3eSJouni Malinen 		}
555cd4e3c3eSJouni Malinen 
556cd4e3c3eSJouni Malinen 
557cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for next "
558cd4e3c3eSJouni Malinen 				"command (can_accept=%d)", can_accept);
559cd4e3c3eSJouni Malinen 		res = select(maxfd + 1, &rfds, NULL, NULL, NULL);
560cd4e3c3eSJouni Malinen 		if (res < 0) {
561cd4e3c3eSJouni Malinen 			perror("select");
562cd4e3c3eSJouni Malinen 			if (!stop_loop)
563cd4e3c3eSJouni Malinen 				sleep(1);
564cd4e3c3eSJouni Malinen 			continue;
565cd4e3c3eSJouni Malinen 		}
566cd4e3c3eSJouni Malinen 
567cd4e3c3eSJouni Malinen 		if (!res) {
568cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Nothing ready");
569cd4e3c3eSJouni Malinen 			sleep(1);
570cd4e3c3eSJouni Malinen 			continue;
571cd4e3c3eSJouni Malinen 		}
572cd4e3c3eSJouni Malinen 
573cd4e3c3eSJouni Malinen 		if (FD_ISSET(dut->s, &rfds)) {
574cd4e3c3eSJouni Malinen 			for (i = 0; i < MAX_CONNECTIONS; i++) {
575cd4e3c3eSJouni Malinen 				if (conn[i].s < 0 &&
576cd4e3c3eSJouni Malinen 				    !conn[i].waiting_completion)
577cd4e3c3eSJouni Malinen 					break;
578cd4e3c3eSJouni Malinen 			}
579cd4e3c3eSJouni Malinen 			if (i == MAX_CONNECTIONS) {
580cd4e3c3eSJouni Malinen 				/*
581cd4e3c3eSJouni Malinen 				 * This cannot really happen since can_accept
582cd4e3c3eSJouni Malinen 				 * would not be set to one.
583cd4e3c3eSJouni Malinen 				 */
584cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_DEBUG,
585cd4e3c3eSJouni Malinen 						"No room for new connection");
586cd4e3c3eSJouni Malinen 				continue;
587cd4e3c3eSJouni Malinen 			}
588cd4e3c3eSJouni Malinen 			conn[i].addrlen = sizeof(conn[i].addr);
589cd4e3c3eSJouni Malinen 			conn[i].s = accept(dut->s,
590cd4e3c3eSJouni Malinen 					   (struct sockaddr *) &conn[i].addr,
591cd4e3c3eSJouni Malinen 					   &conn[i].addrlen);
592cd4e3c3eSJouni Malinen 			if (conn[i].s < 0) {
593cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_INFO,
594cd4e3c3eSJouni Malinen 						"accept: %s",
595cd4e3c3eSJouni Malinen 						strerror(errno));
596cd4e3c3eSJouni Malinen 				continue;
597cd4e3c3eSJouni Malinen 			}
598cd4e3c3eSJouni Malinen 
599cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG,
600cd4e3c3eSJouni Malinen 					"Connection %d from %s:%d", i,
601cd4e3c3eSJouni Malinen 					inet_ntoa(conn[i].addr.sin_addr),
602cd4e3c3eSJouni Malinen 					ntohs(conn[i].addr.sin_port));
603cd4e3c3eSJouni Malinen 			conn[i].pos = 0;
604cd4e3c3eSJouni Malinen 		}
605cd4e3c3eSJouni Malinen 
606cd4e3c3eSJouni Malinen 		for (i = 0; i < MAX_CONNECTIONS; i++) {
607cd4e3c3eSJouni Malinen 			if (conn[i].s < 0)
608cd4e3c3eSJouni Malinen 				continue;
609cd4e3c3eSJouni Malinen 			if (FD_ISSET(conn[i].s, &rfds))
610cd4e3c3eSJouni Malinen 				process_conn(dut, &conn[i]);
611cd4e3c3eSJouni Malinen 		}
612cd4e3c3eSJouni Malinen 	}
613cd4e3c3eSJouni Malinen }
614cd4e3c3eSJouni Malinen 
615cd4e3c3eSJouni Malinen 
616cd4e3c3eSJouni Malinen static int run_local_cmd(int port, char *lcmd)
617cd4e3c3eSJouni Malinen {
618cd4e3c3eSJouni Malinen 	int s, len;
619cd4e3c3eSJouni Malinen 	struct sockaddr_in addr;
620cd4e3c3eSJouni Malinen 	char cmd[MAX_CMD_LEN];
621cd4e3c3eSJouni Malinen 	ssize_t res;
622cd4e3c3eSJouni Malinen 	int count;
623cd4e3c3eSJouni Malinen 	char resp[MAX_CMD_LEN];
624cd4e3c3eSJouni Malinen 	int pos;
625cd4e3c3eSJouni Malinen 
626cd4e3c3eSJouni Malinen 
627cd4e3c3eSJouni Malinen 	if (strlen(lcmd) > sizeof(cmd) - 4) {
628cd4e3c3eSJouni Malinen 		printf("Too long command\n");
629cd4e3c3eSJouni Malinen 		return -1;
630cd4e3c3eSJouni Malinen 	}
631cd4e3c3eSJouni Malinen 	len = snprintf(cmd, sizeof(cmd), "%s \r\n", lcmd);
632cd4e3c3eSJouni Malinen 
633cd4e3c3eSJouni Malinen 	memset(&addr, 0, sizeof(addr));
634cd4e3c3eSJouni Malinen 	addr.sin_family = AF_INET;
635cd4e3c3eSJouni Malinen 	inet_aton("127.0.0.1", &addr.sin_addr);
636cd4e3c3eSJouni Malinen 	addr.sin_port = htons(port);
637cd4e3c3eSJouni Malinen 
638cd4e3c3eSJouni Malinen 	/* Make sure we do not get stuck indefinitely */
639cd4e3c3eSJouni Malinen 	alarm(150);
640cd4e3c3eSJouni Malinen 
641cd4e3c3eSJouni Malinen 	s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
642cd4e3c3eSJouni Malinen 	if (s < 0) {
643cd4e3c3eSJouni Malinen 		perror("socket");
644cd4e3c3eSJouni Malinen 		return -1;
645cd4e3c3eSJouni Malinen 	}
646cd4e3c3eSJouni Malinen 
647cd4e3c3eSJouni Malinen 	if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
648cd4e3c3eSJouni Malinen 		perror("connect");
649cd4e3c3eSJouni Malinen 		close(s);
650cd4e3c3eSJouni Malinen 		return -1;
651cd4e3c3eSJouni Malinen 	}
652cd4e3c3eSJouni Malinen 
653cd4e3c3eSJouni Malinen 	res = send(s, cmd, len, 0);
654cd4e3c3eSJouni Malinen 	if (res < 0) {
655cd4e3c3eSJouni Malinen 		perror("send");
656cd4e3c3eSJouni Malinen 		close(s);
657cd4e3c3eSJouni Malinen 		return -1;
658cd4e3c3eSJouni Malinen 	}
659cd4e3c3eSJouni Malinen 	if (res != len) {
660cd4e3c3eSJouni Malinen 		printf("Unexpected send result: %d (expected %d)\n",
661cd4e3c3eSJouni Malinen 		       (int) res, len);
662cd4e3c3eSJouni Malinen 		close(s);
663cd4e3c3eSJouni Malinen 		return -1;
664cd4e3c3eSJouni Malinen 	}
665cd4e3c3eSJouni Malinen 
666cd4e3c3eSJouni Malinen 	count = 0;
667cd4e3c3eSJouni Malinen 	pos = 0;
668cd4e3c3eSJouni Malinen 	len = 0;
669cd4e3c3eSJouni Malinen 	for (;;) {
670cd4e3c3eSJouni Malinen 		char *e;
671cd4e3c3eSJouni Malinen 		res = recv(s, resp + len, sizeof(resp) - len, 0);
672cd4e3c3eSJouni Malinen 		if (res < 0) {
673cd4e3c3eSJouni Malinen 			perror("recv");
674cd4e3c3eSJouni Malinen 			close(s);
675cd4e3c3eSJouni Malinen 			return -1;
676cd4e3c3eSJouni Malinen 		}
677cd4e3c3eSJouni Malinen 		if (res == 0) {
678cd4e3c3eSJouni Malinen 			printf("Could not read response\n");
679cd4e3c3eSJouni Malinen 			close(s);
680cd4e3c3eSJouni Malinen 			return -1;
681cd4e3c3eSJouni Malinen 		}
682cd4e3c3eSJouni Malinen 		len += res;
683cd4e3c3eSJouni Malinen 	next_line:
684cd4e3c3eSJouni Malinen 		e = memchr(resp + pos, '\r', len - pos);
685cd4e3c3eSJouni Malinen 		if (e == NULL)
686cd4e3c3eSJouni Malinen 			continue;
687cd4e3c3eSJouni Malinen 		*e++ = '\0';
688cd4e3c3eSJouni Malinen 		if (e - resp < len && *e == '\n')
689cd4e3c3eSJouni Malinen 			*e++ = '\n';
690cd4e3c3eSJouni Malinen 		printf("%s\n", resp + pos);
691cd4e3c3eSJouni Malinen 		if (strncasecmp(resp + pos, "status,RUNNING", 14) != 0)
692cd4e3c3eSJouni Malinen 			break;
693cd4e3c3eSJouni Malinen 		count++;
694cd4e3c3eSJouni Malinen 		if (count == 2)
695cd4e3c3eSJouni Malinen 			break;
696cd4e3c3eSJouni Malinen 		pos = e - resp;
697cd4e3c3eSJouni Malinen 		goto next_line;
698cd4e3c3eSJouni Malinen 	}
699cd4e3c3eSJouni Malinen 
700cd4e3c3eSJouni Malinen 	close(s);
701cd4e3c3eSJouni Malinen 
702cd4e3c3eSJouni Malinen 	return 0;
703cd4e3c3eSJouni Malinen }
704cd4e3c3eSJouni Malinen 
705cd4e3c3eSJouni Malinen 
706091e253dSPurushottam Kushwaha static char * determine_sigma_p2p_ifname(void)
707f2af39bfSDanny Segal {
708f2af39bfSDanny Segal 	char buf[256];
709f2af39bfSDanny Segal 	struct wpa_ctrl *ctrl;
710f2af39bfSDanny Segal 
711f2af39bfSDanny Segal 	if (sigma_p2p_ifname)
712091e253dSPurushottam Kushwaha 		return sigma_p2p_ifname;
713f2af39bfSDanny Segal 
714f2af39bfSDanny Segal 	snprintf(buf, sizeof(buf), "p2p-dev-%s", get_station_ifname());
715f2af39bfSDanny Segal 	ctrl = open_wpa_mon(buf);
716f2af39bfSDanny Segal 	if (ctrl) {
717f2af39bfSDanny Segal 		wpa_ctrl_detach(ctrl);
718f2af39bfSDanny Segal 		wpa_ctrl_close(ctrl);
719f2af39bfSDanny Segal 		sigma_p2p_ifname_buf = strdup(buf);
720f2af39bfSDanny Segal 		sigma_p2p_ifname = sigma_p2p_ifname_buf;
721f2af39bfSDanny Segal 		sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
722f2af39bfSDanny Segal 				"Using interface %s for P2P operations instead of interface %s",
723f2af39bfSDanny Segal 				sigma_p2p_ifname ? sigma_p2p_ifname : "NULL",
724f2af39bfSDanny Segal 				get_station_ifname());
725f2af39bfSDanny Segal 	} else {
726f2af39bfSDanny Segal 		sigma_p2p_ifname = get_station_ifname();
727f2af39bfSDanny Segal 	}
728091e253dSPurushottam Kushwaha 
729091e253dSPurushottam Kushwaha 	return sigma_p2p_ifname;
730f2af39bfSDanny Segal }
731f2af39bfSDanny Segal 
732f2af39bfSDanny Segal 
733*d06f100bSPriyadharshini Gowthaman static int get_nl80211_config_enable_option(struct sigma_dut *dut)
734*d06f100bSPriyadharshini Gowthaman {
735*d06f100bSPriyadharshini Gowthaman 	char cmd[100], result[5];
736*d06f100bSPriyadharshini Gowthaman 	FILE *f;
737*d06f100bSPriyadharshini Gowthaman 	size_t len;
738*d06f100bSPriyadharshini Gowthaman 	int ap_nl80211_enable;
739*d06f100bSPriyadharshini Gowthaman 
740*d06f100bSPriyadharshini Gowthaman 	snprintf(cmd, sizeof(cmd), "uci get qcacfg80211.config.enable");
741*d06f100bSPriyadharshini Gowthaman 	f = popen(cmd, "r");
742*d06f100bSPriyadharshini Gowthaman 	if (!f)
743*d06f100bSPriyadharshini Gowthaman 		return -1;
744*d06f100bSPriyadharshini Gowthaman 
745*d06f100bSPriyadharshini Gowthaman 	len = fread(result, 1, sizeof(result) - 1, f);
746*d06f100bSPriyadharshini Gowthaman 	pclose(f);
747*d06f100bSPriyadharshini Gowthaman 
748*d06f100bSPriyadharshini Gowthaman 	if (len == 0)
749*d06f100bSPriyadharshini Gowthaman 		return -1;
750*d06f100bSPriyadharshini Gowthaman 
751*d06f100bSPriyadharshini Gowthaman 	result[len] = '\0';
752*d06f100bSPriyadharshini Gowthaman 	ap_nl80211_enable = atoi(result);
753*d06f100bSPriyadharshini Gowthaman 
754*d06f100bSPriyadharshini Gowthaman 	if (ap_nl80211_enable)
755*d06f100bSPriyadharshini Gowthaman 		dut->priv_cmd = "cfg80211tool";
756*d06f100bSPriyadharshini Gowthaman 
757*d06f100bSPriyadharshini Gowthaman 	return 0;
758*d06f100bSPriyadharshini Gowthaman }
759*d06f100bSPriyadharshini Gowthaman 
760*d06f100bSPriyadharshini Gowthaman 
761cd4e3c3eSJouni Malinen static void set_defaults(struct sigma_dut *dut)
762cd4e3c3eSJouni Malinen {
763cd4e3c3eSJouni Malinen 	dut->ap_p2p_cross_connect = -1;
764cd4e3c3eSJouni Malinen 	dut->ap_chwidth = AP_AUTO;
765bf8af292SPradeep Reddy Potteti 	dut->default_11na_ap_chwidth = AP_AUTO;
766bf8af292SPradeep Reddy Potteti 	dut->default_11ng_ap_chwidth = AP_AUTO;
767cd4e3c3eSJouni Malinen 	/* by default, enable writing of traffic stream stats */
768cd4e3c3eSJouni Malinen 	dut->write_stats = 1;
769*d06f100bSPriyadharshini Gowthaman 	dut->priv_cmd = "iwpriv";
770cd4e3c3eSJouni Malinen }
771cd4e3c3eSJouni Malinen 
772cd4e3c3eSJouni Malinen 
773cd4e3c3eSJouni Malinen static const char * const license1 =
774cd4e3c3eSJouni Malinen "sigma_dut - WFA Sigma DUT/CA\n"
775cd4e3c3eSJouni Malinen "----------------------------\n"
776cd4e3c3eSJouni Malinen "\n"
777cd4e3c3eSJouni Malinen "Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
7789d7e31d5SJouni Malinen "Copyright (c) 2011-2017, Qualcomm Atheros, Inc.\n"
7795b16b51eSJouni Malinen "Copyright (c) 2018-2019, The Linux Foundation\n"
780cd4e3c3eSJouni Malinen "All Rights Reserved.\n"
781cd4e3c3eSJouni Malinen "Licensed under the Clear BSD license.\n"
782cd4e3c3eSJouni Malinen "\n";
783cd4e3c3eSJouni Malinen static const char * const license2 =
784cd4e3c3eSJouni Malinen "Redistribution and use in source and binary forms, with or without\n"
785cd4e3c3eSJouni Malinen "modification, are permitted (subject to the limitations in the\n"
786cd4e3c3eSJouni Malinen "disclaimer below) provided that the following conditions are met:\n"
787cd4e3c3eSJouni Malinen "\n";
788cd4e3c3eSJouni Malinen static const char * const license3 =
789cd4e3c3eSJouni Malinen "* Redistributions of source code must retain the above copyright notice,\n"
790cd4e3c3eSJouni Malinen "  this list of conditions and the following disclaimer.\n"
791cd4e3c3eSJouni Malinen "\n"
792cd4e3c3eSJouni Malinen "* Redistributions in binary form must reproduce the above copyright\n"
793cd4e3c3eSJouni Malinen "  notice, this list of conditions and the following disclaimer in the\n"
794cd4e3c3eSJouni Malinen "  documentation and/or other materials provided with the distribution.\n"
795cd4e3c3eSJouni Malinen "\n"
796cd4e3c3eSJouni Malinen "* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
797cd4e3c3eSJouni Malinen "  contributors may be used to endorse or promote products derived from\n"
798cd4e3c3eSJouni Malinen "  this software without specific prior written permission.\n"
799cd4e3c3eSJouni Malinen "\n";
800cd4e3c3eSJouni Malinen static const char * const license4 =
801cd4e3c3eSJouni Malinen "NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
802cd4e3c3eSJouni Malinen "BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
803cd4e3c3eSJouni Malinen "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
804cd4e3c3eSJouni Malinen "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
805cd4e3c3eSJouni Malinen "FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
806cd4e3c3eSJouni Malinen "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
807cd4e3c3eSJouni Malinen "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
808cd4e3c3eSJouni Malinen "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
809cd4e3c3eSJouni Malinen "USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
810cd4e3c3eSJouni Malinen "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
811cd4e3c3eSJouni Malinen "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
812cd4e3c3eSJouni Malinen "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
813cd4e3c3eSJouni Malinen 
814cd4e3c3eSJouni Malinen 
815cd4e3c3eSJouni Malinen static void print_license(void)
816cd4e3c3eSJouni Malinen {
817cd4e3c3eSJouni Malinen 	printf("%s%s%s%s\n",
818cd4e3c3eSJouni Malinen 	       license1, license2, license3, license4);
819cd4e3c3eSJouni Malinen }
820cd4e3c3eSJouni Malinen 
821cd4e3c3eSJouni Malinen 
822cd4e3c3eSJouni Malinen int main(int argc, char *argv[])
823cd4e3c3eSJouni Malinen {
824cd4e3c3eSJouni Malinen 	int c;
825cd4e3c3eSJouni Malinen 	int daemonize = 0;
826cd4e3c3eSJouni Malinen 	int port = SIGMA_DUT_PORT;
827cd4e3c3eSJouni Malinen 	char *local_cmd = NULL;
828091e253dSPurushottam Kushwaha 	int internal_dhcp_enabled = 0;
829cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
830cd4e3c3eSJouni Malinen 	char *env_str = NULL;
831cd4e3c3eSJouni Malinen 	char buf[20];
832cd4e3c3eSJouni Malinen 	char *sigma_ctrl_sock = NULL; /* env used for QNX */
833cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
834cd4e3c3eSJouni Malinen 
835cd4e3c3eSJouni Malinen 	memset(&sigma_dut, 0, sizeof(sigma_dut));
836cd4e3c3eSJouni Malinen 	sigma_dut.debug_level = DUT_MSG_INFO;
837cd4e3c3eSJouni Malinen 	sigma_dut.default_timeout = 120;
838cd4e3c3eSJouni Malinen 	sigma_dut.dialog_token = 0;
839d86e5828SJouni Malinen 	sigma_dut.dpp_conf_id = -1;
84063d5041cSJouni Malinen 	sigma_dut.dpp_local_bootstrap = -1;
841ac6c511cSArif Hussain 	sigma_dut.sta_nss = 2; /* Make default nss 2 */
8428863ec7cSPeng Xu 	sigma_dut.trans_proto = NAN_TRANSPORT_PROTOCOL_DEFAULT;
8438863ec7cSPeng Xu 	sigma_dut.trans_port = NAN_TRANSPORT_PORT_DEFAULT;
844cd4e3c3eSJouni Malinen 	set_defaults(&sigma_dut);
845cd4e3c3eSJouni Malinen 
846cd4e3c3eSJouni Malinen 	for (;;) {
847cd4e3c3eSJouni Malinen 		c = getopt(argc, argv,
8483e8267ecSAlexei Avshalom Lazar 			   "aAb:Bc:C:dDE:e:fF:gGhH:j:J:i:Ik:l:L:m:M:nN:o:O:p:P:qr:R:s:S:tT:uv:VWw:x:y:z:");
849cd4e3c3eSJouni Malinen 		if (c < 0)
850cd4e3c3eSJouni Malinen 			break;
851cd4e3c3eSJouni Malinen 		switch (c) {
852cd4e3c3eSJouni Malinen 		case 'a':
853cd4e3c3eSJouni Malinen 			sigma_dut.ap_anqpserver = 1;
854cd4e3c3eSJouni Malinen 			break;
855cd4e3c3eSJouni Malinen 		case 'b':
856cd4e3c3eSJouni Malinen 			sigma_dut.bridge = optarg;
857cd4e3c3eSJouni Malinen 			break;
858cd4e3c3eSJouni Malinen 		case 'B':
859cd4e3c3eSJouni Malinen 			daemonize++;
860cd4e3c3eSJouni Malinen 			break;
861cd4e3c3eSJouni Malinen 		case 'C':
862cd4e3c3eSJouni Malinen 			sigma_cert_path = optarg;
863cd4e3c3eSJouni Malinen 			break;
864cd4e3c3eSJouni Malinen 		case 'd':
865cd4e3c3eSJouni Malinen 			if (sigma_dut.debug_level > 0)
866cd4e3c3eSJouni Malinen 				sigma_dut.debug_level--;
867cd4e3c3eSJouni Malinen 			break;
868cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
869cd4e3c3eSJouni Malinen 		case 'E':
870cd4e3c3eSJouni Malinen 			sigma_ctrl_sock = optarg;
871cd4e3c3eSJouni Malinen 			break;
872cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
873cd4e3c3eSJouni Malinen 		case 'D':
874cd4e3c3eSJouni Malinen 			sigma_dut.stdout_debug = 1;
875cd4e3c3eSJouni Malinen 			break;
876cd4e3c3eSJouni Malinen 		case 'e':
877cd4e3c3eSJouni Malinen 			sigma_dut.hostapd_entropy_log = optarg;
878cd4e3c3eSJouni Malinen 			break;
879cd4e3c3eSJouni Malinen 		case 'f':
880cd4e3c3eSJouni Malinen 			/* Disable writing stats */
881cd4e3c3eSJouni Malinen 			sigma_dut.write_stats = 0;
882cd4e3c3eSJouni Malinen 			break;
883d6bf1b4aSJouni Malinen 		case 'F':
884d6bf1b4aSJouni Malinen 			sigma_dut.hostapd_bin = optarg;
885d6bf1b4aSJouni Malinen 			break;
886091e253dSPurushottam Kushwaha 		case 'g':
887091e253dSPurushottam Kushwaha 			/* Enable internal processing of P2P group formation
888091e253dSPurushottam Kushwaha 			 * events to start/stop DHCP server/client. */
889091e253dSPurushottam Kushwaha 			internal_dhcp_enabled = 1;
890091e253dSPurushottam Kushwaha 			break;
891d6bf1b4aSJouni Malinen 		case 'G':
892d6bf1b4aSJouni Malinen 			sigma_dut.use_hostapd_pid_file = 1;
893d6bf1b4aSJouni Malinen 			break;
894cd4e3c3eSJouni Malinen 		case 'H':
895cd4e3c3eSJouni Malinen 			sigma_dut.hostapd_debug_log = optarg;
896cd4e3c3eSJouni Malinen 			break;
897cd4e3c3eSJouni Malinen 		case 'I':
898cd4e3c3eSJouni Malinen 			print_license();
899cd4e3c3eSJouni Malinen 			exit(0);
900cd4e3c3eSJouni Malinen 			break;
901d6bf1b4aSJouni Malinen 		case 'j':
902d6bf1b4aSJouni Malinen 			sigma_dut.hostapd_ifname = optarg;
903d6bf1b4aSJouni Malinen 			break;
9043e8267ecSAlexei Avshalom Lazar 		case 'J':
9053e8267ecSAlexei Avshalom Lazar 			sigma_dut.wpa_supplicant_debug_log = optarg;
9063e8267ecSAlexei Avshalom Lazar 			break;
907cd4e3c3eSJouni Malinen 		case 'l':
908cd4e3c3eSJouni Malinen 			local_cmd = optarg;
909cd4e3c3eSJouni Malinen 			break;
910cd4e3c3eSJouni Malinen 		case 'L':
911cd4e3c3eSJouni Malinen 			sigma_dut.summary_log = optarg;
912cd4e3c3eSJouni Malinen 			break;
913cd4e3c3eSJouni Malinen 		case 'p':
914cd4e3c3eSJouni Malinen 			port = atoi(optarg);
915cd4e3c3eSJouni Malinen 			break;
916f2af39bfSDanny Segal 		case 'P':
917f2af39bfSDanny Segal 			sigma_p2p_ifname = optarg;
918f2af39bfSDanny Segal 			break;
919cd4e3c3eSJouni Malinen 		case 'q':
920cd4e3c3eSJouni Malinen 			sigma_dut.debug_level++;
921cd4e3c3eSJouni Malinen 			break;
922cd4e3c3eSJouni Malinen 		case 'r':
923cd4e3c3eSJouni Malinen 			if (strcmp(optarg, "HT40") == 0) {
924bf8af292SPradeep Reddy Potteti 				sigma_dut.default_11na_ap_chwidth = AP_40;
925bf8af292SPradeep Reddy Potteti 			} else if (strcmp(optarg, "2.4_HT40") == 0) {
926bf8af292SPradeep Reddy Potteti 				sigma_dut.default_11ng_ap_chwidth = AP_40;
927cd4e3c3eSJouni Malinen 			} else {
928cd4e3c3eSJouni Malinen 				printf("Unsupported -r value\n");
929cd4e3c3eSJouni Malinen 				exit(1);
930cd4e3c3eSJouni Malinen 			}
931cd4e3c3eSJouni Malinen 			break;
932cd4e3c3eSJouni Malinen 		case 'R': {
933cd4e3c3eSJouni Malinen 			static int num_radio = 0;
934cd4e3c3eSJouni Malinen 			static char **radio_ptr = sigma_radio_ifname;
935cd4e3c3eSJouni Malinen 
936cd4e3c3eSJouni Malinen 			num_radio++;
937cd4e3c3eSJouni Malinen 			if (num_radio > MAX_RADIO) {
938cd4e3c3eSJouni Malinen 				printf("Multiple radio support limit (%d) exceeded\n",
939cd4e3c3eSJouni Malinen 				       MAX_RADIO);
940cd4e3c3eSJouni Malinen 				exit(1);
941cd4e3c3eSJouni Malinen 			}
942cd4e3c3eSJouni Malinen 			*radio_ptr++ = optarg;
943cd4e3c3eSJouni Malinen 			break;
944cd4e3c3eSJouni Malinen 		}
945cd4e3c3eSJouni Malinen 		case 's':
946cd4e3c3eSJouni Malinen 			sigma_dut.sniffer_ifname = optarg;
947cd4e3c3eSJouni Malinen 			break;
948cd4e3c3eSJouni Malinen 		case 't':
949cd4e3c3eSJouni Malinen 			sigma_dut.no_timestamps = 1;
950cd4e3c3eSJouni Malinen 			break;
951cd4e3c3eSJouni Malinen 		case 'T':
952cd4e3c3eSJouni Malinen 			sigma_dut.throughput_pktsize = atoi(optarg);
953c2493f83SJouni Malinen 			if (sigma_dut.throughput_pktsize == 0) {
954cd4e3c3eSJouni Malinen 				printf("Invalid -T value\n");
955cd4e3c3eSJouni Malinen 				exit(0);
956cd4e3c3eSJouni Malinen 			}
957cd4e3c3eSJouni Malinen 			break;
958cd4e3c3eSJouni Malinen 		case 'm':
959cd4e3c3eSJouni Malinen 			sigma_dut.set_macaddr = optarg;
960cd4e3c3eSJouni Malinen 			break;
961cd4e3c3eSJouni Malinen 		case 'M':
962cd4e3c3eSJouni Malinen 			sigma_main_ifname = optarg;
963cd4e3c3eSJouni Malinen 			break;
964cd4e3c3eSJouni Malinen 		case 'n':
965cd4e3c3eSJouni Malinen 			sigma_dut.no_ip_addr_set = 1;
966cd4e3c3eSJouni Malinen 			break;
9675db3b104SJouni Malinen 		case 'N':
9685db3b104SJouni Malinen 			sigma_dut.vendor_name = optarg;
9695db3b104SJouni Malinen 			break;
9705db3b104SJouni Malinen 		case 'o':
9715db3b104SJouni Malinen 			sigma_dut.model_name = optarg;
9725db3b104SJouni Malinen 			break;
9735db3b104SJouni Malinen 		case 'O':
9745db3b104SJouni Malinen 			sigma_dut.version_name = optarg;
9755db3b104SJouni Malinen 			break;
976cd4e3c3eSJouni Malinen 		case 'S':
977cd4e3c3eSJouni Malinen 			sigma_station_ifname = optarg;
978cd4e3c3eSJouni Malinen 			break;
979cd4e3c3eSJouni Malinen 		case 'w':
980cd4e3c3eSJouni Malinen 			sigma_hapd_ctrl = optarg;
981cd4e3c3eSJouni Malinen 			sigma_wpas_ctrl = optarg;
982cd4e3c3eSJouni Malinen 			break;
983cd4e3c3eSJouni Malinen 		case 'i':
984cd4e3c3eSJouni Malinen 			ap_inet_addr = optarg;
985cd4e3c3eSJouni Malinen 			break;
986cd4e3c3eSJouni Malinen 		case 'k':
987cd4e3c3eSJouni Malinen 			ap_inet_mask = optarg;
988cd4e3c3eSJouni Malinen 			break;
989cd4e3c3eSJouni Malinen 		case 'c':
990cd4e3c3eSJouni Malinen 			printf("%s", optarg);
991cd4e3c3eSJouni Malinen 			if (set_wifi_chip(optarg) < 0)
992cd4e3c3eSJouni Malinen 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
993cd4e3c3eSJouni Malinen 						"WRONG CHIP TYPE: SAP will "
994cd4e3c3eSJouni Malinen 						"not load");
995cd4e3c3eSJouni Malinen 			break;
996cd4e3c3eSJouni Malinen 		case 'v':
997cd4e3c3eSJouni Malinen 			sigma_dut.version = optarg;
998cd4e3c3eSJouni Malinen 			break;
999cd4e3c3eSJouni Malinen 		case 'V':
1000cd4e3c3eSJouni Malinen 			printf("sigma_dut " SIGMA_DUT_VER "\n");
1001cd4e3c3eSJouni Malinen 			exit(0);
1002cd4e3c3eSJouni Malinen 			break;
1003cd4e3c3eSJouni Malinen 		case 'W':
1004cd4e3c3eSJouni Malinen 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1005cd4e3c3eSJouni Malinen 					"Running WMM-AC test suite");
1006cd4e3c3eSJouni Malinen 			sigma_wmm_ac = 1;
1007cd4e3c3eSJouni Malinen 			break;
1008cd4e3c3eSJouni Malinen 		case 'u':
1009cd4e3c3eSJouni Malinen 		       sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1010cd4e3c3eSJouni Malinen 				       "Use iface down/up in reset cmd");
1011cd4e3c3eSJouni Malinen 		       sigma_dut.iface_down_on_reset = 1;
1012cd4e3c3eSJouni Malinen 		       break;
101373d7af09SBala Krishna Bhamidipati 		case 'A':
101473d7af09SBala Krishna Bhamidipati 			sigma_dut.sim_no_username = 1;
101573d7af09SBala Krishna Bhamidipati 			break;
10169c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
10179c381f59SAmarnath Hullur Subramanyam 		case 'x':
10189c381f59SAmarnath Hullur Subramanyam 			if (strcmp(optarg, "sink") == 0) {
10199c381f59SAmarnath Hullur Subramanyam 				sigma_dut.wfd_device_type = 1;
10209c381f59SAmarnath Hullur Subramanyam 				sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
10219c381f59SAmarnath Hullur Subramanyam 						"Device Type is SINK");
10229c381f59SAmarnath Hullur Subramanyam 			} else if (strcmp(optarg, "source") == 0) {
10239c381f59SAmarnath Hullur Subramanyam 				sigma_dut.wfd_device_type = 0;
10249c381f59SAmarnath Hullur Subramanyam 				sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
10259c381f59SAmarnath Hullur Subramanyam 						"Device Type is SOURCE");
10269c381f59SAmarnath Hullur Subramanyam 			}
10279c381f59SAmarnath Hullur Subramanyam 			break;
10289c381f59SAmarnath Hullur Subramanyam 		case 'y':
10299c381f59SAmarnath Hullur Subramanyam 			sigma_dut.miracast_lib_path = optarg;
10309c381f59SAmarnath Hullur Subramanyam 			break;
10319c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
1032525dbfd1SRajiv Ranjan 		case 'z':
1033525dbfd1SRajiv Ranjan 			client_socket_path = optarg;
1034525dbfd1SRajiv Ranjan 			break;
1035cd4e3c3eSJouni Malinen 		case 'h':
1036cd4e3c3eSJouni Malinen 		default:
1037d6bf1b4aSJouni Malinen 			printf("usage: sigma_dut [-aABdfGqDIntuVW] [-p<port>] "
1038cd4e3c3eSJouni Malinen 			       "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
1039cd4e3c3eSJouni Malinen 				"       [-M<main ifname>] [-R<radio ifname>] "
1040f2af39bfSDanny Segal 			       "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
1041cd4e3c3eSJouni Malinen 			       "       [-T<throughput pktsize>] \\\n"
1042cd4e3c3eSJouni Malinen 			       "       [-w<wpa_supplicant/hostapd ctrl_iface "
1043cd4e3c3eSJouni Malinen 			       "dir>] \\\n"
1044cd4e3c3eSJouni Malinen 			       "       [-H <hostapd log file>] \\\n"
1045d6bf1b4aSJouni Malinen 			       "       [-F <hostapd binary path>] \\\n"
1046d6bf1b4aSJouni Malinen 			       "       [-j <hostapd ifname>] \\\n"
10473e8267ecSAlexei Avshalom Lazar 			       "       [-J <wpa_supplicant debug log>] \\\n"
1048cd4e3c3eSJouni Malinen 			       "       [-C <certificate path>] \\\n"
1049cd4e3c3eSJouni Malinen 			       "       [-v <version string>] \\\n"
1050cd4e3c3eSJouni Malinen 			       "       [-L <summary log>] \\\n"
1051cd4e3c3eSJouni Malinen 			       "       [-c <wifi chip type: WCN or ATHEROS or "
1052b692f107SSreelakshmi Konamki 			       "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
1053b692f107SSreelakshmi Konamki 			       "LINUX-WCN>] "
1054cd4e3c3eSJouni Malinen 			       "\\\n"
1055cd4e3c3eSJouni Malinen 			       "       [-i <IP address of the AP>] \\\n"
1056cd4e3c3eSJouni Malinen 			       "       [-k <subnet mask for the AP>] \\\n"
1057cd4e3c3eSJouni Malinen 			       "       [-e <hostapd entropy file>] \\\n"
10585db3b104SJouni Malinen 			       "       [-N <device_get_info vendor>] \\\n"
10595db3b104SJouni Malinen 			       "       [-o <device_get_info model>] \\\n"
10605db3b104SJouni Malinen 			       "       [-O <device_get_info version>] \\\n"
10619c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
10629c381f59SAmarnath Hullur Subramanyam 			       "       [-x <sink|source>] \\\n"
10639c381f59SAmarnath Hullur Subramanyam 			       "       [-y <Miracast library path>] \\\n"
10649c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
1065525dbfd1SRajiv Ranjan 			       "       [-z <client socket directory path \\\n"
1066525dbfd1SRajiv Ranjan 			       "       Ex: </data/vendor/wifi/sockets>] \\\n"
1067bf8af292SPradeep Reddy Potteti 			       "       [-r <HT40 or 2.4_HT40>]\n");
1068cd4e3c3eSJouni Malinen 			printf("local command: sigma_dut [-p<port>] "
1069cd4e3c3eSJouni Malinen 			       "<-l<cmd>>\n");
1070cd4e3c3eSJouni Malinen 			exit(0);
1071cd4e3c3eSJouni Malinen 			break;
1072cd4e3c3eSJouni Malinen 		}
1073cd4e3c3eSJouni Malinen 	}
1074cd4e3c3eSJouni Malinen 
1075091e253dSPurushottam Kushwaha 	sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
10769c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
10779c381f59SAmarnath Hullur Subramanyam 	miracast_init(&sigma_dut);
10789c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
1079cd4e3c3eSJouni Malinen 	if (local_cmd)
1080cd4e3c3eSJouni Malinen 		return run_local_cmd(port, local_cmd);
1081cd4e3c3eSJouni Malinen 
108208eaeba2SPradeep Reddy Potteti 	if ((wifi_chip_type == DRIVER_QNXNTO ||
108308eaeba2SPradeep Reddy Potteti 	     wifi_chip_type == DRIVER_LINUX_WCN) &&
1084cd4e3c3eSJouni Malinen 	    (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
1085cd4e3c3eSJouni Malinen 		sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
108608eaeba2SPradeep Reddy Potteti 				"Interface should be provided for QNX/LINUX-WCN driver - check option M and S");
1087cd4e3c3eSJouni Malinen 	}
1088cd4e3c3eSJouni Malinen 
1089*d06f100bSPriyadharshini Gowthaman 	if (get_openwrt_driver_type() == OPENWRT_DRIVER_ATHEROS)
1090*d06f100bSPriyadharshini Gowthaman 		get_nl80211_config_enable_option(&sigma_dut);
1091*d06f100bSPriyadharshini Gowthaman 
1092291d97daSPeng Xu #ifdef NL80211_SUPPORT
1093291d97daSPeng Xu 	sigma_dut.nl_ctx = nl80211_init(&sigma_dut);
1094291d97daSPeng Xu #endif /* NL80211_SUPPORT */
1095cd4e3c3eSJouni Malinen 	sigma_dut_register_cmds();
1096cd4e3c3eSJouni Malinen 
1097cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1098cd4e3c3eSJouni Malinen 	/* Try to open socket in other env dev */
1099cd4e3c3eSJouni Malinen 	if (sigma_ctrl_sock) {
1100cd4e3c3eSJouni Malinen 		env_str = getenv("SOCK");
1101cd4e3c3eSJouni Malinen 		if (env_str) {
1102cd4e3c3eSJouni Malinen 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1103cd4e3c3eSJouni Malinen 					"SOCK=%s", env_str);
1104cd4e3c3eSJouni Malinen 		}
1105cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
1106cd4e3c3eSJouni Malinen 		if (putenv(buf) != 0) {
1107cd4e3c3eSJouni Malinen 			sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1108cd4e3c3eSJouni Malinen 					"putenv() failed setting SOCK");
1109cd4e3c3eSJouni Malinen 			return EXIT_FAILURE;
1110cd4e3c3eSJouni Malinen 		}
1111cd4e3c3eSJouni Malinen 	}
1112cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1113cd4e3c3eSJouni Malinen 
1114cd4e3c3eSJouni Malinen 	if (open_socket(&sigma_dut, port) < 0)
1115cd4e3c3eSJouni Malinen 		return -1;
1116cd4e3c3eSJouni Malinen 
1117cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1118cd4e3c3eSJouni Malinen 	/* restore back the SOCK */
1119cd4e3c3eSJouni Malinen 	if (sigma_ctrl_sock) {
1120cd4e3c3eSJouni Malinen 		if (env_str) {
1121cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
1122cd4e3c3eSJouni Malinen 			if (putenv(buf) != 0) {
1123cd4e3c3eSJouni Malinen 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1124cd4e3c3eSJouni Malinen 						"putenv() failed setting SOCK");
1125cd4e3c3eSJouni Malinen 				return EXIT_FAILURE;
1126cd4e3c3eSJouni Malinen 			}
1127cd4e3c3eSJouni Malinen 		} else {
1128cd4e3c3eSJouni Malinen 			/* unset the env for sock */
1129cd4e3c3eSJouni Malinen 			unsetenv("SOCK");
1130cd4e3c3eSJouni Malinen 		}
1131cd4e3c3eSJouni Malinen 	}
1132cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1133cd4e3c3eSJouni Malinen 
1134cd4e3c3eSJouni Malinen 	if (daemonize) {
1135cd4e3c3eSJouni Malinen 		if (daemon(0, 0) < 0) {
1136cd4e3c3eSJouni Malinen 			perror("daemon");
1137cd4e3c3eSJouni Malinen 			exit(-1);
1138cd4e3c3eSJouni Malinen 		}
1139cd4e3c3eSJouni Malinen 	} else {
1140cd4e3c3eSJouni Malinen #ifdef __linux__
1141cd4e3c3eSJouni Malinen 		setlinebuf(stdout);
1142cd4e3c3eSJouni Malinen #endif /* __linux__ */
1143cd4e3c3eSJouni Malinen 	}
1144cd4e3c3eSJouni Malinen 
1145091e253dSPurushottam Kushwaha 	if (internal_dhcp_enabled)
1146091e253dSPurushottam Kushwaha 		p2p_create_event_thread(&sigma_dut);
1147091e253dSPurushottam Kushwaha 
1148cd4e3c3eSJouni Malinen 	run_loop(&sigma_dut);
1149cd4e3c3eSJouni Malinen 
1150cd4e3c3eSJouni Malinen #ifdef CONFIG_SNIFFER
1151cd4e3c3eSJouni Malinen 	sniffer_close(&sigma_dut);
1152cd4e3c3eSJouni Malinen #endif /* CONFIG_SNIFFER */
1153cd4e3c3eSJouni Malinen 
1154f2af39bfSDanny Segal 	free(sigma_p2p_ifname_buf);
1155cd4e3c3eSJouni Malinen 	close_socket(&sigma_dut);
11569c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
11579c381f59SAmarnath Hullur Subramanyam 	miracast_deinit(&sigma_dut);
11589c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
11590040258bSAshwini Patil 	free(sigma_dut.non_pref_ch_list);
11600040258bSAshwini Patil 	sigma_dut.non_pref_ch_list = NULL;
11615acd738cSAshwini Patil 	free(sigma_dut.btm_query_cand_list);
11625acd738cSAshwini Patil 	sigma_dut.btm_query_cand_list = NULL;
11633c367e8dSJouni Malinen 	free(sigma_dut.rsne_override);
1164ed670f4cSJouni Malinen 	free(sigma_dut.ap_sae_groups);
1165b1dd21f8SJouni Malinen 	free(sigma_dut.dpp_peer_uri);
116609550de6SJouni Malinen 	free(sigma_dut.ap_sae_passwords);
1167291d97daSPeng Xu #ifdef NL80211_SUPPORT
1168291d97daSPeng Xu 	nl80211_deinit(&sigma_dut, sigma_dut.nl_ctx);
1169291d97daSPeng Xu #endif /* NL80211_SUPPORT */
1170cd4e3c3eSJouni Malinen 	sigma_dut_unreg_cmds(&sigma_dut);
11711bde7947SAnkita Bajaj #ifdef ANDROID
11721bde7947SAnkita Bajaj 	hlp_thread_cleanup(&sigma_dut);
11731bde7947SAnkita Bajaj #endif /* ANDROID */
1174cd4e3c3eSJouni Malinen 
1175cd4e3c3eSJouni Malinen 	return 0;
1176cd4e3c3eSJouni Malinen }
1177