xref: /wlan-dirver/utils/sigma-dut/sigma_dut.c (revision f7a2cbf925c5a97f0d23d3c32665b7921dc96e4d)
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_radio_ifname[MAX_RADIO] = {};
27cd4e3c3eSJouni Malinen char *sigma_wpas_ctrl = "/var/run/wpa_supplicant/";
28cd4e3c3eSJouni Malinen char *sigma_hapd_ctrl = NULL;
29525dbfd1SRajiv Ranjan char *client_socket_path = NULL;
30cd4e3c3eSJouni Malinen char *ap_inet_addr = "192.168.43.1";
31cd4e3c3eSJouni Malinen char *ap_inet_mask = "255.255.255.0";
32cd4e3c3eSJouni Malinen char *sigma_cert_path = "/etc/wpa_supplicant";
33cd4e3c3eSJouni Malinen 
34cd4e3c3eSJouni Malinen /* For WMM-AC testing this set to 1 through argument,
35cd4e3c3eSJouni Malinen  * otherwise default WMM-PS 0 */
36cd4e3c3eSJouni Malinen int sigma_wmm_ac = 0;
37cd4e3c3eSJouni Malinen 
38cd4e3c3eSJouni Malinen 
39cd4e3c3eSJouni Malinen #ifdef ANDROID
40cd4e3c3eSJouni Malinen #include <android/log.h>
41cd4e3c3eSJouni Malinen 
422dfb1daeSVinay Gannevaram #ifdef ANDROID_WIFI_HAL
432dfb1daeSVinay Gannevaram 
wifi_hal_event_thread(void * ptr)442dfb1daeSVinay Gannevaram static void * wifi_hal_event_thread(void *ptr)
452dfb1daeSVinay Gannevaram {
462dfb1daeSVinay Gannevaram 	struct sigma_dut *dut = ptr;
472dfb1daeSVinay Gannevaram 
482dfb1daeSVinay Gannevaram 	wifi_event_loop(dut->wifi_hal_handle);
492dfb1daeSVinay Gannevaram 	pthread_exit(0);
502dfb1daeSVinay Gannevaram 
512dfb1daeSVinay Gannevaram 	return NULL;
522dfb1daeSVinay Gannevaram }
532dfb1daeSVinay Gannevaram 
542dfb1daeSVinay Gannevaram 
wifi_hal_initialize(struct sigma_dut * dut)552dfb1daeSVinay Gannevaram int wifi_hal_initialize(struct sigma_dut *dut)
562dfb1daeSVinay Gannevaram {
572dfb1daeSVinay Gannevaram 	pthread_t thread1;
582dfb1daeSVinay Gannevaram 	wifi_error err;
59c2ae961eSAjit Vaishya 	const char *ifname;
602dfb1daeSVinay Gannevaram 
612dfb1daeSVinay Gannevaram 	if (dut->wifi_hal_initialized)
622dfb1daeSVinay Gannevaram 		return 0;
632dfb1daeSVinay Gannevaram 
642dfb1daeSVinay Gannevaram 	err = wifi_initialize(&dut->wifi_hal_handle);
652dfb1daeSVinay Gannevaram 	if (err) {
662dfb1daeSVinay Gannevaram 		sigma_dut_print(dut, DUT_MSG_ERROR,
672dfb1daeSVinay Gannevaram 				"wifi hal initialize failed");
682dfb1daeSVinay Gannevaram 		return -1;
692dfb1daeSVinay Gannevaram 	}
702dfb1daeSVinay Gannevaram 
71c2ae961eSAjit Vaishya 	if (if_nametoindex(NAN_AWARE_IFACE))
72c2ae961eSAjit Vaishya 		ifname = NAN_AWARE_IFACE;
73c2ae961eSAjit Vaishya 	else
74c2ae961eSAjit Vaishya 		ifname = "wlan0";
75c2ae961eSAjit Vaishya 
762dfb1daeSVinay Gannevaram 	dut->wifi_hal_iface_handle = wifi_get_iface_handle(dut->wifi_hal_handle,
77c2ae961eSAjit Vaishya 							   (char *) ifname);
78c2ae961eSAjit Vaishya 
792dfb1daeSVinay Gannevaram 	pthread_create(&thread1, NULL, &wifi_hal_event_thread, (void *) dut);
802dfb1daeSVinay Gannevaram 	dut->wifi_hal_initialized = true;
812dfb1daeSVinay Gannevaram 
822dfb1daeSVinay Gannevaram 	return 0;
832dfb1daeSVinay Gannevaram }
842dfb1daeSVinay Gannevaram 
852dfb1daeSVinay Gannevaram #endif /* ANDROID_WIFI_HAL */
862dfb1daeSVinay Gannevaram 
872dfb1daeSVinay Gannevaram 
level_to_android_priority(int level)88cd4e3c3eSJouni Malinen static enum android_LogPriority level_to_android_priority(int level)
89cd4e3c3eSJouni Malinen {
90cd4e3c3eSJouni Malinen 	switch (level) {
91cd4e3c3eSJouni Malinen 	case DUT_MSG_ERROR:
92cd4e3c3eSJouni Malinen 		return ANDROID_LOG_ERROR;
93cd4e3c3eSJouni Malinen 	case DUT_MSG_INFO:
94cd4e3c3eSJouni Malinen 		return ANDROID_LOG_INFO;
95cd4e3c3eSJouni Malinen 	case DUT_MSG_DEBUG:
96cd4e3c3eSJouni Malinen 		return ANDROID_LOG_DEBUG;
97cd4e3c3eSJouni Malinen 	default:
98cd4e3c3eSJouni Malinen 		return ANDROID_LOG_VERBOSE;
99cd4e3c3eSJouni Malinen 	}
100cd4e3c3eSJouni Malinen }
1012dfb1daeSVinay Gannevaram 
102cd4e3c3eSJouni Malinen #endif /* ANDROID */
103cd4e3c3eSJouni Malinen 
104cd4e3c3eSJouni Malinen 
sigma_dut_print(struct sigma_dut * dut,int level,const char * fmt,...)105cd4e3c3eSJouni Malinen void sigma_dut_print(struct sigma_dut *dut, int level, const char *fmt, ...)
106cd4e3c3eSJouni Malinen {
107cd4e3c3eSJouni Malinen 	va_list ap;
108cd4e3c3eSJouni Malinen 	struct timeval tv;
109cd4e3c3eSJouni Malinen 
110cd4e3c3eSJouni Malinen 	if (level < dut->debug_level)
111cd4e3c3eSJouni Malinen 		return;
112cd4e3c3eSJouni Malinen 
1130128bf99SKiran Kumar Lokere 	gettimeofday(&tv, NULL);
114cd4e3c3eSJouni Malinen #ifdef ANDROID
115cd4e3c3eSJouni Malinen 	va_start(ap, fmt);
116cd4e3c3eSJouni Malinen 	__android_log_vprint(level_to_android_priority(level),
117cd4e3c3eSJouni Malinen 			     "sigma_dut", fmt, ap);
118cd4e3c3eSJouni Malinen 	va_end(ap);
119cd4e3c3eSJouni Malinen 	if (!dut->stdout_debug)
120cd4e3c3eSJouni Malinen 		return;
1210128bf99SKiran Kumar Lokere #else /* ANDROID */
1220128bf99SKiran Kumar Lokere 	if (dut->log_file_fd) {
1230128bf99SKiran Kumar Lokere 		va_start(ap, fmt);
1240128bf99SKiran Kumar Lokere 		fprintf(dut->log_file_fd, "%ld.%06u: ",
1250128bf99SKiran Kumar Lokere 			(long) tv.tv_sec, (unsigned int) tv.tv_usec);
1260128bf99SKiran Kumar Lokere 		vfprintf(dut->log_file_fd, fmt, ap);
1270128bf99SKiran Kumar Lokere 		fprintf(dut->log_file_fd, "\n");
1280128bf99SKiran Kumar Lokere 		va_end(ap);
1290128bf99SKiran Kumar Lokere 	}
130cd4e3c3eSJouni Malinen #endif /* ANDROID */
131cd4e3c3eSJouni Malinen 
132cd4e3c3eSJouni Malinen 	va_start(ap, fmt);
133cd4e3c3eSJouni Malinen 	printf("%ld.%06u: ", (long) tv.tv_sec,
134cd4e3c3eSJouni Malinen 	       (unsigned int) tv.tv_usec);
135cd4e3c3eSJouni Malinen 	vprintf(fmt, ap);
136cd4e3c3eSJouni Malinen 	printf("\n");
137cd4e3c3eSJouni Malinen 	va_end(ap);
138cd4e3c3eSJouni Malinen }
139cd4e3c3eSJouni Malinen 
140cd4e3c3eSJouni Malinen 
sigma_dut_summary(struct sigma_dut * dut,const char * fmt,...)141cd4e3c3eSJouni Malinen void sigma_dut_summary(struct sigma_dut *dut, const char *fmt, ...)
142cd4e3c3eSJouni Malinen {
143cd4e3c3eSJouni Malinen 	va_list ap;
144cd4e3c3eSJouni Malinen 	FILE *f;
145cd4e3c3eSJouni Malinen 
146cd4e3c3eSJouni Malinen 	if (!dut->summary_log)
147cd4e3c3eSJouni Malinen 		return;
148cd4e3c3eSJouni Malinen 
149cd4e3c3eSJouni Malinen 	f = fopen(dut->summary_log, "a");
150cd4e3c3eSJouni Malinen 	if (f == NULL)
151cd4e3c3eSJouni Malinen 		return;
152cd4e3c3eSJouni Malinen 
153cd4e3c3eSJouni Malinen 	va_start(ap, fmt);
154cd4e3c3eSJouni Malinen 	vfprintf(f, fmt, ap);
155cd4e3c3eSJouni Malinen 	fprintf(f, "\n");
156cd4e3c3eSJouni Malinen 	va_end(ap);
157cd4e3c3eSJouni Malinen 	fclose(f);
158cd4e3c3eSJouni Malinen }
159cd4e3c3eSJouni Malinen 
160cd4e3c3eSJouni Malinen 
sigma_dut_reg_cmd(const char * cmd,int (* validate)(struct sigma_cmd * cmd),enum sigma_cmd_result (* process)(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd))161cd4e3c3eSJouni Malinen int sigma_dut_reg_cmd(const char *cmd,
162cd4e3c3eSJouni Malinen 		      int (*validate)(struct sigma_cmd *cmd),
16326a5b76dSJouni Malinen 		      enum sigma_cmd_result (*process)(struct sigma_dut *dut,
164cd4e3c3eSJouni Malinen 						       struct sigma_conn *conn,
165cd4e3c3eSJouni Malinen 						       struct sigma_cmd *cmd))
166cd4e3c3eSJouni Malinen {
167cd4e3c3eSJouni Malinen 	struct sigma_cmd_handler *h;
168cd4e3c3eSJouni Malinen 	size_t clen, len;
169cd4e3c3eSJouni Malinen 
1705404f5fdSJouni Malinen 	for (h = sigma_dut.cmds; h; h = h->next) {
1715404f5fdSJouni Malinen 		if (strcmp(h->cmd, cmd) == 0) {
1725404f5fdSJouni Malinen 			printf("ERROR: Duplicate sigma_dut command registration for '%s'\n",
1735404f5fdSJouni Malinen 			       cmd);
1745404f5fdSJouni Malinen 			return -1;
1755404f5fdSJouni Malinen 		}
1765404f5fdSJouni Malinen 	}
1775404f5fdSJouni Malinen 
178cd4e3c3eSJouni Malinen 	clen = strlen(cmd);
179cd4e3c3eSJouni Malinen 	len = sizeof(*h) + clen + 1;
180cd4e3c3eSJouni Malinen 	h = malloc(len);
181cd4e3c3eSJouni Malinen 	if (h == NULL)
182cd4e3c3eSJouni Malinen 		return -1;
183cd4e3c3eSJouni Malinen 	memset(h, 0, len);
184cd4e3c3eSJouni Malinen 	h->cmd = (char *) (h + 1); /* include in same allocation */
185cd4e3c3eSJouni Malinen 	memcpy(h->cmd, cmd, clen);
186cd4e3c3eSJouni Malinen 	h->validate = validate;
187cd4e3c3eSJouni Malinen 	h->process= process;
188cd4e3c3eSJouni Malinen 
189cd4e3c3eSJouni Malinen 	h->next = sigma_dut.cmds;
190cd4e3c3eSJouni Malinen 	sigma_dut.cmds = h;
191cd4e3c3eSJouni Malinen 
192cd4e3c3eSJouni Malinen 	return 0;
193cd4e3c3eSJouni Malinen }
194cd4e3c3eSJouni Malinen 
195cd4e3c3eSJouni Malinen 
sigma_dut_unreg_cmds(struct sigma_dut * dut)196cd4e3c3eSJouni Malinen static void sigma_dut_unreg_cmds(struct sigma_dut *dut)
197cd4e3c3eSJouni Malinen {
198cd4e3c3eSJouni Malinen 	struct sigma_cmd_handler *cmd, *prev;
199cd4e3c3eSJouni Malinen 	cmd = dut->cmds;
200cd4e3c3eSJouni Malinen 	dut->cmds = NULL;
201cd4e3c3eSJouni Malinen 	while (cmd) {
202cd4e3c3eSJouni Malinen 		prev = cmd;
203cd4e3c3eSJouni Malinen 		cmd = cmd->next;
204cd4e3c3eSJouni Malinen 		free(prev);
205cd4e3c3eSJouni Malinen 	}
206cd4e3c3eSJouni Malinen }
207cd4e3c3eSJouni Malinen 
208cd4e3c3eSJouni Malinen 
open_socket(struct sigma_dut * dut,int port)209cd4e3c3eSJouni Malinen static int open_socket(struct sigma_dut *dut, int port)
210cd4e3c3eSJouni Malinen {
211cd4e3c3eSJouni Malinen 	struct sockaddr_in addr;
212cd4e3c3eSJouni Malinen #ifndef __QNXNTO__
213cd4e3c3eSJouni Malinen 	int val;
214cd4e3c3eSJouni Malinen #endif /* !__QNXNTO__ */
215cd4e3c3eSJouni Malinen 
216cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
217cd4e3c3eSJouni Malinen 	dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
218cd4e3c3eSJouni Malinen #else /* __QNXNTO__ */
219cd4e3c3eSJouni Malinen 	dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
220cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
221cd4e3c3eSJouni Malinen 	if (dut->s < 0) {
222cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "socket: %s",
223cd4e3c3eSJouni Malinen 				strerror(errno));
224cd4e3c3eSJouni Malinen 		return -1;
225cd4e3c3eSJouni Malinen 	}
226cd4e3c3eSJouni Malinen 
227cd4e3c3eSJouni Malinen #ifndef __QNXNTO__
228cd4e3c3eSJouni Malinen 	val = 1;
229cd4e3c3eSJouni Malinen 	if (setsockopt(dut->s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) <
230cd4e3c3eSJouni Malinen 	    0)
231cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt SO_REUSEADDR: "
232cd4e3c3eSJouni Malinen 				"%s", strerror(errno));
233cd4e3c3eSJouni Malinen #endif /* !__QNXNTO__ */
234cd4e3c3eSJouni Malinen 
235cd4e3c3eSJouni Malinen #ifdef __linux__
236cd4e3c3eSJouni Malinen 	val = 1;
237cd4e3c3eSJouni Malinen 	if (setsockopt(dut->s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) <
238cd4e3c3eSJouni Malinen 	    0)
239cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt TCP_NODELAY: "
240cd4e3c3eSJouni Malinen 				"%s", strerror(errno));
241cd4e3c3eSJouni Malinen #endif /* __linux__ */
242cd4e3c3eSJouni Malinen 
243cd4e3c3eSJouni Malinen 	memset(&addr, 0, sizeof(addr));
244cd4e3c3eSJouni Malinen 	addr.sin_family = AF_INET;
245cd4e3c3eSJouni Malinen 	addr.sin_port = htons(port);
246cd4e3c3eSJouni Malinen 
247cd4e3c3eSJouni Malinen 	if (bind(dut->s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
248cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "bind: %s",
249cd4e3c3eSJouni Malinen 				strerror(errno));
250cd4e3c3eSJouni Malinen 		goto fail;
251cd4e3c3eSJouni Malinen 	}
252cd4e3c3eSJouni Malinen 
253cd4e3c3eSJouni Malinen 	if (listen(dut->s, 5) < 0) {
254cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "listen: %s",
255cd4e3c3eSJouni Malinen 				strerror(errno));
256cd4e3c3eSJouni Malinen 		goto fail;
257cd4e3c3eSJouni Malinen 	}
258cd4e3c3eSJouni Malinen 
259cd4e3c3eSJouni Malinen 	return 0;
260cd4e3c3eSJouni Malinen 
261cd4e3c3eSJouni Malinen fail:
262cd4e3c3eSJouni Malinen 	shutdown(dut->s, SHUT_RDWR);
263cd4e3c3eSJouni Malinen 	close(dut->s);
264cd4e3c3eSJouni Malinen 	dut->s = -1;
265cd4e3c3eSJouni Malinen 	return -1;
266cd4e3c3eSJouni Malinen }
267cd4e3c3eSJouni Malinen 
268cd4e3c3eSJouni Malinen 
close_socket(struct sigma_dut * dut)269cd4e3c3eSJouni Malinen static void close_socket(struct sigma_dut *dut)
270cd4e3c3eSJouni Malinen {
271cd4e3c3eSJouni Malinen 	shutdown(dut->s, SHUT_RDWR);
272cd4e3c3eSJouni Malinen 	close(dut->s);
273cd4e3c3eSJouni Malinen 	dut->s = -1;
274cd4e3c3eSJouni Malinen }
275cd4e3c3eSJouni Malinen 
276cd4e3c3eSJouni Malinen 
send_resp(struct sigma_dut * dut,struct sigma_conn * conn,enum sigma_status status,const char * buf)277cd4e3c3eSJouni Malinen void send_resp(struct sigma_dut *dut, struct sigma_conn *conn,
27876401f50SJouni Malinen 	       enum sigma_status status, const char *buf)
279cd4e3c3eSJouni Malinen {
280cd4e3c3eSJouni Malinen 	struct msghdr msg;
281cd4e3c3eSJouni Malinen 	struct iovec iov[4];
282cd4e3c3eSJouni Malinen 	size_t elems;
283cd4e3c3eSJouni Malinen 
284a326d7b5SJouni Malinen 	if (!conn)
285a326d7b5SJouni Malinen 		return;
286a326d7b5SJouni Malinen 
287cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "resp: status=%d buf=%s",
288cd4e3c3eSJouni Malinen 			status, buf ? buf : "N/A");
289cd4e3c3eSJouni Malinen 
290cd4e3c3eSJouni Malinen 	iov[0].iov_base = "status,";
291cd4e3c3eSJouni Malinen 	iov[0].iov_len = 7;
292cd4e3c3eSJouni Malinen 	switch (status) {
293cd4e3c3eSJouni Malinen 	case SIGMA_RUNNING:
294cd4e3c3eSJouni Malinen 		iov[1].iov_base = "RUNNING,";
295cd4e3c3eSJouni Malinen 		iov[1].iov_len = 8;
296cd4e3c3eSJouni Malinen 		break;
297cd4e3c3eSJouni Malinen 	case SIGMA_INVALID:
298cd4e3c3eSJouni Malinen 		iov[1].iov_base = "INVALID,";
299cd4e3c3eSJouni Malinen 		iov[1].iov_len = 8;
300cd4e3c3eSJouni Malinen 		break;
301cd4e3c3eSJouni Malinen 	case SIGMA_ERROR:
302cd4e3c3eSJouni Malinen 		iov[1].iov_base = "ERROR,";
303cd4e3c3eSJouni Malinen 		iov[1].iov_len = 6;
304cd4e3c3eSJouni Malinen 		break;
305cd4e3c3eSJouni Malinen 	case SIGMA_COMPLETE:
306cd4e3c3eSJouni Malinen 		iov[1].iov_base = "COMPLETE,";
307cd4e3c3eSJouni Malinen 		iov[1].iov_len = 9;
308cd4e3c3eSJouni Malinen 		break;
309cd4e3c3eSJouni Malinen 	}
310cd4e3c3eSJouni Malinen 	if (status != SIGMA_RUNNING) {
311cd4e3c3eSJouni Malinen 		sigma_dut_summary(dut, "CAPI resp: status,%s%s",
312cd4e3c3eSJouni Malinen 				  (char *) iov[1].iov_base, buf ? buf : "");
313cd4e3c3eSJouni Malinen 	}
314cd4e3c3eSJouni Malinen 	if (buf) {
31576401f50SJouni Malinen 		iov[2].iov_base = (void *) buf;
316cd4e3c3eSJouni Malinen 		iov[2].iov_len = strlen(buf);
317cd4e3c3eSJouni Malinen 		iov[3].iov_base = "\r\n";
318cd4e3c3eSJouni Malinen 		iov[3].iov_len = 2;
319cd4e3c3eSJouni Malinen 		elems = 4;
320cd4e3c3eSJouni Malinen 	} else {
321cd4e3c3eSJouni Malinen 		iov[1].iov_len--;
322cd4e3c3eSJouni Malinen 		iov[2].iov_base = "\r\n";
323cd4e3c3eSJouni Malinen 		iov[2].iov_len = 2;
324cd4e3c3eSJouni Malinen 		elems = 3;
325cd4e3c3eSJouni Malinen 	}
326cd4e3c3eSJouni Malinen 
327cd4e3c3eSJouni Malinen 	memset(&msg, 0, sizeof(msg));
328cd4e3c3eSJouni Malinen 	msg.msg_iov = iov;
329cd4e3c3eSJouni Malinen 	msg.msg_iovlen = elems;
330cd4e3c3eSJouni Malinen 	if (sendmsg(conn->s, &msg, 0) < 0)
331cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "sendmsg: %s",
332cd4e3c3eSJouni Malinen 				strerror(errno));
3330fee701cSJouni Malinen 	dut->response_sent++;
334cd4e3c3eSJouni Malinen }
335cd4e3c3eSJouni Malinen 
336cd4e3c3eSJouni Malinen 
get_param(struct sigma_cmd * cmd,const char * name)337cd4e3c3eSJouni Malinen const char * get_param(struct sigma_cmd *cmd, const char *name)
338cd4e3c3eSJouni Malinen {
339cd4e3c3eSJouni Malinen 	int i;
340cd4e3c3eSJouni Malinen 	for (i = 0; i < cmd->count; i++) {
341cd4e3c3eSJouni Malinen 		if (strcasecmp(name, cmd->params[i]) == 0)
342cd4e3c3eSJouni Malinen 			return cmd->values[i];
343cd4e3c3eSJouni Malinen 	}
344cd4e3c3eSJouni Malinen 	return NULL;
345cd4e3c3eSJouni Malinen }
346cd4e3c3eSJouni Malinen 
347cd4e3c3eSJouni Malinen 
get_param_indexed(struct sigma_cmd * cmd,const char * name,int index)348bc180dc5SAlexei Avshalom Lazar const char * get_param_indexed(struct sigma_cmd *cmd, const char *name,
349bc180dc5SAlexei Avshalom Lazar 			       int index)
350bc180dc5SAlexei Avshalom Lazar {
351bc180dc5SAlexei Avshalom Lazar 	int i, j;
352bc180dc5SAlexei Avshalom Lazar 
353bc180dc5SAlexei Avshalom Lazar 	for (i = 0, j = 0; i < cmd->count; i++) {
354bc180dc5SAlexei Avshalom Lazar 		if (strcasecmp(name, cmd->params[i]) == 0) {
355bc180dc5SAlexei Avshalom Lazar 			j++;
356bc180dc5SAlexei Avshalom Lazar 			if (j > index)
357bc180dc5SAlexei Avshalom Lazar 				return cmd->values[i];
358bc180dc5SAlexei Avshalom Lazar 		}
359bc180dc5SAlexei Avshalom Lazar 	}
360bc180dc5SAlexei Avshalom Lazar 
361bc180dc5SAlexei Avshalom Lazar 	return NULL;
362bc180dc5SAlexei Avshalom Lazar }
363bc180dc5SAlexei Avshalom Lazar 
364bc180dc5SAlexei Avshalom Lazar 
process_cmd(struct sigma_dut * dut,struct sigma_conn * conn,char * buf)365cd4e3c3eSJouni Malinen static void process_cmd(struct sigma_dut *dut, struct sigma_conn *conn,
366cd4e3c3eSJouni Malinen 			char *buf)
367cd4e3c3eSJouni Malinen {
368cd4e3c3eSJouni Malinen 	struct sigma_cmd_handler *h;
369cd4e3c3eSJouni Malinen 	struct sigma_cmd c;
370cd4e3c3eSJouni Malinen 	char *cmd, *pos, *pos2;
371cd4e3c3eSJouni Malinen 	int len;
3725fdd8650SAlexei Avshalom Lazar 	char txt[300];
37326a5b76dSJouni Malinen 	enum sigma_cmd_result res;
374cd4e3c3eSJouni Malinen 
375cd4e3c3eSJouni Malinen 	while (*buf == '\r' || *buf == '\n' || *buf == '\t' || *buf == ' ')
376cd4e3c3eSJouni Malinen 		buf++;
377cd4e3c3eSJouni Malinen 	len = strlen(buf);
378cd4e3c3eSJouni Malinen 	while (len > 0 && buf[len - 1] == ' ') {
379cd4e3c3eSJouni Malinen 		buf[len - 1] = '\0';
380cd4e3c3eSJouni Malinen 		len--;
381cd4e3c3eSJouni Malinen 	}
382cd4e3c3eSJouni Malinen 
383cd4e3c3eSJouni Malinen 	if (dut->debug_level < DUT_MSG_INFO) {
384cd4e3c3eSJouni Malinen 		pos = strchr(buf, ',');
385cd4e3c3eSJouni Malinen 		if (pos == NULL)
386cd4e3c3eSJouni Malinen 			pos = buf + len;
387cd4e3c3eSJouni Malinen 		if (pos - buf > 50)
388cd4e3c3eSJouni Malinen 			pos = buf + 50;
389cd4e3c3eSJouni Malinen 		memcpy(txt, "/====[ ", 7);
390cd4e3c3eSJouni Malinen 		pos2 = txt + 7;
391cd4e3c3eSJouni Malinen 		memcpy(pos2, buf, pos - buf);
392cd4e3c3eSJouni Malinen 		pos2 += pos - buf;
393cd4e3c3eSJouni Malinen 		*pos2++ = ' ';
394cd4e3c3eSJouni Malinen 		*pos2++ = ']';
395cd4e3c3eSJouni Malinen 		while (pos2 - txt < 70)
396cd4e3c3eSJouni Malinen 			*pos2++ = '=';
397cd4e3c3eSJouni Malinen 		*pos2++ = '\\';
398cd4e3c3eSJouni Malinen 		*pos2 = '\0';
399cd4e3c3eSJouni Malinen 		printf("\n%s\n\n", txt);
400cd4e3c3eSJouni Malinen 	}
401cd4e3c3eSJouni Malinen 
402cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "cmd: %s", buf);
403cd4e3c3eSJouni Malinen 	sigma_dut_summary(dut, "CAPI cmd: %s", buf);
404cd4e3c3eSJouni Malinen 	snprintf(txt, sizeof(txt), "NOTE CAPI:%s", buf);
405cd4e3c3eSJouni Malinen 	txt[sizeof(txt) - 1] = '\0';
406016ae6c8SJouni Malinen 	wpa_command(get_main_ifname(dut), txt);
407cd4e3c3eSJouni Malinen 
408cd4e3c3eSJouni Malinen 	memset(&c, 0, sizeof(c));
409cd4e3c3eSJouni Malinen 	cmd = buf;
410cd4e3c3eSJouni Malinen 	pos = strchr(cmd, ',');
411cd4e3c3eSJouni Malinen 	if (pos) {
412cd4e3c3eSJouni Malinen 		*pos++ = '\0';
413cd4e3c3eSJouni Malinen 		if (strcasecmp(cmd, "AccessPoint") == 0 ||
414cd4e3c3eSJouni Malinen 		    strcasecmp(cmd, "PowerSwitch") == 0) {
415cd4e3c3eSJouni Malinen 			pos2 = strchr(pos, ',');
416cd4e3c3eSJouni Malinen 			if (pos2 == NULL)
417cd4e3c3eSJouni Malinen 				goto invalid_params;
418cd4e3c3eSJouni Malinen 			c.params[c.count] = pos;
419cd4e3c3eSJouni Malinen 			c.values[c.count] = pos2;
420cd4e3c3eSJouni Malinen 			c.count++;
421cd4e3c3eSJouni Malinen 			pos = strchr(pos2, ',');
422cd4e3c3eSJouni Malinen 			if (pos)
423cd4e3c3eSJouni Malinen 				*pos++ = '\0';
424cd4e3c3eSJouni Malinen 		}
425cd4e3c3eSJouni Malinen 		while (pos) {
426cd4e3c3eSJouni Malinen 			pos2 = strchr(pos, ',');
427cd4e3c3eSJouni Malinen 			if (pos2 == NULL)
428cd4e3c3eSJouni Malinen 				goto invalid_params;
429cd4e3c3eSJouni Malinen 			*pos2++ = '\0';
430cd4e3c3eSJouni Malinen 			if (c.count == MAX_PARAMS) {
431cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_INFO, "Too many "
432cd4e3c3eSJouni Malinen 						"parameters");
433cd4e3c3eSJouni Malinen 				goto invalid_params;
434cd4e3c3eSJouni Malinen 			}
435cd4e3c3eSJouni Malinen 			c.params[c.count] = pos;
436cd4e3c3eSJouni Malinen 			c.values[c.count] = pos2;
437cd4e3c3eSJouni Malinen 			c.count++;
438cd4e3c3eSJouni Malinen 			pos = strchr(pos2, ',');
439cd4e3c3eSJouni Malinen 			if (pos)
440cd4e3c3eSJouni Malinen 				*pos++ = '\0';
441cd4e3c3eSJouni Malinen 		}
442cd4e3c3eSJouni Malinen 	}
443cd4e3c3eSJouni Malinen 	h = dut->cmds;
444cd4e3c3eSJouni Malinen 	while (h) {
445cd4e3c3eSJouni Malinen 		if (strcasecmp(cmd, h->cmd) == 0)
446cd4e3c3eSJouni Malinen 			break;
447cd4e3c3eSJouni Malinen 		h = h->next;
448cd4e3c3eSJouni Malinen 	}
449cd4e3c3eSJouni Malinen 
450cd4e3c3eSJouni Malinen 	if (h == NULL) {
451cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Unknown command: '%s'",
452cd4e3c3eSJouni Malinen 				cmd);
453cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID,
454cd4e3c3eSJouni Malinen 			  "errorCode,Unknown command");
455cd4e3c3eSJouni Malinen 		goto out;
456cd4e3c3eSJouni Malinen 	}
457cd4e3c3eSJouni Malinen 
458cd4e3c3eSJouni Malinen 	if (h->validate && h->validate(&c) < 0) {
459cd4e3c3eSJouni Malinen 	invalid_params:
460cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Invalid parameters");
461cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid "
462cd4e3c3eSJouni Malinen 			  "parameters");
463cd4e3c3eSJouni Malinen 		goto out;
464cd4e3c3eSJouni Malinen 	}
465cd4e3c3eSJouni Malinen 
4660fee701cSJouni Malinen 	dut->response_sent = 0;
467cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_RUNNING, NULL);
468cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "Run command: %s", cmd);
469cd4e3c3eSJouni Malinen 	res = h->process(dut, conn, &c);
47026a5b76dSJouni Malinen 	switch (res) {
47126a5b76dSJouni Malinen 	case ERROR_SEND_STATUS:
472cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, NULL);
47326a5b76dSJouni Malinen 		break;
47426a5b76dSJouni Malinen 	case INVALID_SEND_STATUS:
475cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, NULL);
47626a5b76dSJouni Malinen 		break;
47726a5b76dSJouni Malinen 	case STATUS_SENT:
47853264f63SJouni Malinen 	case STATUS_SENT_ERROR:
47926a5b76dSJouni Malinen 		break;
48026a5b76dSJouni Malinen 	case SUCCESS_SEND_STATUS:
481cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, NULL);
48226a5b76dSJouni Malinen 		break;
48326a5b76dSJouni Malinen 	}
484cd4e3c3eSJouni Malinen 
4850fee701cSJouni Malinen 	if (!conn->waiting_completion && dut->response_sent != 2) {
4860fee701cSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR,
4870fee701cSJouni Malinen 				"ERROR: Unexpected number of status lines sent (%d) for command '%s'",
4880fee701cSJouni Malinen 				dut->response_sent, cmd);
4890fee701cSJouni Malinen 	}
4900fee701cSJouni Malinen 
491cd4e3c3eSJouni Malinen out:
492cd4e3c3eSJouni Malinen 	if (dut->debug_level < DUT_MSG_INFO) {
493cd4e3c3eSJouni Malinen 		pos2 = txt;
494cd4e3c3eSJouni Malinen 		*pos2++ = '\\';
495cd4e3c3eSJouni Malinen 		memset(pos2, '-', 69);
496cd4e3c3eSJouni Malinen 		pos2 += 69;
497cd4e3c3eSJouni Malinen 		*pos2++ = '/';
498cd4e3c3eSJouni Malinen 		*pos2 = '\0';
499cd4e3c3eSJouni Malinen 		printf("\n%s\n\n", txt);
500cd4e3c3eSJouni Malinen 	}
501cd4e3c3eSJouni Malinen }
502cd4e3c3eSJouni Malinen 
503cd4e3c3eSJouni Malinen 
process_conn(struct sigma_dut * dut,struct sigma_conn * conn)504cd4e3c3eSJouni Malinen static void process_conn(struct sigma_dut *dut, struct sigma_conn *conn)
505cd4e3c3eSJouni Malinen {
506cd4e3c3eSJouni Malinen 	ssize_t res;
507cd4e3c3eSJouni Malinen 	int i;
508cd4e3c3eSJouni Malinen 
509cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Read from %s:%d",
510cd4e3c3eSJouni Malinen 			inet_ntoa(conn->addr.sin_addr),
511cd4e3c3eSJouni Malinen 			ntohs(conn->addr.sin_port));
512cd4e3c3eSJouni Malinen 
513cd4e3c3eSJouni Malinen 	res = recv(conn->s, conn->buf + conn->pos, MAX_CMD_LEN + 5 - conn->pos,
514cd4e3c3eSJouni Malinen 		   0);
515cd4e3c3eSJouni Malinen 	if (res < 0) {
516cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "recv: %s",
517cd4e3c3eSJouni Malinen 				strerror(errno));
518cd4e3c3eSJouni Malinen 	}
519cd4e3c3eSJouni Malinen 	if (res <= 0) {
520cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Close connection from "
521cd4e3c3eSJouni Malinen 				"%s:%d",
522cd4e3c3eSJouni Malinen 				inet_ntoa(conn->addr.sin_addr),
523cd4e3c3eSJouni Malinen 				ntohs(conn->addr.sin_port));
524cd4e3c3eSJouni Malinen 		shutdown(conn->s, SHUT_RDWR);
525cd4e3c3eSJouni Malinen 		close(conn->s);
526cd4e3c3eSJouni Malinen 		conn->s = -1;
527cd4e3c3eSJouni Malinen 		return;
528cd4e3c3eSJouni Malinen 	}
529cd4e3c3eSJouni Malinen 
530cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Received %d bytes",
531cd4e3c3eSJouni Malinen 			(int) res);
532cd4e3c3eSJouni Malinen 
533cd4e3c3eSJouni Malinen 	for (;;) {
534cd4e3c3eSJouni Malinen 		for (i = conn->pos; i < conn->pos + res; i++) {
535cd4e3c3eSJouni Malinen 			if (conn->buf[i] == '\r' || conn->buf[i] == '\n')
536cd4e3c3eSJouni Malinen 				break;
537cd4e3c3eSJouni Malinen 		}
538cd4e3c3eSJouni Malinen 
539cd4e3c3eSJouni Malinen 		if (i == conn->pos + res) {
540cd4e3c3eSJouni Malinen 			/* Full command not yet received */
541cd4e3c3eSJouni Malinen 			conn->pos += res;
542cd4e3c3eSJouni Malinen 			if (conn->pos >= MAX_CMD_LEN + 5) {
543cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_INFO, "Too long "
544cd4e3c3eSJouni Malinen 						"command dropped");
545cd4e3c3eSJouni Malinen 				conn->pos = 0;
546cd4e3c3eSJouni Malinen 			}
547cd4e3c3eSJouni Malinen 			break;
548cd4e3c3eSJouni Malinen 		}
549cd4e3c3eSJouni Malinen 
550cd4e3c3eSJouni Malinen 		/* Full command received */
551cd4e3c3eSJouni Malinen 		conn->buf[i++] = '\0';
552cd4e3c3eSJouni Malinen 		process_cmd(dut, conn, conn->buf);
553cd4e3c3eSJouni Malinen 		while (i < conn->pos + res &&
554cd4e3c3eSJouni Malinen 		       (conn->buf[i] == '\r' || conn->buf[i] == '\n'))
555cd4e3c3eSJouni Malinen 			i++;
556cd4e3c3eSJouni Malinen 		memmove(conn->buf, &conn->buf[i], conn->pos + res - i);
557cd4e3c3eSJouni Malinen 		res = conn->pos + res - i;
558cd4e3c3eSJouni Malinen 		conn->pos = 0;
559cd4e3c3eSJouni Malinen 	}
560cd4e3c3eSJouni Malinen }
561cd4e3c3eSJouni Malinen 
562cd4e3c3eSJouni Malinen 
563cd4e3c3eSJouni Malinen static int stop_loop = 0;
564cd4e3c3eSJouni Malinen 
565cd4e3c3eSJouni Malinen #ifdef __linux__
handle_term(int sig)566cd4e3c3eSJouni Malinen static void handle_term(int sig)
567cd4e3c3eSJouni Malinen {
568ad4c6756SJouni Malinen 	struct sigma_dut *dut = &sigma_dut;
569ad4c6756SJouni Malinen 
570ad4c6756SJouni Malinen 	if (dut->sta_2g_started || dut->sta_5g_started)
571ad4c6756SJouni Malinen 		stop_sta_mode(dut);
572cd4e3c3eSJouni Malinen 	stop_loop = 1;
573091e253dSPurushottam Kushwaha 	stop_event_thread();
574cd4e3c3eSJouni Malinen 	printf("sigma_dut terminating\n");
575cd4e3c3eSJouni Malinen }
576cd4e3c3eSJouni Malinen #endif /* __linux__ */
577cd4e3c3eSJouni Malinen 
run_loop(struct sigma_dut * dut)578cd4e3c3eSJouni Malinen static void run_loop(struct sigma_dut *dut)
579cd4e3c3eSJouni Malinen {
580cd4e3c3eSJouni Malinen 	struct sigma_conn conn[MAX_CONNECTIONS];
581cd4e3c3eSJouni Malinen 	int i, res, maxfd, can_accept;
582cd4e3c3eSJouni Malinen 	fd_set rfds;
583cd4e3c3eSJouni Malinen 
584cd4e3c3eSJouni Malinen 	memset(&conn, 0, sizeof(conn));
585cd4e3c3eSJouni Malinen 	for (i = 0; i < MAX_CONNECTIONS; i++)
586cd4e3c3eSJouni Malinen 		conn[i].s = -1;
587cd4e3c3eSJouni Malinen 
588cd4e3c3eSJouni Malinen #ifdef __linux__
589cd4e3c3eSJouni Malinen 	signal(SIGINT, handle_term);
590cd4e3c3eSJouni Malinen 	signal(SIGTERM, handle_term);
591cd4e3c3eSJouni Malinen 	signal(SIGPIPE, SIG_IGN);
592cd4e3c3eSJouni Malinen #endif /* __linux__ */
593cd4e3c3eSJouni Malinen 
594cd4e3c3eSJouni Malinen 	while (!stop_loop) {
595cd4e3c3eSJouni Malinen 		FD_ZERO(&rfds);
596cd4e3c3eSJouni Malinen 		maxfd = -1;
597cd4e3c3eSJouni Malinen 		can_accept = 0;
598cd4e3c3eSJouni Malinen 		for (i = 0; i < MAX_CONNECTIONS; i++) {
599cd4e3c3eSJouni Malinen 			if (conn[i].s >= 0) {
600cd4e3c3eSJouni Malinen 				FD_SET(conn[i].s, &rfds);
601cd4e3c3eSJouni Malinen 				if (conn[i].s > maxfd)
602cd4e3c3eSJouni Malinen 					maxfd = conn[i].s;
603cd4e3c3eSJouni Malinen 			} else if (!conn[i].waiting_completion)
604cd4e3c3eSJouni Malinen 				can_accept = 1;
605cd4e3c3eSJouni Malinen 		}
606cd4e3c3eSJouni Malinen 
607cd4e3c3eSJouni Malinen 		if (can_accept) {
608cd4e3c3eSJouni Malinen 			FD_SET(dut->s, &rfds);
609cd4e3c3eSJouni Malinen 			if (dut->s > maxfd)
610cd4e3c3eSJouni Malinen 				maxfd = dut->s;
611cd4e3c3eSJouni Malinen 		}
612cd4e3c3eSJouni Malinen 
613cd4e3c3eSJouni Malinen 
614cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for next "
615cd4e3c3eSJouni Malinen 				"command (can_accept=%d)", can_accept);
616cd4e3c3eSJouni Malinen 		res = select(maxfd + 1, &rfds, NULL, NULL, NULL);
617cd4e3c3eSJouni Malinen 		if (res < 0) {
618cd4e3c3eSJouni Malinen 			perror("select");
619cd4e3c3eSJouni Malinen 			if (!stop_loop)
620cd4e3c3eSJouni Malinen 				sleep(1);
621cd4e3c3eSJouni Malinen 			continue;
622cd4e3c3eSJouni Malinen 		}
623cd4e3c3eSJouni Malinen 
624cd4e3c3eSJouni Malinen 		if (!res) {
625cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Nothing ready");
626cd4e3c3eSJouni Malinen 			sleep(1);
627cd4e3c3eSJouni Malinen 			continue;
628cd4e3c3eSJouni Malinen 		}
629cd4e3c3eSJouni Malinen 
630cd4e3c3eSJouni Malinen 		if (FD_ISSET(dut->s, &rfds)) {
631cd4e3c3eSJouni Malinen 			for (i = 0; i < MAX_CONNECTIONS; i++) {
632cd4e3c3eSJouni Malinen 				if (conn[i].s < 0 &&
633cd4e3c3eSJouni Malinen 				    !conn[i].waiting_completion)
634cd4e3c3eSJouni Malinen 					break;
635cd4e3c3eSJouni Malinen 			}
636cd4e3c3eSJouni Malinen 			if (i == MAX_CONNECTIONS) {
637cd4e3c3eSJouni Malinen 				/*
638cd4e3c3eSJouni Malinen 				 * This cannot really happen since can_accept
639cd4e3c3eSJouni Malinen 				 * would not be set to one.
640cd4e3c3eSJouni Malinen 				 */
641cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_DEBUG,
642cd4e3c3eSJouni Malinen 						"No room for new connection");
643cd4e3c3eSJouni Malinen 				continue;
644cd4e3c3eSJouni Malinen 			}
645cd4e3c3eSJouni Malinen 			conn[i].addrlen = sizeof(conn[i].addr);
646cd4e3c3eSJouni Malinen 			conn[i].s = accept(dut->s,
647cd4e3c3eSJouni Malinen 					   (struct sockaddr *) &conn[i].addr,
648cd4e3c3eSJouni Malinen 					   &conn[i].addrlen);
649cd4e3c3eSJouni Malinen 			if (conn[i].s < 0) {
650cd4e3c3eSJouni Malinen 				sigma_dut_print(dut, DUT_MSG_INFO,
651cd4e3c3eSJouni Malinen 						"accept: %s",
652cd4e3c3eSJouni Malinen 						strerror(errno));
653cd4e3c3eSJouni Malinen 				continue;
654cd4e3c3eSJouni Malinen 			}
655cd4e3c3eSJouni Malinen 
656cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG,
657cd4e3c3eSJouni Malinen 					"Connection %d from %s:%d", i,
658cd4e3c3eSJouni Malinen 					inet_ntoa(conn[i].addr.sin_addr),
659cd4e3c3eSJouni Malinen 					ntohs(conn[i].addr.sin_port));
660cd4e3c3eSJouni Malinen 			conn[i].pos = 0;
661cd4e3c3eSJouni Malinen 		}
662cd4e3c3eSJouni Malinen 
663cd4e3c3eSJouni Malinen 		for (i = 0; i < MAX_CONNECTIONS; i++) {
664cd4e3c3eSJouni Malinen 			if (conn[i].s < 0)
665cd4e3c3eSJouni Malinen 				continue;
666cd4e3c3eSJouni Malinen 			if (FD_ISSET(conn[i].s, &rfds))
667cd4e3c3eSJouni Malinen 				process_conn(dut, &conn[i]);
668cd4e3c3eSJouni Malinen 		}
669cd4e3c3eSJouni Malinen 	}
670cd4e3c3eSJouni Malinen }
671cd4e3c3eSJouni Malinen 
672cd4e3c3eSJouni Malinen 
run_local_cmd(int port,char * lcmd)673cd4e3c3eSJouni Malinen static int run_local_cmd(int port, char *lcmd)
674cd4e3c3eSJouni Malinen {
675cd4e3c3eSJouni Malinen 	int s, len;
676cd4e3c3eSJouni Malinen 	struct sockaddr_in addr;
677cd4e3c3eSJouni Malinen 	char cmd[MAX_CMD_LEN];
678cd4e3c3eSJouni Malinen 	ssize_t res;
679cd4e3c3eSJouni Malinen 	int count;
680cd4e3c3eSJouni Malinen 	char resp[MAX_CMD_LEN];
681cd4e3c3eSJouni Malinen 	int pos;
682cd4e3c3eSJouni Malinen 
683cd4e3c3eSJouni Malinen 
684cd4e3c3eSJouni Malinen 	if (strlen(lcmd) > sizeof(cmd) - 4) {
685cd4e3c3eSJouni Malinen 		printf("Too long command\n");
686cd4e3c3eSJouni Malinen 		return -1;
687cd4e3c3eSJouni Malinen 	}
688cd4e3c3eSJouni Malinen 	len = snprintf(cmd, sizeof(cmd), "%s \r\n", lcmd);
689cd4e3c3eSJouni Malinen 
690cd4e3c3eSJouni Malinen 	memset(&addr, 0, sizeof(addr));
691cd4e3c3eSJouni Malinen 	addr.sin_family = AF_INET;
692cd4e3c3eSJouni Malinen 	inet_aton("127.0.0.1", &addr.sin_addr);
693cd4e3c3eSJouni Malinen 	addr.sin_port = htons(port);
694cd4e3c3eSJouni Malinen 
695cd4e3c3eSJouni Malinen 	/* Make sure we do not get stuck indefinitely */
696cd4e3c3eSJouni Malinen 	alarm(150);
697cd4e3c3eSJouni Malinen 
698cd4e3c3eSJouni Malinen 	s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
699cd4e3c3eSJouni Malinen 	if (s < 0) {
700cd4e3c3eSJouni Malinen 		perror("socket");
701cd4e3c3eSJouni Malinen 		return -1;
702cd4e3c3eSJouni Malinen 	}
703cd4e3c3eSJouni Malinen 
704cd4e3c3eSJouni Malinen 	if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
705cd4e3c3eSJouni Malinen 		perror("connect");
706cd4e3c3eSJouni Malinen 		close(s);
707cd4e3c3eSJouni Malinen 		return -1;
708cd4e3c3eSJouni Malinen 	}
709cd4e3c3eSJouni Malinen 
710cd4e3c3eSJouni Malinen 	res = send(s, cmd, len, 0);
711cd4e3c3eSJouni Malinen 	if (res < 0) {
712cd4e3c3eSJouni Malinen 		perror("send");
713cd4e3c3eSJouni Malinen 		close(s);
714cd4e3c3eSJouni Malinen 		return -1;
715cd4e3c3eSJouni Malinen 	}
716cd4e3c3eSJouni Malinen 	if (res != len) {
717cd4e3c3eSJouni Malinen 		printf("Unexpected send result: %d (expected %d)\n",
718cd4e3c3eSJouni Malinen 		       (int) res, len);
719cd4e3c3eSJouni Malinen 		close(s);
720cd4e3c3eSJouni Malinen 		return -1;
721cd4e3c3eSJouni Malinen 	}
722cd4e3c3eSJouni Malinen 
723cd4e3c3eSJouni Malinen 	count = 0;
724cd4e3c3eSJouni Malinen 	pos = 0;
725cd4e3c3eSJouni Malinen 	len = 0;
726cd4e3c3eSJouni Malinen 	for (;;) {
727cd4e3c3eSJouni Malinen 		char *e;
728cd4e3c3eSJouni Malinen 		res = recv(s, resp + len, sizeof(resp) - len, 0);
729cd4e3c3eSJouni Malinen 		if (res < 0) {
730cd4e3c3eSJouni Malinen 			perror("recv");
731cd4e3c3eSJouni Malinen 			close(s);
732cd4e3c3eSJouni Malinen 			return -1;
733cd4e3c3eSJouni Malinen 		}
734cd4e3c3eSJouni Malinen 		if (res == 0) {
735cd4e3c3eSJouni Malinen 			printf("Could not read response\n");
736cd4e3c3eSJouni Malinen 			close(s);
737cd4e3c3eSJouni Malinen 			return -1;
738cd4e3c3eSJouni Malinen 		}
739cd4e3c3eSJouni Malinen 		len += res;
740cd4e3c3eSJouni Malinen 	next_line:
741cd4e3c3eSJouni Malinen 		e = memchr(resp + pos, '\r', len - pos);
742cd4e3c3eSJouni Malinen 		if (e == NULL)
743cd4e3c3eSJouni Malinen 			continue;
744cd4e3c3eSJouni Malinen 		*e++ = '\0';
745cd4e3c3eSJouni Malinen 		if (e - resp < len && *e == '\n')
746cd4e3c3eSJouni Malinen 			*e++ = '\n';
747cd4e3c3eSJouni Malinen 		printf("%s\n", resp + pos);
748cd4e3c3eSJouni Malinen 		if (strncasecmp(resp + pos, "status,RUNNING", 14) != 0)
749cd4e3c3eSJouni Malinen 			break;
750cd4e3c3eSJouni Malinen 		count++;
751cd4e3c3eSJouni Malinen 		if (count == 2)
752cd4e3c3eSJouni Malinen 			break;
753cd4e3c3eSJouni Malinen 		pos = e - resp;
754cd4e3c3eSJouni Malinen 		goto next_line;
755cd4e3c3eSJouni Malinen 	}
756cd4e3c3eSJouni Malinen 
757cd4e3c3eSJouni Malinen 	close(s);
758cd4e3c3eSJouni Malinen 
759cd4e3c3eSJouni Malinen 	return 0;
760cd4e3c3eSJouni Malinen }
761cd4e3c3eSJouni Malinen 
762cd4e3c3eSJouni Malinen 
determine_sigma_p2p_ifname(struct sigma_dut * dut)7631f76fa6dSJouni Malinen static void determine_sigma_p2p_ifname(struct sigma_dut *dut)
764f2af39bfSDanny Segal {
765f2af39bfSDanny Segal 	char buf[256];
766f2af39bfSDanny Segal 	struct wpa_ctrl *ctrl;
767f2af39bfSDanny Segal 
7681f76fa6dSJouni Malinen 	if (dut->p2p_ifname)
7691f76fa6dSJouni Malinen 		return;
770f2af39bfSDanny Segal 
771016ae6c8SJouni Malinen 	snprintf(buf, sizeof(buf), "p2p-dev-%s", get_station_ifname(dut));
772f2af39bfSDanny Segal 	ctrl = open_wpa_mon(buf);
773f2af39bfSDanny Segal 	if (ctrl) {
774f2af39bfSDanny Segal 		wpa_ctrl_detach(ctrl);
775f2af39bfSDanny Segal 		wpa_ctrl_close(ctrl);
7761f76fa6dSJouni Malinen 		dut->p2p_ifname_buf = strdup(buf);
7771f76fa6dSJouni Malinen 		dut->p2p_ifname = dut->p2p_ifname_buf;
778f2af39bfSDanny Segal 		sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
779f2af39bfSDanny Segal 				"Using interface %s for P2P operations instead of interface %s",
7801f76fa6dSJouni Malinen 				dut->p2p_ifname ? dut->p2p_ifname : "NULL",
781016ae6c8SJouni Malinen 				get_station_ifname(dut));
782f2af39bfSDanny Segal 	} else {
7831f76fa6dSJouni Malinen 		dut->p2p_ifname = get_station_ifname(dut);
784f2af39bfSDanny Segal 	}
785f2af39bfSDanny Segal }
786f2af39bfSDanny Segal 
787f2af39bfSDanny Segal 
get_nl80211_config_enable_option(struct sigma_dut * dut)788d06f100bSPriyadharshini Gowthaman static int get_nl80211_config_enable_option(struct sigma_dut *dut)
789d06f100bSPriyadharshini Gowthaman {
790d06f100bSPriyadharshini Gowthaman 	char cmd[100], result[5];
791d06f100bSPriyadharshini Gowthaman 	FILE *f;
792d06f100bSPriyadharshini Gowthaman 	size_t len;
793d06f100bSPriyadharshini Gowthaman 	int ap_nl80211_enable;
794d06f100bSPriyadharshini Gowthaman 
795d06f100bSPriyadharshini Gowthaman 	snprintf(cmd, sizeof(cmd), "uci get qcacfg80211.config.enable");
796d06f100bSPriyadharshini Gowthaman 	f = popen(cmd, "r");
797d06f100bSPriyadharshini Gowthaman 	if (!f)
798d06f100bSPriyadharshini Gowthaman 		return -1;
799d06f100bSPriyadharshini Gowthaman 
800d06f100bSPriyadharshini Gowthaman 	len = fread(result, 1, sizeof(result) - 1, f);
801d06f100bSPriyadharshini Gowthaman 	pclose(f);
802d06f100bSPriyadharshini Gowthaman 
803d06f100bSPriyadharshini Gowthaman 	if (len == 0)
804d06f100bSPriyadharshini Gowthaman 		return -1;
805d06f100bSPriyadharshini Gowthaman 
806d06f100bSPriyadharshini Gowthaman 	result[len] = '\0';
807d06f100bSPriyadharshini Gowthaman 	ap_nl80211_enable = atoi(result);
808d06f100bSPriyadharshini Gowthaman 
809d06f100bSPriyadharshini Gowthaman 	if (ap_nl80211_enable)
810d06f100bSPriyadharshini Gowthaman 		dut->priv_cmd = "cfg80211tool";
811d06f100bSPriyadharshini Gowthaman 
812d06f100bSPriyadharshini Gowthaman 	return 0;
813d06f100bSPriyadharshini Gowthaman }
814d06f100bSPriyadharshini Gowthaman 
815d06f100bSPriyadharshini Gowthaman 
set_defaults(struct sigma_dut * dut)816cd4e3c3eSJouni Malinen static void set_defaults(struct sigma_dut *dut)
817cd4e3c3eSJouni Malinen {
8181dd0b617SJouni Malinen 	dut->debug_level = DUT_MSG_INFO;
8191dd0b617SJouni Malinen 	dut->default_timeout = 120;
8201dd0b617SJouni Malinen 	dut->dialog_token = 0;
8211dd0b617SJouni Malinen 	dut->dpp_conf_id = -1;
8221dd0b617SJouni Malinen 	dut->dpp_local_bootstrap = -1;
8231dd0b617SJouni Malinen 	dut->sta_nss = 2; /* Make default nss 2 */
8241dd0b617SJouni Malinen 	dut->trans_proto = NAN_TRANSPORT_PROTOCOL_DEFAULT;
8251dd0b617SJouni Malinen 	dut->trans_port = NAN_TRANSPORT_PORT_DEFAULT;
8261dd0b617SJouni Malinen 	dut->nan_ipv6_len = 0;
827cd4e3c3eSJouni Malinen 	dut->ap_p2p_cross_connect = -1;
828cd4e3c3eSJouni Malinen 	dut->ap_chwidth = AP_AUTO;
829bf8af292SPradeep Reddy Potteti 	dut->default_11na_ap_chwidth = AP_AUTO;
830bf8af292SPradeep Reddy Potteti 	dut->default_11ng_ap_chwidth = AP_AUTO;
831cd4e3c3eSJouni Malinen 	/* by default, enable writing of traffic stream stats */
832cd4e3c3eSJouni Malinen 	dut->write_stats = 1;
833d06f100bSPriyadharshini Gowthaman 	dut->priv_cmd = "iwpriv";
834c9bc15d1SAlexei Avshalom Lazar 	dut->sigma_tmpdir = SIGMA_TMPDIR;
835ce7ba82fSPriyadharshini Gowthaman 	dut->ap_ocvc = -1;
8360a9876c1SJouni Malinen 	dut->ap_sae_commit_status = -1;
837cd4e3c3eSJouni Malinen }
838cd4e3c3eSJouni Malinen 
839cd4e3c3eSJouni Malinen 
deinit_sigma_dut(struct sigma_dut * dut)840829b7decSJouni Malinen static void deinit_sigma_dut(struct sigma_dut *dut)
841829b7decSJouni Malinen {
842829b7decSJouni Malinen 	free(dut->non_pref_ch_list);
843829b7decSJouni Malinen 	dut->non_pref_ch_list = NULL;
844829b7decSJouni Malinen 	free(dut->btm_query_cand_list);
845829b7decSJouni Malinen 	dut->btm_query_cand_list = NULL;
846829b7decSJouni Malinen 	free(dut->rsne_override);
847829b7decSJouni Malinen 	dut->rsne_override = NULL;
8487960e3adSJouni Malinen 	free(dut->rsnxe_override_eapol);
8497960e3adSJouni Malinen 	dut->rsnxe_override_eapol = NULL;
850829b7decSJouni Malinen 	free(dut->ap_sae_groups);
851829b7decSJouni Malinen 	dut->ap_sae_groups = NULL;
852829b7decSJouni Malinen 	free(dut->dpp_peer_uri);
853829b7decSJouni Malinen 	dut->dpp_peer_uri = NULL;
854829b7decSJouni Malinen 	free(dut->ap_sae_passwords);
855829b7decSJouni Malinen 	dut->ap_sae_passwords = NULL;
85659fab0f4SJouni Malinen 	free(dut->ap_sae_pk_modifier);
85759fab0f4SJouni Malinen 	dut->ap_sae_pk_modifier = NULL;
85859fab0f4SJouni Malinen 	free(dut->ap_sae_pk_keypair);
85959fab0f4SJouni Malinen 	dut->ap_sae_pk_keypair = NULL;
860fbf12efeSJouni Malinen 	free(dut->ap_sae_pk_keypair_sig);
861fbf12efeSJouni Malinen 	dut->ap_sae_pk_keypair_sig = NULL;
862829b7decSJouni Malinen 	free(dut->ar_ltf);
863829b7decSJouni Malinen 	dut->ar_ltf = NULL;
864829b7decSJouni Malinen 	free(dut->ap_dpp_conf_addr);
865829b7decSJouni Malinen 	dut->ap_dpp_conf_addr = NULL;
866829b7decSJouni Malinen 	free(dut->ap_dpp_conf_pkhash);
867829b7decSJouni Malinen 	dut->ap_dpp_conf_pkhash = NULL;
868829b7decSJouni Malinen 	if (dut->log_file_fd) {
869829b7decSJouni Malinen 		fclose(dut->log_file_fd);
870829b7decSJouni Malinen 		dut->log_file_fd = NULL;
871829b7decSJouni Malinen 	}
8721f76fa6dSJouni Malinen 	free(dut->p2p_ifname_buf);
8731f76fa6dSJouni Malinen 	dut->p2p_ifname_buf = NULL;
874b21f0542SJouni Malinen 	free(dut->main_ifname_2g);
875b21f0542SJouni Malinen 	dut->main_ifname_2g = NULL;
876b21f0542SJouni Malinen 	free(dut->main_ifname_5g);
877b21f0542SJouni Malinen 	dut->main_ifname_5g = NULL;
878b21f0542SJouni Malinen 	free(dut->station_ifname_2g);
879b21f0542SJouni Malinen 	dut->station_ifname_2g = NULL;
880b21f0542SJouni Malinen 	free(dut->station_ifname_5g);
881b21f0542SJouni Malinen 	dut->station_ifname_5g = NULL;
882b21f0542SJouni Malinen }
883b21f0542SJouni Malinen 
884b21f0542SJouni Malinen 
set_main_ifname(struct sigma_dut * dut,const char * val)885b21f0542SJouni Malinen static void set_main_ifname(struct sigma_dut *dut, const char *val)
886b21f0542SJouni Malinen {
887b21f0542SJouni Malinen 	const char *pos;
888b21f0542SJouni Malinen 
889b21f0542SJouni Malinen 	dut->main_ifname = optarg;
890b21f0542SJouni Malinen 	pos = strchr(val, '/');
891b21f0542SJouni Malinen 	if (!pos)
892b21f0542SJouni Malinen 		return;
893b21f0542SJouni Malinen 	free(dut->main_ifname_2g);
894b21f0542SJouni Malinen 	dut->main_ifname_2g = malloc(pos - val + 1);
895b21f0542SJouni Malinen 	if (dut->main_ifname_2g) {
896b21f0542SJouni Malinen 		memcpy(dut->main_ifname_2g, val, pos - val);
897b21f0542SJouni Malinen 		dut->main_ifname_2g[pos - val] = '\0';
898b21f0542SJouni Malinen 	}
899b21f0542SJouni Malinen 	free(dut->main_ifname_5g);
900b21f0542SJouni Malinen 	dut->main_ifname_5g = strdup(pos + 1);
901b21f0542SJouni Malinen }
902b21f0542SJouni Malinen 
903b21f0542SJouni Malinen 
set_station_ifname(struct sigma_dut * dut,const char * val)904b21f0542SJouni Malinen static void set_station_ifname(struct sigma_dut *dut, const char *val)
905b21f0542SJouni Malinen {
906b21f0542SJouni Malinen 	const char *pos;
907b21f0542SJouni Malinen 
908b21f0542SJouni Malinen 	dut->station_ifname = optarg;
909b21f0542SJouni Malinen 	pos = strchr(val, '/');
910b21f0542SJouni Malinen 	if (!pos)
911b21f0542SJouni Malinen 		return;
912b21f0542SJouni Malinen 	free(dut->station_ifname_2g);
913b21f0542SJouni Malinen 	dut->station_ifname_2g = malloc(pos - val + 1);
914b21f0542SJouni Malinen 	if (dut->station_ifname_2g) {
915b21f0542SJouni Malinen 		memcpy(dut->station_ifname_2g, val, pos - val);
916b21f0542SJouni Malinen 		dut->station_ifname_2g[pos - val] = '\0';
917b21f0542SJouni Malinen 	}
918b21f0542SJouni Malinen 	free(dut->station_ifname_5g);
919b21f0542SJouni Malinen 	dut->station_ifname_5g = strdup(pos + 1);
920829b7decSJouni Malinen }
921829b7decSJouni Malinen 
922829b7decSJouni Malinen 
923cd4e3c3eSJouni Malinen static const char * const license1 =
924cd4e3c3eSJouni Malinen "sigma_dut - WFA Sigma DUT/CA\n"
925cd4e3c3eSJouni Malinen "----------------------------\n"
926cd4e3c3eSJouni Malinen "\n"
927cd4e3c3eSJouni Malinen "Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
9289d7e31d5SJouni Malinen "Copyright (c) 2011-2017, Qualcomm Atheros, Inc.\n"
9295b16b51eSJouni Malinen "Copyright (c) 2018-2019, The Linux Foundation\n"
930cd4e3c3eSJouni Malinen "All Rights Reserved.\n"
931cd4e3c3eSJouni Malinen "Licensed under the Clear BSD license.\n"
932cd4e3c3eSJouni Malinen "\n";
933cd4e3c3eSJouni Malinen static const char * const license2 =
934cd4e3c3eSJouni Malinen "Redistribution and use in source and binary forms, with or without\n"
935cd4e3c3eSJouni Malinen "modification, are permitted (subject to the limitations in the\n"
936cd4e3c3eSJouni Malinen "disclaimer below) provided that the following conditions are met:\n"
937cd4e3c3eSJouni Malinen "\n";
938cd4e3c3eSJouni Malinen static const char * const license3 =
939cd4e3c3eSJouni Malinen "* Redistributions of source code must retain the above copyright notice,\n"
940cd4e3c3eSJouni Malinen "  this list of conditions and the following disclaimer.\n"
941cd4e3c3eSJouni Malinen "\n"
942cd4e3c3eSJouni Malinen "* Redistributions in binary form must reproduce the above copyright\n"
943cd4e3c3eSJouni Malinen "  notice, this list of conditions and the following disclaimer in the\n"
944cd4e3c3eSJouni Malinen "  documentation and/or other materials provided with the distribution.\n"
945cd4e3c3eSJouni Malinen "\n"
946cd4e3c3eSJouni Malinen "* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
947cd4e3c3eSJouni Malinen "  contributors may be used to endorse or promote products derived from\n"
948cd4e3c3eSJouni Malinen "  this software without specific prior written permission.\n"
949cd4e3c3eSJouni Malinen "\n";
950cd4e3c3eSJouni Malinen static const char * const license4 =
951cd4e3c3eSJouni Malinen "NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
952cd4e3c3eSJouni Malinen "BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
953cd4e3c3eSJouni Malinen "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
954cd4e3c3eSJouni Malinen "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
955cd4e3c3eSJouni Malinen "FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
956cd4e3c3eSJouni Malinen "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
957cd4e3c3eSJouni Malinen "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
958cd4e3c3eSJouni Malinen "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
959cd4e3c3eSJouni Malinen "USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
960cd4e3c3eSJouni Malinen "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
961cd4e3c3eSJouni Malinen "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
962cd4e3c3eSJouni Malinen "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
963cd4e3c3eSJouni Malinen 
964cd4e3c3eSJouni Malinen 
print_license(void)965cd4e3c3eSJouni Malinen static void print_license(void)
966cd4e3c3eSJouni Malinen {
967cd4e3c3eSJouni Malinen 	printf("%s%s%s%s\n",
968cd4e3c3eSJouni Malinen 	       license1, license2, license3, license4);
969cd4e3c3eSJouni Malinen }
970cd4e3c3eSJouni Malinen 
971cd4e3c3eSJouni Malinen 
usage(void)9725174e020SJouni Malinen static void usage(void)
9735174e020SJouni Malinen {
97447867204SVeerendranath Jakkam 	printf("usage: sigma_dut [-aABdfGqDIntuVW234] [-p<port>] "
9755174e020SJouni Malinen 	       "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
9765174e020SJouni Malinen 	       "       [-M<main ifname>] [-R<radio ifname>] "
9775174e020SJouni Malinen 	       "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
9785174e020SJouni Malinen 	       "       [-T<throughput pktsize>] \\\n"
9795174e020SJouni Malinen 	       "       [-w<wpa_supplicant/hostapd ctrl_iface dir>] \\\n"
9805174e020SJouni Malinen 	       "       [-H <hostapd log file>] \\\n"
9815174e020SJouni Malinen 	       "       [-F <hostapd binary path>] \\\n"
9825174e020SJouni Malinen 	       "       [-j <hostapd ifname>] \\\n"
9835174e020SJouni Malinen 	       "       [-J <wpa_supplicant debug log>] \\\n"
9845174e020SJouni Malinen 	       "       [-C <certificate path>] \\\n"
9855174e020SJouni Malinen 	       "       [-v <version string>] \\\n"
9865174e020SJouni Malinen 	       "       [-L <summary log>] \\\n"
9875174e020SJouni Malinen 	       "       [-c <wifi chip type: WCN or ATHEROS or "
9885174e020SJouni Malinen 	       "AR6003 or MAC80211 or QNXNTO or OPENWRT or LINUX-WCN>] \\\n"
9895174e020SJouni Malinen 	       "       [-i <IP address of the AP>] \\\n"
9905174e020SJouni Malinen 	       "       [-k <subnet mask for the AP>] \\\n"
9915174e020SJouni Malinen 	       "       [-K <sigma_dut log file directory>] \\\n"
9925174e020SJouni Malinen 	       "       [-e <hostapd entropy file>] \\\n"
9935174e020SJouni Malinen 	       "       [-N <device_get_info vendor>] \\\n"
9945174e020SJouni Malinen 	       "       [-o <device_get_info model>] \\\n"
9955174e020SJouni Malinen 	       "       [-O <device_get_info version>] \\\n"
9965174e020SJouni Malinen #ifdef MIRACAST
9975174e020SJouni Malinen 	       "       [-x <sink|source>] \\\n"
9985174e020SJouni Malinen 	       "       [-y <Miracast library path>] \\\n"
9995174e020SJouni Malinen #endif /* MIRACAST */
10005174e020SJouni Malinen 	       "       [-z <client socket directory path \\\n"
10015174e020SJouni Malinen 	       "       Ex: </data/vendor/wifi/sockets>] \\\n"
1002c9bc15d1SAlexei Avshalom Lazar 	       "       [-Z <Override default tmp dir path>] \\\n"
1003*f7a2cbf9SVinita S. Maloo 	       "       [-5 <WFD timeout override>] \\\n"
10045174e020SJouni Malinen 	       "       [-r <HT40 or 2.4_HT40>]\n");
10055174e020SJouni Malinen 	printf("local command: sigma_dut [-p<port>] <-l<cmd>>\n");
10065174e020SJouni Malinen }
10075174e020SJouni Malinen 
10085174e020SJouni Malinen 
main(int argc,char * argv[])1009cd4e3c3eSJouni Malinen int main(int argc, char *argv[])
1010cd4e3c3eSJouni Malinen {
1011cd4e3c3eSJouni Malinen 	int c;
1012cd4e3c3eSJouni Malinen 	int daemonize = 0;
1013cd4e3c3eSJouni Malinen 	int port = SIGMA_DUT_PORT;
1014cd4e3c3eSJouni Malinen 	char *local_cmd = NULL;
1015091e253dSPurushottam Kushwaha 	int internal_dhcp_enabled = 0;
1016cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1017cd4e3c3eSJouni Malinen 	char *env_str = NULL;
1018cd4e3c3eSJouni Malinen 	char buf[20];
1019cd4e3c3eSJouni Malinen 	char *sigma_ctrl_sock = NULL; /* env used for QNX */
1020cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1021cd4e3c3eSJouni Malinen 
1022cd4e3c3eSJouni Malinen 	memset(&sigma_dut, 0, sizeof(sigma_dut));
1023cd4e3c3eSJouni Malinen 	set_defaults(&sigma_dut);
1024cd4e3c3eSJouni Malinen 
1025cd4e3c3eSJouni Malinen 	for (;;) {
1026cd4e3c3eSJouni Malinen 		c = getopt(argc, argv,
1027*f7a2cbf9SVinita S. Maloo 			   "aAb:Bc:C:dDE:e:fF:gGhH:j:J:i:Ik:K:l:L:m:M:nN:o:O:p:P:qr:R:s:S:tT:uv:VWw:x:y:z:Z:2345:");
1028cd4e3c3eSJouni Malinen 		if (c < 0)
1029cd4e3c3eSJouni Malinen 			break;
1030cd4e3c3eSJouni Malinen 		switch (c) {
1031cd4e3c3eSJouni Malinen 		case 'a':
1032cd4e3c3eSJouni Malinen 			sigma_dut.ap_anqpserver = 1;
1033cd4e3c3eSJouni Malinen 			break;
1034cd4e3c3eSJouni Malinen 		case 'b':
1035cd4e3c3eSJouni Malinen 			sigma_dut.bridge = optarg;
1036cd4e3c3eSJouni Malinen 			break;
1037cd4e3c3eSJouni Malinen 		case 'B':
1038cd4e3c3eSJouni Malinen 			daemonize++;
1039cd4e3c3eSJouni Malinen 			break;
1040cd4e3c3eSJouni Malinen 		case 'C':
1041cd4e3c3eSJouni Malinen 			sigma_cert_path = optarg;
1042cd4e3c3eSJouni Malinen 			break;
1043cd4e3c3eSJouni Malinen 		case 'd':
1044cd4e3c3eSJouni Malinen 			if (sigma_dut.debug_level > 0)
1045cd4e3c3eSJouni Malinen 				sigma_dut.debug_level--;
1046cd4e3c3eSJouni Malinen 			break;
1047cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1048cd4e3c3eSJouni Malinen 		case 'E':
1049cd4e3c3eSJouni Malinen 			sigma_ctrl_sock = optarg;
1050cd4e3c3eSJouni Malinen 			break;
1051cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1052cd4e3c3eSJouni Malinen 		case 'D':
1053cd4e3c3eSJouni Malinen 			sigma_dut.stdout_debug = 1;
1054cd4e3c3eSJouni Malinen 			break;
1055cd4e3c3eSJouni Malinen 		case 'e':
1056cd4e3c3eSJouni Malinen 			sigma_dut.hostapd_entropy_log = optarg;
1057cd4e3c3eSJouni Malinen 			break;
1058cd4e3c3eSJouni Malinen 		case 'f':
1059cd4e3c3eSJouni Malinen 			/* Disable writing stats */
1060cd4e3c3eSJouni Malinen 			sigma_dut.write_stats = 0;
1061cd4e3c3eSJouni Malinen 			break;
1062d6bf1b4aSJouni Malinen 		case 'F':
1063d6bf1b4aSJouni Malinen 			sigma_dut.hostapd_bin = optarg;
1064d6bf1b4aSJouni Malinen 			break;
1065091e253dSPurushottam Kushwaha 		case 'g':
1066091e253dSPurushottam Kushwaha 			/* Enable internal processing of P2P group formation
1067091e253dSPurushottam Kushwaha 			 * events to start/stop DHCP server/client. */
1068091e253dSPurushottam Kushwaha 			internal_dhcp_enabled = 1;
1069091e253dSPurushottam Kushwaha 			break;
1070d6bf1b4aSJouni Malinen 		case 'G':
1071d6bf1b4aSJouni Malinen 			sigma_dut.use_hostapd_pid_file = 1;
1072d6bf1b4aSJouni Malinen 			break;
1073cd4e3c3eSJouni Malinen 		case 'H':
1074cd4e3c3eSJouni Malinen 			sigma_dut.hostapd_debug_log = optarg;
1075cd4e3c3eSJouni Malinen 			break;
1076cd4e3c3eSJouni Malinen 		case 'I':
1077cd4e3c3eSJouni Malinen 			print_license();
1078cd4e3c3eSJouni Malinen 			exit(0);
1079cd4e3c3eSJouni Malinen 			break;
1080d6bf1b4aSJouni Malinen 		case 'j':
1081d6bf1b4aSJouni Malinen 			sigma_dut.hostapd_ifname = optarg;
1082d6bf1b4aSJouni Malinen 			break;
10833e8267ecSAlexei Avshalom Lazar 		case 'J':
10843e8267ecSAlexei Avshalom Lazar 			sigma_dut.wpa_supplicant_debug_log = optarg;
10853e8267ecSAlexei Avshalom Lazar 			break;
1086cd4e3c3eSJouni Malinen 		case 'l':
1087cd4e3c3eSJouni Malinen 			local_cmd = optarg;
1088cd4e3c3eSJouni Malinen 			break;
1089cd4e3c3eSJouni Malinen 		case 'L':
1090cd4e3c3eSJouni Malinen 			sigma_dut.summary_log = optarg;
1091cd4e3c3eSJouni Malinen 			break;
1092cd4e3c3eSJouni Malinen 		case 'p':
1093cd4e3c3eSJouni Malinen 			port = atoi(optarg);
1094cd4e3c3eSJouni Malinen 			break;
1095f2af39bfSDanny Segal 		case 'P':
10961f76fa6dSJouni Malinen 			sigma_dut.p2p_ifname = optarg;
1097f2af39bfSDanny Segal 			break;
1098cd4e3c3eSJouni Malinen 		case 'q':
1099cd4e3c3eSJouni Malinen 			sigma_dut.debug_level++;
1100cd4e3c3eSJouni Malinen 			break;
1101cd4e3c3eSJouni Malinen 		case 'r':
1102cd4e3c3eSJouni Malinen 			if (strcmp(optarg, "HT40") == 0) {
1103bf8af292SPradeep Reddy Potteti 				sigma_dut.default_11na_ap_chwidth = AP_40;
1104bf8af292SPradeep Reddy Potteti 			} else if (strcmp(optarg, "2.4_HT40") == 0) {
1105bf8af292SPradeep Reddy Potteti 				sigma_dut.default_11ng_ap_chwidth = AP_40;
1106cd4e3c3eSJouni Malinen 			} else {
1107cd4e3c3eSJouni Malinen 				printf("Unsupported -r value\n");
1108cd4e3c3eSJouni Malinen 				exit(1);
1109cd4e3c3eSJouni Malinen 			}
1110cd4e3c3eSJouni Malinen 			break;
1111cd4e3c3eSJouni Malinen 		case 'R': {
1112cd4e3c3eSJouni Malinen 			static int num_radio = 0;
1113cd4e3c3eSJouni Malinen 			static char **radio_ptr = sigma_radio_ifname;
1114cd4e3c3eSJouni Malinen 
1115cd4e3c3eSJouni Malinen 			num_radio++;
1116cd4e3c3eSJouni Malinen 			if (num_radio > MAX_RADIO) {
1117cd4e3c3eSJouni Malinen 				printf("Multiple radio support limit (%d) exceeded\n",
1118cd4e3c3eSJouni Malinen 				       MAX_RADIO);
1119cd4e3c3eSJouni Malinen 				exit(1);
1120cd4e3c3eSJouni Malinen 			}
1121cd4e3c3eSJouni Malinen 			*radio_ptr++ = optarg;
1122cd4e3c3eSJouni Malinen 			break;
1123cd4e3c3eSJouni Malinen 		}
1124cd4e3c3eSJouni Malinen 		case 's':
1125cd4e3c3eSJouni Malinen 			sigma_dut.sniffer_ifname = optarg;
1126cd4e3c3eSJouni Malinen 			break;
1127cd4e3c3eSJouni Malinen 		case 't':
1128cd4e3c3eSJouni Malinen 			sigma_dut.no_timestamps = 1;
1129cd4e3c3eSJouni Malinen 			break;
1130cd4e3c3eSJouni Malinen 		case 'T':
1131cd4e3c3eSJouni Malinen 			sigma_dut.throughput_pktsize = atoi(optarg);
1132c2493f83SJouni Malinen 			if (sigma_dut.throughput_pktsize == 0) {
1133cd4e3c3eSJouni Malinen 				printf("Invalid -T value\n");
1134cd4e3c3eSJouni Malinen 				exit(0);
1135cd4e3c3eSJouni Malinen 			}
1136cd4e3c3eSJouni Malinen 			break;
1137cd4e3c3eSJouni Malinen 		case 'm':
1138cd4e3c3eSJouni Malinen 			sigma_dut.set_macaddr = optarg;
1139cd4e3c3eSJouni Malinen 			break;
1140cd4e3c3eSJouni Malinen 		case 'M':
1141b21f0542SJouni Malinen 			set_main_ifname(&sigma_dut, optarg);
1142cd4e3c3eSJouni Malinen 			break;
1143cd4e3c3eSJouni Malinen 		case 'n':
1144cd4e3c3eSJouni Malinen 			sigma_dut.no_ip_addr_set = 1;
1145cd4e3c3eSJouni Malinen 			break;
11465db3b104SJouni Malinen 		case 'N':
11475db3b104SJouni Malinen 			sigma_dut.vendor_name = optarg;
11485db3b104SJouni Malinen 			break;
11495db3b104SJouni Malinen 		case 'o':
11505db3b104SJouni Malinen 			sigma_dut.model_name = optarg;
11515db3b104SJouni Malinen 			break;
11525db3b104SJouni Malinen 		case 'O':
11535db3b104SJouni Malinen 			sigma_dut.version_name = optarg;
11545db3b104SJouni Malinen 			break;
11550128bf99SKiran Kumar Lokere 		case 'K':
11560128bf99SKiran Kumar Lokere 			sigma_dut.log_file_dir = optarg;
11570128bf99SKiran Kumar Lokere 			break;
1158cd4e3c3eSJouni Malinen 		case 'S':
1159b21f0542SJouni Malinen 			set_station_ifname(&sigma_dut, optarg);
1160cd4e3c3eSJouni Malinen 			break;
1161cd4e3c3eSJouni Malinen 		case 'w':
1162cd4e3c3eSJouni Malinen 			sigma_hapd_ctrl = optarg;
1163cd4e3c3eSJouni Malinen 			sigma_wpas_ctrl = optarg;
1164cd4e3c3eSJouni Malinen 			break;
1165cd4e3c3eSJouni Malinen 		case 'i':
1166cd4e3c3eSJouni Malinen 			ap_inet_addr = optarg;
1167cd4e3c3eSJouni Malinen 			break;
1168cd4e3c3eSJouni Malinen 		case 'k':
1169cd4e3c3eSJouni Malinen 			ap_inet_mask = optarg;
1170cd4e3c3eSJouni Malinen 			break;
1171cd4e3c3eSJouni Malinen 		case 'c':
1172cd4e3c3eSJouni Malinen 			printf("%s", optarg);
1173cd4e3c3eSJouni Malinen 			if (set_wifi_chip(optarg) < 0)
1174cd4e3c3eSJouni Malinen 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1175cd4e3c3eSJouni Malinen 						"WRONG CHIP TYPE: SAP will "
1176cd4e3c3eSJouni Malinen 						"not load");
1177cd4e3c3eSJouni Malinen 			break;
1178cd4e3c3eSJouni Malinen 		case 'v':
1179cd4e3c3eSJouni Malinen 			sigma_dut.version = optarg;
1180cd4e3c3eSJouni Malinen 			break;
1181cd4e3c3eSJouni Malinen 		case 'V':
1182cd4e3c3eSJouni Malinen 			printf("sigma_dut " SIGMA_DUT_VER "\n");
1183cd4e3c3eSJouni Malinen 			exit(0);
1184cd4e3c3eSJouni Malinen 			break;
1185cd4e3c3eSJouni Malinen 		case 'W':
1186cd4e3c3eSJouni Malinen 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1187cd4e3c3eSJouni Malinen 					"Running WMM-AC test suite");
1188cd4e3c3eSJouni Malinen 			sigma_wmm_ac = 1;
1189cd4e3c3eSJouni Malinen 			break;
1190cd4e3c3eSJouni Malinen 		case 'u':
1191cd4e3c3eSJouni Malinen 		       sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1192cd4e3c3eSJouni Malinen 				       "Use iface down/up in reset cmd");
1193cd4e3c3eSJouni Malinen 		       sigma_dut.iface_down_on_reset = 1;
1194cd4e3c3eSJouni Malinen 		       break;
119573d7af09SBala Krishna Bhamidipati 		case 'A':
119673d7af09SBala Krishna Bhamidipati 			sigma_dut.sim_no_username = 1;
119773d7af09SBala Krishna Bhamidipati 			break;
11989c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
11999c381f59SAmarnath Hullur Subramanyam 		case 'x':
12009c381f59SAmarnath Hullur Subramanyam 			if (strcmp(optarg, "sink") == 0) {
12019c381f59SAmarnath Hullur Subramanyam 				sigma_dut.wfd_device_type = 1;
12029c381f59SAmarnath Hullur Subramanyam 				sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
12039c381f59SAmarnath Hullur Subramanyam 						"Device Type is SINK");
12049c381f59SAmarnath Hullur Subramanyam 			} else if (strcmp(optarg, "source") == 0) {
12059c381f59SAmarnath Hullur Subramanyam 				sigma_dut.wfd_device_type = 0;
12069c381f59SAmarnath Hullur Subramanyam 				sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
12079c381f59SAmarnath Hullur Subramanyam 						"Device Type is SOURCE");
12089c381f59SAmarnath Hullur Subramanyam 			}
12099c381f59SAmarnath Hullur Subramanyam 			break;
12109c381f59SAmarnath Hullur Subramanyam 		case 'y':
12119c381f59SAmarnath Hullur Subramanyam 			sigma_dut.miracast_lib_path = optarg;
12129c381f59SAmarnath Hullur Subramanyam 			break;
12139c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
1214525dbfd1SRajiv Ranjan 		case 'z':
1215525dbfd1SRajiv Ranjan 			client_socket_path = optarg;
1216525dbfd1SRajiv Ranjan 			break;
1217c9bc15d1SAlexei Avshalom Lazar 		case 'Z':
1218c9bc15d1SAlexei Avshalom Lazar 			sigma_dut.sigma_tmpdir = optarg;
1219c9bc15d1SAlexei Avshalom Lazar 			break;
122011e5521bSJouni Malinen 		case '2':
122111e5521bSJouni Malinen 			sigma_dut.sae_h2e_default = 1;
122211e5521bSJouni Malinen 			break;
12236010ce7dSHu Wang 		case '3':
12246010ce7dSHu Wang 			sigma_dut.owe_ptk_workaround = 1;
12256010ce7dSHu Wang 			break;
122647867204SVeerendranath Jakkam 		case '4':
122747867204SVeerendranath Jakkam 			sigma_dut.client_privacy_default = 1;
122847867204SVeerendranath Jakkam 			break;
1229*f7a2cbf9SVinita S. Maloo 		case '5': {
1230*f7a2cbf9SVinita S. Maloo 			int timeout;
1231*f7a2cbf9SVinita S. Maloo 
1232*f7a2cbf9SVinita S. Maloo 			errno = 0;
1233*f7a2cbf9SVinita S. Maloo 			timeout = strtol(optarg, NULL, 10);
1234*f7a2cbf9SVinita S. Maloo 			if (errno || timeout < 0) {
1235*f7a2cbf9SVinita S. Maloo 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1236*f7a2cbf9SVinita S. Maloo 					       "failed to set default_timeout");
1237*f7a2cbf9SVinita S. Maloo 				return -1;
1238*f7a2cbf9SVinita S. Maloo 			}
1239*f7a2cbf9SVinita S. Maloo 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1240*f7a2cbf9SVinita S. Maloo 					"default timeout set to %d", timeout);
1241*f7a2cbf9SVinita S. Maloo 			sigma_dut.user_config_timeout = timeout;
1242*f7a2cbf9SVinita S. Maloo 			break;
1243*f7a2cbf9SVinita S. Maloo 		}
1244cd4e3c3eSJouni Malinen 		case 'h':
1245cd4e3c3eSJouni Malinen 		default:
12465174e020SJouni Malinen 			usage();
1247cd4e3c3eSJouni Malinen 			exit(0);
1248cd4e3c3eSJouni Malinen 			break;
1249cd4e3c3eSJouni Malinen 		}
1250cd4e3c3eSJouni Malinen 	}
1251cd4e3c3eSJouni Malinen 
12521f76fa6dSJouni Malinen 	determine_sigma_p2p_ifname(&sigma_dut);
12539c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
12549c381f59SAmarnath Hullur Subramanyam 	miracast_init(&sigma_dut);
12559c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
1256cd4e3c3eSJouni Malinen 	if (local_cmd)
1257cd4e3c3eSJouni Malinen 		return run_local_cmd(port, local_cmd);
1258cd4e3c3eSJouni Malinen 
125908eaeba2SPradeep Reddy Potteti 	if ((wifi_chip_type == DRIVER_QNXNTO ||
126008eaeba2SPradeep Reddy Potteti 	     wifi_chip_type == DRIVER_LINUX_WCN) &&
1261d2095485SJouni Malinen 	    (!sigma_dut.main_ifname || !sigma_dut.station_ifname)) {
1262cd4e3c3eSJouni Malinen 		sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
126308eaeba2SPradeep Reddy Potteti 				"Interface should be provided for QNX/LINUX-WCN driver - check option M and S");
1264cd4e3c3eSJouni Malinen 	}
1265cd4e3c3eSJouni Malinen 
1266d06f100bSPriyadharshini Gowthaman 	if (get_openwrt_driver_type() == OPENWRT_DRIVER_ATHEROS)
1267d06f100bSPriyadharshini Gowthaman 		get_nl80211_config_enable_option(&sigma_dut);
1268d06f100bSPriyadharshini Gowthaman 
1269f0f8805aSVenkateswara Naralasetty 	sigma_dut_get_device_driver_name(get_main_ifname(&sigma_dut),
1270f0f8805aSVenkateswara Naralasetty 					 sigma_dut.device_driver,
1271f0f8805aSVenkateswara Naralasetty 					 sizeof(sigma_dut.device_driver));
1272f0f8805aSVenkateswara Naralasetty 	if (sigma_dut.device_driver[0])
1273f0f8805aSVenkateswara Naralasetty 		sigma_dut_print(&sigma_dut, DUT_MSG_DEBUG, "device driver: %s",
1274f0f8805aSVenkateswara Naralasetty 				sigma_dut.device_driver);
1275f0f8805aSVenkateswara Naralasetty 
1276291d97daSPeng Xu #ifdef NL80211_SUPPORT
1277291d97daSPeng Xu 	sigma_dut.nl_ctx = nl80211_init(&sigma_dut);
1278291d97daSPeng Xu #endif /* NL80211_SUPPORT */
1279cd4e3c3eSJouni Malinen 	sigma_dut_register_cmds();
1280cd4e3c3eSJouni Malinen 
1281cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1282cd4e3c3eSJouni Malinen 	/* Try to open socket in other env dev */
1283cd4e3c3eSJouni Malinen 	if (sigma_ctrl_sock) {
1284cd4e3c3eSJouni Malinen 		env_str = getenv("SOCK");
1285cd4e3c3eSJouni Malinen 		if (env_str) {
1286cd4e3c3eSJouni Malinen 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1287cd4e3c3eSJouni Malinen 					"SOCK=%s", env_str);
1288cd4e3c3eSJouni Malinen 		}
1289cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
1290cd4e3c3eSJouni Malinen 		if (putenv(buf) != 0) {
1291cd4e3c3eSJouni Malinen 			sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1292cd4e3c3eSJouni Malinen 					"putenv() failed setting SOCK");
1293cd4e3c3eSJouni Malinen 			return EXIT_FAILURE;
1294cd4e3c3eSJouni Malinen 		}
1295cd4e3c3eSJouni Malinen 	}
1296cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1297cd4e3c3eSJouni Malinen 
1298cd4e3c3eSJouni Malinen 	if (open_socket(&sigma_dut, port) < 0)
1299cd4e3c3eSJouni Malinen 		return -1;
1300cd4e3c3eSJouni Malinen 
1301cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1302cd4e3c3eSJouni Malinen 	/* restore back the SOCK */
1303cd4e3c3eSJouni Malinen 	if (sigma_ctrl_sock) {
1304cd4e3c3eSJouni Malinen 		if (env_str) {
1305cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
1306cd4e3c3eSJouni Malinen 			if (putenv(buf) != 0) {
1307cd4e3c3eSJouni Malinen 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1308cd4e3c3eSJouni Malinen 						"putenv() failed setting SOCK");
1309cd4e3c3eSJouni Malinen 				return EXIT_FAILURE;
1310cd4e3c3eSJouni Malinen 			}
1311cd4e3c3eSJouni Malinen 		} else {
1312cd4e3c3eSJouni Malinen 			/* unset the env for sock */
1313cd4e3c3eSJouni Malinen 			unsetenv("SOCK");
1314cd4e3c3eSJouni Malinen 		}
1315cd4e3c3eSJouni Malinen 	}
1316cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1317cd4e3c3eSJouni Malinen 
1318cd4e3c3eSJouni Malinen 	if (daemonize) {
1319cd4e3c3eSJouni Malinen 		if (daemon(0, 0) < 0) {
1320cd4e3c3eSJouni Malinen 			perror("daemon");
1321cd4e3c3eSJouni Malinen 			exit(-1);
1322cd4e3c3eSJouni Malinen 		}
1323cd4e3c3eSJouni Malinen 	} else {
1324cd4e3c3eSJouni Malinen #ifdef __linux__
1325cd4e3c3eSJouni Malinen 		setlinebuf(stdout);
1326cd4e3c3eSJouni Malinen #endif /* __linux__ */
1327cd4e3c3eSJouni Malinen 	}
1328cd4e3c3eSJouni Malinen 
1329091e253dSPurushottam Kushwaha 	if (internal_dhcp_enabled)
1330091e253dSPurushottam Kushwaha 		p2p_create_event_thread(&sigma_dut);
1331091e253dSPurushottam Kushwaha 
1332cd4e3c3eSJouni Malinen 	run_loop(&sigma_dut);
1333cd4e3c3eSJouni Malinen 
1334cd4e3c3eSJouni Malinen #ifdef CONFIG_SNIFFER
1335cd4e3c3eSJouni Malinen 	sniffer_close(&sigma_dut);
1336cd4e3c3eSJouni Malinen #endif /* CONFIG_SNIFFER */
1337cd4e3c3eSJouni Malinen 
1338cd4e3c3eSJouni Malinen 	close_socket(&sigma_dut);
13399c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
13409c381f59SAmarnath Hullur Subramanyam 	miracast_deinit(&sigma_dut);
13419c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
1342829b7decSJouni Malinen 	deinit_sigma_dut(&sigma_dut);
1343291d97daSPeng Xu #ifdef NL80211_SUPPORT
1344291d97daSPeng Xu 	nl80211_deinit(&sigma_dut, sigma_dut.nl_ctx);
1345291d97daSPeng Xu #endif /* NL80211_SUPPORT */
1346cd4e3c3eSJouni Malinen 	sigma_dut_unreg_cmds(&sigma_dut);
13471bde7947SAnkita Bajaj #ifdef ANDROID
13481bde7947SAnkita Bajaj 	hlp_thread_cleanup(&sigma_dut);
13491bde7947SAnkita Bajaj #endif /* ANDROID */
1350cd4e3c3eSJouni Malinen 
1351cd4e3c3eSJouni Malinen 	return 0;
1352cd4e3c3eSJouni Malinen }
1353