xref: /wlan-dirver/utils/sigma-dut/sigma_dut.c (revision f7a2cbf925c5a97f0d23d3c32665b7921dc96e4d)
1 /*
2  * Sigma Control API DUT (station/AP)
3  * Copyright (c) 2010-2011, Atheros Communications, Inc.
4  * Copyright (c) 2011-2017, Qualcomm Atheros, Inc.
5  * Copyright (c) 2018-2019, The Linux Foundation
6  * All Rights Reserved.
7  * Licensed under the Clear BSD license. See README for more details.
8  */
9 
10 #include "sigma_dut.h"
11 #ifdef __linux__
12 #include <signal.h>
13 #include <netinet/tcp.h>
14 #endif /* __linux__ */
15 #include "wpa_ctrl.h"
16 #include "wpa_helpers.h"
17 #include "miracast.h"
18 
19 #define SIGMA_DUT_PORT 9000
20 #define MAX_CONNECTIONS 4
21 
22 extern enum driver_type wifi_chip_type;
23 
24 static struct sigma_dut sigma_dut;
25 
26 char *sigma_radio_ifname[MAX_RADIO] = {};
27 char *sigma_wpas_ctrl = "/var/run/wpa_supplicant/";
28 char *sigma_hapd_ctrl = NULL;
29 char *client_socket_path = NULL;
30 char *ap_inet_addr = "192.168.43.1";
31 char *ap_inet_mask = "255.255.255.0";
32 char *sigma_cert_path = "/etc/wpa_supplicant";
33 
34 /* For WMM-AC testing this set to 1 through argument,
35  * otherwise default WMM-PS 0 */
36 int sigma_wmm_ac = 0;
37 
38 
39 #ifdef ANDROID
40 #include <android/log.h>
41 
42 #ifdef ANDROID_WIFI_HAL
43 
wifi_hal_event_thread(void * ptr)44 static void * wifi_hal_event_thread(void *ptr)
45 {
46 	struct sigma_dut *dut = ptr;
47 
48 	wifi_event_loop(dut->wifi_hal_handle);
49 	pthread_exit(0);
50 
51 	return NULL;
52 }
53 
54 
wifi_hal_initialize(struct sigma_dut * dut)55 int wifi_hal_initialize(struct sigma_dut *dut)
56 {
57 	pthread_t thread1;
58 	wifi_error err;
59 	const char *ifname;
60 
61 	if (dut->wifi_hal_initialized)
62 		return 0;
63 
64 	err = wifi_initialize(&dut->wifi_hal_handle);
65 	if (err) {
66 		sigma_dut_print(dut, DUT_MSG_ERROR,
67 				"wifi hal initialize failed");
68 		return -1;
69 	}
70 
71 	if (if_nametoindex(NAN_AWARE_IFACE))
72 		ifname = NAN_AWARE_IFACE;
73 	else
74 		ifname = "wlan0";
75 
76 	dut->wifi_hal_iface_handle = wifi_get_iface_handle(dut->wifi_hal_handle,
77 							   (char *) ifname);
78 
79 	pthread_create(&thread1, NULL, &wifi_hal_event_thread, (void *) dut);
80 	dut->wifi_hal_initialized = true;
81 
82 	return 0;
83 }
84 
85 #endif /* ANDROID_WIFI_HAL */
86 
87 
level_to_android_priority(int level)88 static enum android_LogPriority level_to_android_priority(int level)
89 {
90 	switch (level) {
91 	case DUT_MSG_ERROR:
92 		return ANDROID_LOG_ERROR;
93 	case DUT_MSG_INFO:
94 		return ANDROID_LOG_INFO;
95 	case DUT_MSG_DEBUG:
96 		return ANDROID_LOG_DEBUG;
97 	default:
98 		return ANDROID_LOG_VERBOSE;
99 	}
100 }
101 
102 #endif /* ANDROID */
103 
104 
sigma_dut_print(struct sigma_dut * dut,int level,const char * fmt,...)105 void sigma_dut_print(struct sigma_dut *dut, int level, const char *fmt, ...)
106 {
107 	va_list ap;
108 	struct timeval tv;
109 
110 	if (level < dut->debug_level)
111 		return;
112 
113 	gettimeofday(&tv, NULL);
114 #ifdef ANDROID
115 	va_start(ap, fmt);
116 	__android_log_vprint(level_to_android_priority(level),
117 			     "sigma_dut", fmt, ap);
118 	va_end(ap);
119 	if (!dut->stdout_debug)
120 		return;
121 #else /* ANDROID */
122 	if (dut->log_file_fd) {
123 		va_start(ap, fmt);
124 		fprintf(dut->log_file_fd, "%ld.%06u: ",
125 			(long) tv.tv_sec, (unsigned int) tv.tv_usec);
126 		vfprintf(dut->log_file_fd, fmt, ap);
127 		fprintf(dut->log_file_fd, "\n");
128 		va_end(ap);
129 	}
130 #endif /* ANDROID */
131 
132 	va_start(ap, fmt);
133 	printf("%ld.%06u: ", (long) tv.tv_sec,
134 	       (unsigned int) tv.tv_usec);
135 	vprintf(fmt, ap);
136 	printf("\n");
137 	va_end(ap);
138 }
139 
140 
sigma_dut_summary(struct sigma_dut * dut,const char * fmt,...)141 void sigma_dut_summary(struct sigma_dut *dut, const char *fmt, ...)
142 {
143 	va_list ap;
144 	FILE *f;
145 
146 	if (!dut->summary_log)
147 		return;
148 
149 	f = fopen(dut->summary_log, "a");
150 	if (f == NULL)
151 		return;
152 
153 	va_start(ap, fmt);
154 	vfprintf(f, fmt, ap);
155 	fprintf(f, "\n");
156 	va_end(ap);
157 	fclose(f);
158 }
159 
160 
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))161 int sigma_dut_reg_cmd(const char *cmd,
162 		      int (*validate)(struct sigma_cmd *cmd),
163 		      enum sigma_cmd_result (*process)(struct sigma_dut *dut,
164 						       struct sigma_conn *conn,
165 						       struct sigma_cmd *cmd))
166 {
167 	struct sigma_cmd_handler *h;
168 	size_t clen, len;
169 
170 	for (h = sigma_dut.cmds; h; h = h->next) {
171 		if (strcmp(h->cmd, cmd) == 0) {
172 			printf("ERROR: Duplicate sigma_dut command registration for '%s'\n",
173 			       cmd);
174 			return -1;
175 		}
176 	}
177 
178 	clen = strlen(cmd);
179 	len = sizeof(*h) + clen + 1;
180 	h = malloc(len);
181 	if (h == NULL)
182 		return -1;
183 	memset(h, 0, len);
184 	h->cmd = (char *) (h + 1); /* include in same allocation */
185 	memcpy(h->cmd, cmd, clen);
186 	h->validate = validate;
187 	h->process= process;
188 
189 	h->next = sigma_dut.cmds;
190 	sigma_dut.cmds = h;
191 
192 	return 0;
193 }
194 
195 
sigma_dut_unreg_cmds(struct sigma_dut * dut)196 static void sigma_dut_unreg_cmds(struct sigma_dut *dut)
197 {
198 	struct sigma_cmd_handler *cmd, *prev;
199 	cmd = dut->cmds;
200 	dut->cmds = NULL;
201 	while (cmd) {
202 		prev = cmd;
203 		cmd = cmd->next;
204 		free(prev);
205 	}
206 }
207 
208 
open_socket(struct sigma_dut * dut,int port)209 static int open_socket(struct sigma_dut *dut, int port)
210 {
211 	struct sockaddr_in addr;
212 #ifndef __QNXNTO__
213 	int val;
214 #endif /* !__QNXNTO__ */
215 
216 #ifdef __QNXNTO__
217 	dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
218 #else /* __QNXNTO__ */
219 	dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
220 #endif /* __QNXNTO__ */
221 	if (dut->s < 0) {
222 		sigma_dut_print(dut, DUT_MSG_ERROR, "socket: %s",
223 				strerror(errno));
224 		return -1;
225 	}
226 
227 #ifndef __QNXNTO__
228 	val = 1;
229 	if (setsockopt(dut->s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) <
230 	    0)
231 		sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt SO_REUSEADDR: "
232 				"%s", strerror(errno));
233 #endif /* !__QNXNTO__ */
234 
235 #ifdef __linux__
236 	val = 1;
237 	if (setsockopt(dut->s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) <
238 	    0)
239 		sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt TCP_NODELAY: "
240 				"%s", strerror(errno));
241 #endif /* __linux__ */
242 
243 	memset(&addr, 0, sizeof(addr));
244 	addr.sin_family = AF_INET;
245 	addr.sin_port = htons(port);
246 
247 	if (bind(dut->s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
248 		sigma_dut_print(dut, DUT_MSG_ERROR, "bind: %s",
249 				strerror(errno));
250 		goto fail;
251 	}
252 
253 	if (listen(dut->s, 5) < 0) {
254 		sigma_dut_print(dut, DUT_MSG_ERROR, "listen: %s",
255 				strerror(errno));
256 		goto fail;
257 	}
258 
259 	return 0;
260 
261 fail:
262 	shutdown(dut->s, SHUT_RDWR);
263 	close(dut->s);
264 	dut->s = -1;
265 	return -1;
266 }
267 
268 
close_socket(struct sigma_dut * dut)269 static void close_socket(struct sigma_dut *dut)
270 {
271 	shutdown(dut->s, SHUT_RDWR);
272 	close(dut->s);
273 	dut->s = -1;
274 }
275 
276 
send_resp(struct sigma_dut * dut,struct sigma_conn * conn,enum sigma_status status,const char * buf)277 void send_resp(struct sigma_dut *dut, struct sigma_conn *conn,
278 	       enum sigma_status status, const char *buf)
279 {
280 	struct msghdr msg;
281 	struct iovec iov[4];
282 	size_t elems;
283 
284 	if (!conn)
285 		return;
286 
287 	sigma_dut_print(dut, DUT_MSG_INFO, "resp: status=%d buf=%s",
288 			status, buf ? buf : "N/A");
289 
290 	iov[0].iov_base = "status,";
291 	iov[0].iov_len = 7;
292 	switch (status) {
293 	case SIGMA_RUNNING:
294 		iov[1].iov_base = "RUNNING,";
295 		iov[1].iov_len = 8;
296 		break;
297 	case SIGMA_INVALID:
298 		iov[1].iov_base = "INVALID,";
299 		iov[1].iov_len = 8;
300 		break;
301 	case SIGMA_ERROR:
302 		iov[1].iov_base = "ERROR,";
303 		iov[1].iov_len = 6;
304 		break;
305 	case SIGMA_COMPLETE:
306 		iov[1].iov_base = "COMPLETE,";
307 		iov[1].iov_len = 9;
308 		break;
309 	}
310 	if (status != SIGMA_RUNNING) {
311 		sigma_dut_summary(dut, "CAPI resp: status,%s%s",
312 				  (char *) iov[1].iov_base, buf ? buf : "");
313 	}
314 	if (buf) {
315 		iov[2].iov_base = (void *) buf;
316 		iov[2].iov_len = strlen(buf);
317 		iov[3].iov_base = "\r\n";
318 		iov[3].iov_len = 2;
319 		elems = 4;
320 	} else {
321 		iov[1].iov_len--;
322 		iov[2].iov_base = "\r\n";
323 		iov[2].iov_len = 2;
324 		elems = 3;
325 	}
326 
327 	memset(&msg, 0, sizeof(msg));
328 	msg.msg_iov = iov;
329 	msg.msg_iovlen = elems;
330 	if (sendmsg(conn->s, &msg, 0) < 0)
331 		sigma_dut_print(dut, DUT_MSG_INFO, "sendmsg: %s",
332 				strerror(errno));
333 	dut->response_sent++;
334 }
335 
336 
get_param(struct sigma_cmd * cmd,const char * name)337 const char * get_param(struct sigma_cmd *cmd, const char *name)
338 {
339 	int i;
340 	for (i = 0; i < cmd->count; i++) {
341 		if (strcasecmp(name, cmd->params[i]) == 0)
342 			return cmd->values[i];
343 	}
344 	return NULL;
345 }
346 
347 
get_param_indexed(struct sigma_cmd * cmd,const char * name,int index)348 const char * get_param_indexed(struct sigma_cmd *cmd, const char *name,
349 			       int index)
350 {
351 	int i, j;
352 
353 	for (i = 0, j = 0; i < cmd->count; i++) {
354 		if (strcasecmp(name, cmd->params[i]) == 0) {
355 			j++;
356 			if (j > index)
357 				return cmd->values[i];
358 		}
359 	}
360 
361 	return NULL;
362 }
363 
364 
process_cmd(struct sigma_dut * dut,struct sigma_conn * conn,char * buf)365 static void process_cmd(struct sigma_dut *dut, struct sigma_conn *conn,
366 			char *buf)
367 {
368 	struct sigma_cmd_handler *h;
369 	struct sigma_cmd c;
370 	char *cmd, *pos, *pos2;
371 	int len;
372 	char txt[300];
373 	enum sigma_cmd_result res;
374 
375 	while (*buf == '\r' || *buf == '\n' || *buf == '\t' || *buf == ' ')
376 		buf++;
377 	len = strlen(buf);
378 	while (len > 0 && buf[len - 1] == ' ') {
379 		buf[len - 1] = '\0';
380 		len--;
381 	}
382 
383 	if (dut->debug_level < DUT_MSG_INFO) {
384 		pos = strchr(buf, ',');
385 		if (pos == NULL)
386 			pos = buf + len;
387 		if (pos - buf > 50)
388 			pos = buf + 50;
389 		memcpy(txt, "/====[ ", 7);
390 		pos2 = txt + 7;
391 		memcpy(pos2, buf, pos - buf);
392 		pos2 += pos - buf;
393 		*pos2++ = ' ';
394 		*pos2++ = ']';
395 		while (pos2 - txt < 70)
396 			*pos2++ = '=';
397 		*pos2++ = '\\';
398 		*pos2 = '\0';
399 		printf("\n%s\n\n", txt);
400 	}
401 
402 	sigma_dut_print(dut, DUT_MSG_INFO, "cmd: %s", buf);
403 	sigma_dut_summary(dut, "CAPI cmd: %s", buf);
404 	snprintf(txt, sizeof(txt), "NOTE CAPI:%s", buf);
405 	txt[sizeof(txt) - 1] = '\0';
406 	wpa_command(get_main_ifname(dut), txt);
407 
408 	memset(&c, 0, sizeof(c));
409 	cmd = buf;
410 	pos = strchr(cmd, ',');
411 	if (pos) {
412 		*pos++ = '\0';
413 		if (strcasecmp(cmd, "AccessPoint") == 0 ||
414 		    strcasecmp(cmd, "PowerSwitch") == 0) {
415 			pos2 = strchr(pos, ',');
416 			if (pos2 == NULL)
417 				goto invalid_params;
418 			c.params[c.count] = pos;
419 			c.values[c.count] = pos2;
420 			c.count++;
421 			pos = strchr(pos2, ',');
422 			if (pos)
423 				*pos++ = '\0';
424 		}
425 		while (pos) {
426 			pos2 = strchr(pos, ',');
427 			if (pos2 == NULL)
428 				goto invalid_params;
429 			*pos2++ = '\0';
430 			if (c.count == MAX_PARAMS) {
431 				sigma_dut_print(dut, DUT_MSG_INFO, "Too many "
432 						"parameters");
433 				goto invalid_params;
434 			}
435 			c.params[c.count] = pos;
436 			c.values[c.count] = pos2;
437 			c.count++;
438 			pos = strchr(pos2, ',');
439 			if (pos)
440 				*pos++ = '\0';
441 		}
442 	}
443 	h = dut->cmds;
444 	while (h) {
445 		if (strcasecmp(cmd, h->cmd) == 0)
446 			break;
447 		h = h->next;
448 	}
449 
450 	if (h == NULL) {
451 		sigma_dut_print(dut, DUT_MSG_INFO, "Unknown command: '%s'",
452 				cmd);
453 		send_resp(dut, conn, SIGMA_INVALID,
454 			  "errorCode,Unknown command");
455 		goto out;
456 	}
457 
458 	if (h->validate && h->validate(&c) < 0) {
459 	invalid_params:
460 		sigma_dut_print(dut, DUT_MSG_INFO, "Invalid parameters");
461 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid "
462 			  "parameters");
463 		goto out;
464 	}
465 
466 	dut->response_sent = 0;
467 	send_resp(dut, conn, SIGMA_RUNNING, NULL);
468 	sigma_dut_print(dut, DUT_MSG_INFO, "Run command: %s", cmd);
469 	res = h->process(dut, conn, &c);
470 	switch (res) {
471 	case ERROR_SEND_STATUS:
472 		send_resp(dut, conn, SIGMA_ERROR, NULL);
473 		break;
474 	case INVALID_SEND_STATUS:
475 		send_resp(dut, conn, SIGMA_INVALID, NULL);
476 		break;
477 	case STATUS_SENT:
478 	case STATUS_SENT_ERROR:
479 		break;
480 	case SUCCESS_SEND_STATUS:
481 		send_resp(dut, conn, SIGMA_COMPLETE, NULL);
482 		break;
483 	}
484 
485 	if (!conn->waiting_completion && dut->response_sent != 2) {
486 		sigma_dut_print(dut, DUT_MSG_ERROR,
487 				"ERROR: Unexpected number of status lines sent (%d) for command '%s'",
488 				dut->response_sent, cmd);
489 	}
490 
491 out:
492 	if (dut->debug_level < DUT_MSG_INFO) {
493 		pos2 = txt;
494 		*pos2++ = '\\';
495 		memset(pos2, '-', 69);
496 		pos2 += 69;
497 		*pos2++ = '/';
498 		*pos2 = '\0';
499 		printf("\n%s\n\n", txt);
500 	}
501 }
502 
503 
process_conn(struct sigma_dut * dut,struct sigma_conn * conn)504 static void process_conn(struct sigma_dut *dut, struct sigma_conn *conn)
505 {
506 	ssize_t res;
507 	int i;
508 
509 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Read from %s:%d",
510 			inet_ntoa(conn->addr.sin_addr),
511 			ntohs(conn->addr.sin_port));
512 
513 	res = recv(conn->s, conn->buf + conn->pos, MAX_CMD_LEN + 5 - conn->pos,
514 		   0);
515 	if (res < 0) {
516 		sigma_dut_print(dut, DUT_MSG_INFO, "recv: %s",
517 				strerror(errno));
518 	}
519 	if (res <= 0) {
520 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Close connection from "
521 				"%s:%d",
522 				inet_ntoa(conn->addr.sin_addr),
523 				ntohs(conn->addr.sin_port));
524 		shutdown(conn->s, SHUT_RDWR);
525 		close(conn->s);
526 		conn->s = -1;
527 		return;
528 	}
529 
530 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Received %d bytes",
531 			(int) res);
532 
533 	for (;;) {
534 		for (i = conn->pos; i < conn->pos + res; i++) {
535 			if (conn->buf[i] == '\r' || conn->buf[i] == '\n')
536 				break;
537 		}
538 
539 		if (i == conn->pos + res) {
540 			/* Full command not yet received */
541 			conn->pos += res;
542 			if (conn->pos >= MAX_CMD_LEN + 5) {
543 				sigma_dut_print(dut, DUT_MSG_INFO, "Too long "
544 						"command dropped");
545 				conn->pos = 0;
546 			}
547 			break;
548 		}
549 
550 		/* Full command received */
551 		conn->buf[i++] = '\0';
552 		process_cmd(dut, conn, conn->buf);
553 		while (i < conn->pos + res &&
554 		       (conn->buf[i] == '\r' || conn->buf[i] == '\n'))
555 			i++;
556 		memmove(conn->buf, &conn->buf[i], conn->pos + res - i);
557 		res = conn->pos + res - i;
558 		conn->pos = 0;
559 	}
560 }
561 
562 
563 static int stop_loop = 0;
564 
565 #ifdef __linux__
handle_term(int sig)566 static void handle_term(int sig)
567 {
568 	struct sigma_dut *dut = &sigma_dut;
569 
570 	if (dut->sta_2g_started || dut->sta_5g_started)
571 		stop_sta_mode(dut);
572 	stop_loop = 1;
573 	stop_event_thread();
574 	printf("sigma_dut terminating\n");
575 }
576 #endif /* __linux__ */
577 
run_loop(struct sigma_dut * dut)578 static void run_loop(struct sigma_dut *dut)
579 {
580 	struct sigma_conn conn[MAX_CONNECTIONS];
581 	int i, res, maxfd, can_accept;
582 	fd_set rfds;
583 
584 	memset(&conn, 0, sizeof(conn));
585 	for (i = 0; i < MAX_CONNECTIONS; i++)
586 		conn[i].s = -1;
587 
588 #ifdef __linux__
589 	signal(SIGINT, handle_term);
590 	signal(SIGTERM, handle_term);
591 	signal(SIGPIPE, SIG_IGN);
592 #endif /* __linux__ */
593 
594 	while (!stop_loop) {
595 		FD_ZERO(&rfds);
596 		maxfd = -1;
597 		can_accept = 0;
598 		for (i = 0; i < MAX_CONNECTIONS; i++) {
599 			if (conn[i].s >= 0) {
600 				FD_SET(conn[i].s, &rfds);
601 				if (conn[i].s > maxfd)
602 					maxfd = conn[i].s;
603 			} else if (!conn[i].waiting_completion)
604 				can_accept = 1;
605 		}
606 
607 		if (can_accept) {
608 			FD_SET(dut->s, &rfds);
609 			if (dut->s > maxfd)
610 				maxfd = dut->s;
611 		}
612 
613 
614 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for next "
615 				"command (can_accept=%d)", can_accept);
616 		res = select(maxfd + 1, &rfds, NULL, NULL, NULL);
617 		if (res < 0) {
618 			perror("select");
619 			if (!stop_loop)
620 				sleep(1);
621 			continue;
622 		}
623 
624 		if (!res) {
625 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Nothing ready");
626 			sleep(1);
627 			continue;
628 		}
629 
630 		if (FD_ISSET(dut->s, &rfds)) {
631 			for (i = 0; i < MAX_CONNECTIONS; i++) {
632 				if (conn[i].s < 0 &&
633 				    !conn[i].waiting_completion)
634 					break;
635 			}
636 			if (i == MAX_CONNECTIONS) {
637 				/*
638 				 * This cannot really happen since can_accept
639 				 * would not be set to one.
640 				 */
641 				sigma_dut_print(dut, DUT_MSG_DEBUG,
642 						"No room for new connection");
643 				continue;
644 			}
645 			conn[i].addrlen = sizeof(conn[i].addr);
646 			conn[i].s = accept(dut->s,
647 					   (struct sockaddr *) &conn[i].addr,
648 					   &conn[i].addrlen);
649 			if (conn[i].s < 0) {
650 				sigma_dut_print(dut, DUT_MSG_INFO,
651 						"accept: %s",
652 						strerror(errno));
653 				continue;
654 			}
655 
656 			sigma_dut_print(dut, DUT_MSG_DEBUG,
657 					"Connection %d from %s:%d", i,
658 					inet_ntoa(conn[i].addr.sin_addr),
659 					ntohs(conn[i].addr.sin_port));
660 			conn[i].pos = 0;
661 		}
662 
663 		for (i = 0; i < MAX_CONNECTIONS; i++) {
664 			if (conn[i].s < 0)
665 				continue;
666 			if (FD_ISSET(conn[i].s, &rfds))
667 				process_conn(dut, &conn[i]);
668 		}
669 	}
670 }
671 
672 
run_local_cmd(int port,char * lcmd)673 static int run_local_cmd(int port, char *lcmd)
674 {
675 	int s, len;
676 	struct sockaddr_in addr;
677 	char cmd[MAX_CMD_LEN];
678 	ssize_t res;
679 	int count;
680 	char resp[MAX_CMD_LEN];
681 	int pos;
682 
683 
684 	if (strlen(lcmd) > sizeof(cmd) - 4) {
685 		printf("Too long command\n");
686 		return -1;
687 	}
688 	len = snprintf(cmd, sizeof(cmd), "%s \r\n", lcmd);
689 
690 	memset(&addr, 0, sizeof(addr));
691 	addr.sin_family = AF_INET;
692 	inet_aton("127.0.0.1", &addr.sin_addr);
693 	addr.sin_port = htons(port);
694 
695 	/* Make sure we do not get stuck indefinitely */
696 	alarm(150);
697 
698 	s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
699 	if (s < 0) {
700 		perror("socket");
701 		return -1;
702 	}
703 
704 	if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
705 		perror("connect");
706 		close(s);
707 		return -1;
708 	}
709 
710 	res = send(s, cmd, len, 0);
711 	if (res < 0) {
712 		perror("send");
713 		close(s);
714 		return -1;
715 	}
716 	if (res != len) {
717 		printf("Unexpected send result: %d (expected %d)\n",
718 		       (int) res, len);
719 		close(s);
720 		return -1;
721 	}
722 
723 	count = 0;
724 	pos = 0;
725 	len = 0;
726 	for (;;) {
727 		char *e;
728 		res = recv(s, resp + len, sizeof(resp) - len, 0);
729 		if (res < 0) {
730 			perror("recv");
731 			close(s);
732 			return -1;
733 		}
734 		if (res == 0) {
735 			printf("Could not read response\n");
736 			close(s);
737 			return -1;
738 		}
739 		len += res;
740 	next_line:
741 		e = memchr(resp + pos, '\r', len - pos);
742 		if (e == NULL)
743 			continue;
744 		*e++ = '\0';
745 		if (e - resp < len && *e == '\n')
746 			*e++ = '\n';
747 		printf("%s\n", resp + pos);
748 		if (strncasecmp(resp + pos, "status,RUNNING", 14) != 0)
749 			break;
750 		count++;
751 		if (count == 2)
752 			break;
753 		pos = e - resp;
754 		goto next_line;
755 	}
756 
757 	close(s);
758 
759 	return 0;
760 }
761 
762 
determine_sigma_p2p_ifname(struct sigma_dut * dut)763 static void determine_sigma_p2p_ifname(struct sigma_dut *dut)
764 {
765 	char buf[256];
766 	struct wpa_ctrl *ctrl;
767 
768 	if (dut->p2p_ifname)
769 		return;
770 
771 	snprintf(buf, sizeof(buf), "p2p-dev-%s", get_station_ifname(dut));
772 	ctrl = open_wpa_mon(buf);
773 	if (ctrl) {
774 		wpa_ctrl_detach(ctrl);
775 		wpa_ctrl_close(ctrl);
776 		dut->p2p_ifname_buf = strdup(buf);
777 		dut->p2p_ifname = dut->p2p_ifname_buf;
778 		sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
779 				"Using interface %s for P2P operations instead of interface %s",
780 				dut->p2p_ifname ? dut->p2p_ifname : "NULL",
781 				get_station_ifname(dut));
782 	} else {
783 		dut->p2p_ifname = get_station_ifname(dut);
784 	}
785 }
786 
787 
get_nl80211_config_enable_option(struct sigma_dut * dut)788 static int get_nl80211_config_enable_option(struct sigma_dut *dut)
789 {
790 	char cmd[100], result[5];
791 	FILE *f;
792 	size_t len;
793 	int ap_nl80211_enable;
794 
795 	snprintf(cmd, sizeof(cmd), "uci get qcacfg80211.config.enable");
796 	f = popen(cmd, "r");
797 	if (!f)
798 		return -1;
799 
800 	len = fread(result, 1, sizeof(result) - 1, f);
801 	pclose(f);
802 
803 	if (len == 0)
804 		return -1;
805 
806 	result[len] = '\0';
807 	ap_nl80211_enable = atoi(result);
808 
809 	if (ap_nl80211_enable)
810 		dut->priv_cmd = "cfg80211tool";
811 
812 	return 0;
813 }
814 
815 
set_defaults(struct sigma_dut * dut)816 static void set_defaults(struct sigma_dut *dut)
817 {
818 	dut->debug_level = DUT_MSG_INFO;
819 	dut->default_timeout = 120;
820 	dut->dialog_token = 0;
821 	dut->dpp_conf_id = -1;
822 	dut->dpp_local_bootstrap = -1;
823 	dut->sta_nss = 2; /* Make default nss 2 */
824 	dut->trans_proto = NAN_TRANSPORT_PROTOCOL_DEFAULT;
825 	dut->trans_port = NAN_TRANSPORT_PORT_DEFAULT;
826 	dut->nan_ipv6_len = 0;
827 	dut->ap_p2p_cross_connect = -1;
828 	dut->ap_chwidth = AP_AUTO;
829 	dut->default_11na_ap_chwidth = AP_AUTO;
830 	dut->default_11ng_ap_chwidth = AP_AUTO;
831 	/* by default, enable writing of traffic stream stats */
832 	dut->write_stats = 1;
833 	dut->priv_cmd = "iwpriv";
834 	dut->sigma_tmpdir = SIGMA_TMPDIR;
835 	dut->ap_ocvc = -1;
836 	dut->ap_sae_commit_status = -1;
837 }
838 
839 
deinit_sigma_dut(struct sigma_dut * dut)840 static void deinit_sigma_dut(struct sigma_dut *dut)
841 {
842 	free(dut->non_pref_ch_list);
843 	dut->non_pref_ch_list = NULL;
844 	free(dut->btm_query_cand_list);
845 	dut->btm_query_cand_list = NULL;
846 	free(dut->rsne_override);
847 	dut->rsne_override = NULL;
848 	free(dut->rsnxe_override_eapol);
849 	dut->rsnxe_override_eapol = NULL;
850 	free(dut->ap_sae_groups);
851 	dut->ap_sae_groups = NULL;
852 	free(dut->dpp_peer_uri);
853 	dut->dpp_peer_uri = NULL;
854 	free(dut->ap_sae_passwords);
855 	dut->ap_sae_passwords = NULL;
856 	free(dut->ap_sae_pk_modifier);
857 	dut->ap_sae_pk_modifier = NULL;
858 	free(dut->ap_sae_pk_keypair);
859 	dut->ap_sae_pk_keypair = NULL;
860 	free(dut->ap_sae_pk_keypair_sig);
861 	dut->ap_sae_pk_keypair_sig = NULL;
862 	free(dut->ar_ltf);
863 	dut->ar_ltf = NULL;
864 	free(dut->ap_dpp_conf_addr);
865 	dut->ap_dpp_conf_addr = NULL;
866 	free(dut->ap_dpp_conf_pkhash);
867 	dut->ap_dpp_conf_pkhash = NULL;
868 	if (dut->log_file_fd) {
869 		fclose(dut->log_file_fd);
870 		dut->log_file_fd = NULL;
871 	}
872 	free(dut->p2p_ifname_buf);
873 	dut->p2p_ifname_buf = NULL;
874 	free(dut->main_ifname_2g);
875 	dut->main_ifname_2g = NULL;
876 	free(dut->main_ifname_5g);
877 	dut->main_ifname_5g = NULL;
878 	free(dut->station_ifname_2g);
879 	dut->station_ifname_2g = NULL;
880 	free(dut->station_ifname_5g);
881 	dut->station_ifname_5g = NULL;
882 }
883 
884 
set_main_ifname(struct sigma_dut * dut,const char * val)885 static void set_main_ifname(struct sigma_dut *dut, const char *val)
886 {
887 	const char *pos;
888 
889 	dut->main_ifname = optarg;
890 	pos = strchr(val, '/');
891 	if (!pos)
892 		return;
893 	free(dut->main_ifname_2g);
894 	dut->main_ifname_2g = malloc(pos - val + 1);
895 	if (dut->main_ifname_2g) {
896 		memcpy(dut->main_ifname_2g, val, pos - val);
897 		dut->main_ifname_2g[pos - val] = '\0';
898 	}
899 	free(dut->main_ifname_5g);
900 	dut->main_ifname_5g = strdup(pos + 1);
901 }
902 
903 
set_station_ifname(struct sigma_dut * dut,const char * val)904 static void set_station_ifname(struct sigma_dut *dut, const char *val)
905 {
906 	const char *pos;
907 
908 	dut->station_ifname = optarg;
909 	pos = strchr(val, '/');
910 	if (!pos)
911 		return;
912 	free(dut->station_ifname_2g);
913 	dut->station_ifname_2g = malloc(pos - val + 1);
914 	if (dut->station_ifname_2g) {
915 		memcpy(dut->station_ifname_2g, val, pos - val);
916 		dut->station_ifname_2g[pos - val] = '\0';
917 	}
918 	free(dut->station_ifname_5g);
919 	dut->station_ifname_5g = strdup(pos + 1);
920 }
921 
922 
923 static const char * const license1 =
924 "sigma_dut - WFA Sigma DUT/CA\n"
925 "----------------------------\n"
926 "\n"
927 "Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
928 "Copyright (c) 2011-2017, Qualcomm Atheros, Inc.\n"
929 "Copyright (c) 2018-2019, The Linux Foundation\n"
930 "All Rights Reserved.\n"
931 "Licensed under the Clear BSD license.\n"
932 "\n";
933 static const char * const license2 =
934 "Redistribution and use in source and binary forms, with or without\n"
935 "modification, are permitted (subject to the limitations in the\n"
936 "disclaimer below) provided that the following conditions are met:\n"
937 "\n";
938 static const char * const license3 =
939 "* Redistributions of source code must retain the above copyright notice,\n"
940 "  this list of conditions and the following disclaimer.\n"
941 "\n"
942 "* Redistributions in binary form must reproduce the above copyright\n"
943 "  notice, this list of conditions and the following disclaimer in the\n"
944 "  documentation and/or other materials provided with the distribution.\n"
945 "\n"
946 "* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
947 "  contributors may be used to endorse or promote products derived from\n"
948 "  this software without specific prior written permission.\n"
949 "\n";
950 static const char * const license4 =
951 "NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
952 "BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
953 "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
954 "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
955 "FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
956 "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
957 "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
958 "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
959 "USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
960 "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
961 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
962 "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
963 
964 
print_license(void)965 static void print_license(void)
966 {
967 	printf("%s%s%s%s\n",
968 	       license1, license2, license3, license4);
969 }
970 
971 
usage(void)972 static void usage(void)
973 {
974 	printf("usage: sigma_dut [-aABdfGqDIntuVW234] [-p<port>] "
975 	       "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
976 	       "       [-M<main ifname>] [-R<radio ifname>] "
977 	       "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
978 	       "       [-T<throughput pktsize>] \\\n"
979 	       "       [-w<wpa_supplicant/hostapd ctrl_iface dir>] \\\n"
980 	       "       [-H <hostapd log file>] \\\n"
981 	       "       [-F <hostapd binary path>] \\\n"
982 	       "       [-j <hostapd ifname>] \\\n"
983 	       "       [-J <wpa_supplicant debug log>] \\\n"
984 	       "       [-C <certificate path>] \\\n"
985 	       "       [-v <version string>] \\\n"
986 	       "       [-L <summary log>] \\\n"
987 	       "       [-c <wifi chip type: WCN or ATHEROS or "
988 	       "AR6003 or MAC80211 or QNXNTO or OPENWRT or LINUX-WCN>] \\\n"
989 	       "       [-i <IP address of the AP>] \\\n"
990 	       "       [-k <subnet mask for the AP>] \\\n"
991 	       "       [-K <sigma_dut log file directory>] \\\n"
992 	       "       [-e <hostapd entropy file>] \\\n"
993 	       "       [-N <device_get_info vendor>] \\\n"
994 	       "       [-o <device_get_info model>] \\\n"
995 	       "       [-O <device_get_info version>] \\\n"
996 #ifdef MIRACAST
997 	       "       [-x <sink|source>] \\\n"
998 	       "       [-y <Miracast library path>] \\\n"
999 #endif /* MIRACAST */
1000 	       "       [-z <client socket directory path \\\n"
1001 	       "       Ex: </data/vendor/wifi/sockets>] \\\n"
1002 	       "       [-Z <Override default tmp dir path>] \\\n"
1003 	       "       [-5 <WFD timeout override>] \\\n"
1004 	       "       [-r <HT40 or 2.4_HT40>]\n");
1005 	printf("local command: sigma_dut [-p<port>] <-l<cmd>>\n");
1006 }
1007 
1008 
main(int argc,char * argv[])1009 int main(int argc, char *argv[])
1010 {
1011 	int c;
1012 	int daemonize = 0;
1013 	int port = SIGMA_DUT_PORT;
1014 	char *local_cmd = NULL;
1015 	int internal_dhcp_enabled = 0;
1016 #ifdef __QNXNTO__
1017 	char *env_str = NULL;
1018 	char buf[20];
1019 	char *sigma_ctrl_sock = NULL; /* env used for QNX */
1020 #endif /* __QNXNTO__ */
1021 
1022 	memset(&sigma_dut, 0, sizeof(sigma_dut));
1023 	set_defaults(&sigma_dut);
1024 
1025 	for (;;) {
1026 		c = getopt(argc, argv,
1027 			   "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:");
1028 		if (c < 0)
1029 			break;
1030 		switch (c) {
1031 		case 'a':
1032 			sigma_dut.ap_anqpserver = 1;
1033 			break;
1034 		case 'b':
1035 			sigma_dut.bridge = optarg;
1036 			break;
1037 		case 'B':
1038 			daemonize++;
1039 			break;
1040 		case 'C':
1041 			sigma_cert_path = optarg;
1042 			break;
1043 		case 'd':
1044 			if (sigma_dut.debug_level > 0)
1045 				sigma_dut.debug_level--;
1046 			break;
1047 #ifdef __QNXNTO__
1048 		case 'E':
1049 			sigma_ctrl_sock = optarg;
1050 			break;
1051 #endif /* __QNXNTO__ */
1052 		case 'D':
1053 			sigma_dut.stdout_debug = 1;
1054 			break;
1055 		case 'e':
1056 			sigma_dut.hostapd_entropy_log = optarg;
1057 			break;
1058 		case 'f':
1059 			/* Disable writing stats */
1060 			sigma_dut.write_stats = 0;
1061 			break;
1062 		case 'F':
1063 			sigma_dut.hostapd_bin = optarg;
1064 			break;
1065 		case 'g':
1066 			/* Enable internal processing of P2P group formation
1067 			 * events to start/stop DHCP server/client. */
1068 			internal_dhcp_enabled = 1;
1069 			break;
1070 		case 'G':
1071 			sigma_dut.use_hostapd_pid_file = 1;
1072 			break;
1073 		case 'H':
1074 			sigma_dut.hostapd_debug_log = optarg;
1075 			break;
1076 		case 'I':
1077 			print_license();
1078 			exit(0);
1079 			break;
1080 		case 'j':
1081 			sigma_dut.hostapd_ifname = optarg;
1082 			break;
1083 		case 'J':
1084 			sigma_dut.wpa_supplicant_debug_log = optarg;
1085 			break;
1086 		case 'l':
1087 			local_cmd = optarg;
1088 			break;
1089 		case 'L':
1090 			sigma_dut.summary_log = optarg;
1091 			break;
1092 		case 'p':
1093 			port = atoi(optarg);
1094 			break;
1095 		case 'P':
1096 			sigma_dut.p2p_ifname = optarg;
1097 			break;
1098 		case 'q':
1099 			sigma_dut.debug_level++;
1100 			break;
1101 		case 'r':
1102 			if (strcmp(optarg, "HT40") == 0) {
1103 				sigma_dut.default_11na_ap_chwidth = AP_40;
1104 			} else if (strcmp(optarg, "2.4_HT40") == 0) {
1105 				sigma_dut.default_11ng_ap_chwidth = AP_40;
1106 			} else {
1107 				printf("Unsupported -r value\n");
1108 				exit(1);
1109 			}
1110 			break;
1111 		case 'R': {
1112 			static int num_radio = 0;
1113 			static char **radio_ptr = sigma_radio_ifname;
1114 
1115 			num_radio++;
1116 			if (num_radio > MAX_RADIO) {
1117 				printf("Multiple radio support limit (%d) exceeded\n",
1118 				       MAX_RADIO);
1119 				exit(1);
1120 			}
1121 			*radio_ptr++ = optarg;
1122 			break;
1123 		}
1124 		case 's':
1125 			sigma_dut.sniffer_ifname = optarg;
1126 			break;
1127 		case 't':
1128 			sigma_dut.no_timestamps = 1;
1129 			break;
1130 		case 'T':
1131 			sigma_dut.throughput_pktsize = atoi(optarg);
1132 			if (sigma_dut.throughput_pktsize == 0) {
1133 				printf("Invalid -T value\n");
1134 				exit(0);
1135 			}
1136 			break;
1137 		case 'm':
1138 			sigma_dut.set_macaddr = optarg;
1139 			break;
1140 		case 'M':
1141 			set_main_ifname(&sigma_dut, optarg);
1142 			break;
1143 		case 'n':
1144 			sigma_dut.no_ip_addr_set = 1;
1145 			break;
1146 		case 'N':
1147 			sigma_dut.vendor_name = optarg;
1148 			break;
1149 		case 'o':
1150 			sigma_dut.model_name = optarg;
1151 			break;
1152 		case 'O':
1153 			sigma_dut.version_name = optarg;
1154 			break;
1155 		case 'K':
1156 			sigma_dut.log_file_dir = optarg;
1157 			break;
1158 		case 'S':
1159 			set_station_ifname(&sigma_dut, optarg);
1160 			break;
1161 		case 'w':
1162 			sigma_hapd_ctrl = optarg;
1163 			sigma_wpas_ctrl = optarg;
1164 			break;
1165 		case 'i':
1166 			ap_inet_addr = optarg;
1167 			break;
1168 		case 'k':
1169 			ap_inet_mask = optarg;
1170 			break;
1171 		case 'c':
1172 			printf("%s", optarg);
1173 			if (set_wifi_chip(optarg) < 0)
1174 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1175 						"WRONG CHIP TYPE: SAP will "
1176 						"not load");
1177 			break;
1178 		case 'v':
1179 			sigma_dut.version = optarg;
1180 			break;
1181 		case 'V':
1182 			printf("sigma_dut " SIGMA_DUT_VER "\n");
1183 			exit(0);
1184 			break;
1185 		case 'W':
1186 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1187 					"Running WMM-AC test suite");
1188 			sigma_wmm_ac = 1;
1189 			break;
1190 		case 'u':
1191 		       sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1192 				       "Use iface down/up in reset cmd");
1193 		       sigma_dut.iface_down_on_reset = 1;
1194 		       break;
1195 		case 'A':
1196 			sigma_dut.sim_no_username = 1;
1197 			break;
1198 #ifdef MIRACAST
1199 		case 'x':
1200 			if (strcmp(optarg, "sink") == 0) {
1201 				sigma_dut.wfd_device_type = 1;
1202 				sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1203 						"Device Type is SINK");
1204 			} else if (strcmp(optarg, "source") == 0) {
1205 				sigma_dut.wfd_device_type = 0;
1206 				sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1207 						"Device Type is SOURCE");
1208 			}
1209 			break;
1210 		case 'y':
1211 			sigma_dut.miracast_lib_path = optarg;
1212 			break;
1213 #endif /* MIRACAST */
1214 		case 'z':
1215 			client_socket_path = optarg;
1216 			break;
1217 		case 'Z':
1218 			sigma_dut.sigma_tmpdir = optarg;
1219 			break;
1220 		case '2':
1221 			sigma_dut.sae_h2e_default = 1;
1222 			break;
1223 		case '3':
1224 			sigma_dut.owe_ptk_workaround = 1;
1225 			break;
1226 		case '4':
1227 			sigma_dut.client_privacy_default = 1;
1228 			break;
1229 		case '5': {
1230 			int timeout;
1231 
1232 			errno = 0;
1233 			timeout = strtol(optarg, NULL, 10);
1234 			if (errno || timeout < 0) {
1235 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1236 					       "failed to set default_timeout");
1237 				return -1;
1238 			}
1239 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1240 					"default timeout set to %d", timeout);
1241 			sigma_dut.user_config_timeout = timeout;
1242 			break;
1243 		}
1244 		case 'h':
1245 		default:
1246 			usage();
1247 			exit(0);
1248 			break;
1249 		}
1250 	}
1251 
1252 	determine_sigma_p2p_ifname(&sigma_dut);
1253 #ifdef MIRACAST
1254 	miracast_init(&sigma_dut);
1255 #endif /* MIRACAST */
1256 	if (local_cmd)
1257 		return run_local_cmd(port, local_cmd);
1258 
1259 	if ((wifi_chip_type == DRIVER_QNXNTO ||
1260 	     wifi_chip_type == DRIVER_LINUX_WCN) &&
1261 	    (!sigma_dut.main_ifname || !sigma_dut.station_ifname)) {
1262 		sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1263 				"Interface should be provided for QNX/LINUX-WCN driver - check option M and S");
1264 	}
1265 
1266 	if (get_openwrt_driver_type() == OPENWRT_DRIVER_ATHEROS)
1267 		get_nl80211_config_enable_option(&sigma_dut);
1268 
1269 	sigma_dut_get_device_driver_name(get_main_ifname(&sigma_dut),
1270 					 sigma_dut.device_driver,
1271 					 sizeof(sigma_dut.device_driver));
1272 	if (sigma_dut.device_driver[0])
1273 		sigma_dut_print(&sigma_dut, DUT_MSG_DEBUG, "device driver: %s",
1274 				sigma_dut.device_driver);
1275 
1276 #ifdef NL80211_SUPPORT
1277 	sigma_dut.nl_ctx = nl80211_init(&sigma_dut);
1278 #endif /* NL80211_SUPPORT */
1279 	sigma_dut_register_cmds();
1280 
1281 #ifdef __QNXNTO__
1282 	/* Try to open socket in other env dev */
1283 	if (sigma_ctrl_sock) {
1284 		env_str = getenv("SOCK");
1285 		if (env_str) {
1286 			sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1287 					"SOCK=%s", env_str);
1288 		}
1289 		snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
1290 		if (putenv(buf) != 0) {
1291 			sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1292 					"putenv() failed setting SOCK");
1293 			return EXIT_FAILURE;
1294 		}
1295 	}
1296 #endif /* __QNXNTO__ */
1297 
1298 	if (open_socket(&sigma_dut, port) < 0)
1299 		return -1;
1300 
1301 #ifdef __QNXNTO__
1302 	/* restore back the SOCK */
1303 	if (sigma_ctrl_sock) {
1304 		if (env_str) {
1305 			snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
1306 			if (putenv(buf) != 0) {
1307 				sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1308 						"putenv() failed setting SOCK");
1309 				return EXIT_FAILURE;
1310 			}
1311 		} else {
1312 			/* unset the env for sock */
1313 			unsetenv("SOCK");
1314 		}
1315 	}
1316 #endif /* __QNXNTO__ */
1317 
1318 	if (daemonize) {
1319 		if (daemon(0, 0) < 0) {
1320 			perror("daemon");
1321 			exit(-1);
1322 		}
1323 	} else {
1324 #ifdef __linux__
1325 		setlinebuf(stdout);
1326 #endif /* __linux__ */
1327 	}
1328 
1329 	if (internal_dhcp_enabled)
1330 		p2p_create_event_thread(&sigma_dut);
1331 
1332 	run_loop(&sigma_dut);
1333 
1334 #ifdef CONFIG_SNIFFER
1335 	sniffer_close(&sigma_dut);
1336 #endif /* CONFIG_SNIFFER */
1337 
1338 	close_socket(&sigma_dut);
1339 #ifdef MIRACAST
1340 	miracast_deinit(&sigma_dut);
1341 #endif /* MIRACAST */
1342 	deinit_sigma_dut(&sigma_dut);
1343 #ifdef NL80211_SUPPORT
1344 	nl80211_deinit(&sigma_dut, sigma_dut.nl_ctx);
1345 #endif /* NL80211_SUPPORT */
1346 	sigma_dut_unreg_cmds(&sigma_dut);
1347 #ifdef ANDROID
1348 	hlp_thread_cleanup(&sigma_dut);
1349 #endif /* ANDROID */
1350 
1351 	return 0;
1352 }
1353