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