blob: 1759e8477288e2c87c7b536057fd41c4bcae541e [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (station/AP)
3 * Copyright (c) 2010-2011, Atheros Communications, Inc.
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004 * Copyright (c) 2011-2017, Qualcomm Atheros, Inc.
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005 * All Rights Reserved.
6 * Licensed under the Clear BSD license. See README for more details.
7 */
8
9#include "sigma_dut.h"
10#ifdef __linux__
11#include <signal.h>
12#include <netinet/tcp.h>
13#endif /* __linux__ */
Danny Segalf2af39b2016-04-10 16:23:11 +030014#include "wpa_ctrl.h"
Jouni Malinencd4e3c32015-10-29 12:39:56 +020015#include "wpa_helpers.h"
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -070016#include "miracast.h"
Jouni Malinencd4e3c32015-10-29 12:39:56 +020017
18#define SIGMA_DUT_PORT 9000
19#define MAX_CONNECTIONS 4
20
21extern enum driver_type wifi_chip_type;
22
23static struct sigma_dut sigma_dut;
24
25char *sigma_main_ifname = NULL;
26char *sigma_radio_ifname[MAX_RADIO] = {};
27char *sigma_station_ifname = NULL;
Danny Segalf2af39b2016-04-10 16:23:11 +030028char *sigma_p2p_ifname = NULL;
29static char *sigma_p2p_ifname_buf = NULL;
Jouni Malinencd4e3c32015-10-29 12:39:56 +020030char *sigma_wpas_ctrl = "/var/run/wpa_supplicant/";
31char *sigma_hapd_ctrl = NULL;
32char *ap_inet_addr = "192.168.43.1";
33char *ap_inet_mask = "255.255.255.0";
34char *sigma_cert_path = "/etc/wpa_supplicant";
35
36/* For WMM-AC testing this set to 1 through argument,
37 * otherwise default WMM-PS 0 */
38int sigma_wmm_ac = 0;
39
40
41#ifdef ANDROID
42#include <android/log.h>
43
44static enum android_LogPriority level_to_android_priority(int level)
45{
46 switch (level) {
47 case DUT_MSG_ERROR:
48 return ANDROID_LOG_ERROR;
49 case DUT_MSG_INFO:
50 return ANDROID_LOG_INFO;
51 case DUT_MSG_DEBUG:
52 return ANDROID_LOG_DEBUG;
53 default:
54 return ANDROID_LOG_VERBOSE;
55 }
56}
57#endif /* ANDROID */
58
59
60void sigma_dut_print(struct sigma_dut *dut, int level, const char *fmt, ...)
61{
62 va_list ap;
63 struct timeval tv;
64
65 if (level < dut->debug_level)
66 return;
67
68#ifdef ANDROID
69 va_start(ap, fmt);
70 __android_log_vprint(level_to_android_priority(level),
71 "sigma_dut", fmt, ap);
72 va_end(ap);
73 if (!dut->stdout_debug)
74 return;
75#endif /* ANDROID */
76
77 va_start(ap, fmt);
78 gettimeofday(&tv, NULL);
79 printf("%ld.%06u: ", (long) tv.tv_sec,
80 (unsigned int) tv.tv_usec);
81 vprintf(fmt, ap);
82 printf("\n");
83 va_end(ap);
84}
85
86
87void sigma_dut_summary(struct sigma_dut *dut, const char *fmt, ...)
88{
89 va_list ap;
90 FILE *f;
91
92 if (!dut->summary_log)
93 return;
94
95 f = fopen(dut->summary_log, "a");
96 if (f == NULL)
97 return;
98
99 va_start(ap, fmt);
100 vfprintf(f, fmt, ap);
101 fprintf(f, "\n");
102 va_end(ap);
103 fclose(f);
104}
105
106
107int sigma_dut_reg_cmd(const char *cmd,
108 int (*validate)(struct sigma_cmd *cmd),
109 int (*process)(struct sigma_dut *dut,
110 struct sigma_conn *conn,
111 struct sigma_cmd *cmd))
112{
113 struct sigma_cmd_handler *h;
114 size_t clen, len;
115
116 clen = strlen(cmd);
117 len = sizeof(*h) + clen + 1;
118 h = malloc(len);
119 if (h == NULL)
120 return -1;
121 memset(h, 0, len);
122 h->cmd = (char *) (h + 1); /* include in same allocation */
123 memcpy(h->cmd, cmd, clen);
124 h->validate = validate;
125 h->process= process;
126
127 h->next = sigma_dut.cmds;
128 sigma_dut.cmds = h;
129
130 return 0;
131}
132
133
134static void sigma_dut_unreg_cmds(struct sigma_dut *dut)
135{
136 struct sigma_cmd_handler *cmd, *prev;
137 cmd = dut->cmds;
138 dut->cmds = NULL;
139 while (cmd) {
140 prev = cmd;
141 cmd = cmd->next;
142 free(prev);
143 }
144}
145
146
147static int open_socket(struct sigma_dut *dut, int port)
148{
149 struct sockaddr_in addr;
150#ifndef __QNXNTO__
151 int val;
152#endif /* !__QNXNTO__ */
153
154#ifdef __QNXNTO__
155 dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
156#else /* __QNXNTO__ */
157 dut->s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
158#endif /* __QNXNTO__ */
159 if (dut->s < 0) {
160 sigma_dut_print(dut, DUT_MSG_ERROR, "socket: %s",
161 strerror(errno));
162 return -1;
163 }
164
165#ifndef __QNXNTO__
166 val = 1;
167 if (setsockopt(dut->s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) <
168 0)
169 sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt SO_REUSEADDR: "
170 "%s", strerror(errno));
171#endif /* !__QNXNTO__ */
172
173#ifdef __linux__
174 val = 1;
175 if (setsockopt(dut->s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) <
176 0)
177 sigma_dut_print(dut, DUT_MSG_INFO, "setsockopt TCP_NODELAY: "
178 "%s", strerror(errno));
179#endif /* __linux__ */
180
181 memset(&addr, 0, sizeof(addr));
182 addr.sin_family = AF_INET;
183 addr.sin_port = htons(port);
184
185 if (bind(dut->s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
186 sigma_dut_print(dut, DUT_MSG_ERROR, "bind: %s",
187 strerror(errno));
188 goto fail;
189 }
190
191 if (listen(dut->s, 5) < 0) {
192 sigma_dut_print(dut, DUT_MSG_ERROR, "listen: %s",
193 strerror(errno));
194 goto fail;
195 }
196
197 return 0;
198
199fail:
200 shutdown(dut->s, SHUT_RDWR);
201 close(dut->s);
202 dut->s = -1;
203 return -1;
204}
205
206
207static void close_socket(struct sigma_dut *dut)
208{
209 shutdown(dut->s, SHUT_RDWR);
210 close(dut->s);
211 dut->s = -1;
212}
213
214
215void send_resp(struct sigma_dut *dut, struct sigma_conn *conn,
Jouni Malinen76401f52017-03-18 01:04:55 +0200216 enum sigma_status status, const char *buf)
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200217{
218 struct msghdr msg;
219 struct iovec iov[4];
220 size_t elems;
221
Jouni Malinena326d7b2017-09-04 13:46:02 +0300222 if (!conn)
223 return;
224
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200225 sigma_dut_print(dut, DUT_MSG_INFO, "resp: status=%d buf=%s",
226 status, buf ? buf : "N/A");
227
228 iov[0].iov_base = "status,";
229 iov[0].iov_len = 7;
230 switch (status) {
231 case SIGMA_RUNNING:
232 iov[1].iov_base = "RUNNING,";
233 iov[1].iov_len = 8;
234 break;
235 case SIGMA_INVALID:
236 iov[1].iov_base = "INVALID,";
237 iov[1].iov_len = 8;
238 break;
239 case SIGMA_ERROR:
240 iov[1].iov_base = "ERROR,";
241 iov[1].iov_len = 6;
242 break;
243 case SIGMA_COMPLETE:
244 iov[1].iov_base = "COMPLETE,";
245 iov[1].iov_len = 9;
246 break;
247 }
248 if (status != SIGMA_RUNNING) {
249 sigma_dut_summary(dut, "CAPI resp: status,%s%s",
250 (char *) iov[1].iov_base, buf ? buf : "");
251 }
252 if (buf) {
Jouni Malinen76401f52017-03-18 01:04:55 +0200253 iov[2].iov_base = (void *) buf;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200254 iov[2].iov_len = strlen(buf);
255 iov[3].iov_base = "\r\n";
256 iov[3].iov_len = 2;
257 elems = 4;
258 } else {
259 iov[1].iov_len--;
260 iov[2].iov_base = "\r\n";
261 iov[2].iov_len = 2;
262 elems = 3;
263 }
264
265 memset(&msg, 0, sizeof(msg));
266 msg.msg_iov = iov;
267 msg.msg_iovlen = elems;
268 if (sendmsg(conn->s, &msg, 0) < 0)
269 sigma_dut_print(dut, DUT_MSG_INFO, "sendmsg: %s",
270 strerror(errno));
271}
272
273
274const char * get_param(struct sigma_cmd *cmd, const char *name)
275{
276 int i;
277 for (i = 0; i < cmd->count; i++) {
278 if (strcasecmp(name, cmd->params[i]) == 0)
279 return cmd->values[i];
280 }
281 return NULL;
282}
283
284
285static void process_cmd(struct sigma_dut *dut, struct sigma_conn *conn,
286 char *buf)
287{
288 struct sigma_cmd_handler *h;
289 struct sigma_cmd c;
290 char *cmd, *pos, *pos2;
291 int len;
292 char txt[200];
293 int res;
294
295 while (*buf == '\r' || *buf == '\n' || *buf == '\t' || *buf == ' ')
296 buf++;
297 len = strlen(buf);
298 while (len > 0 && buf[len - 1] == ' ') {
299 buf[len - 1] = '\0';
300 len--;
301 }
302
303 if (dut->debug_level < DUT_MSG_INFO) {
304 pos = strchr(buf, ',');
305 if (pos == NULL)
306 pos = buf + len;
307 if (pos - buf > 50)
308 pos = buf + 50;
309 memcpy(txt, "/====[ ", 7);
310 pos2 = txt + 7;
311 memcpy(pos2, buf, pos - buf);
312 pos2 += pos - buf;
313 *pos2++ = ' ';
314 *pos2++ = ']';
315 while (pos2 - txt < 70)
316 *pos2++ = '=';
317 *pos2++ = '\\';
318 *pos2 = '\0';
319 printf("\n%s\n\n", txt);
320 }
321
322 sigma_dut_print(dut, DUT_MSG_INFO, "cmd: %s", buf);
323 sigma_dut_summary(dut, "CAPI cmd: %s", buf);
324 snprintf(txt, sizeof(txt), "NOTE CAPI:%s", buf);
325 txt[sizeof(txt) - 1] = '\0';
326 wpa_command(get_main_ifname(), txt);
327
328 memset(&c, 0, sizeof(c));
329 cmd = buf;
330 pos = strchr(cmd, ',');
331 if (pos) {
332 *pos++ = '\0';
333 if (strcasecmp(cmd, "AccessPoint") == 0 ||
334 strcasecmp(cmd, "PowerSwitch") == 0) {
335 pos2 = strchr(pos, ',');
336 if (pos2 == NULL)
337 goto invalid_params;
338 c.params[c.count] = pos;
339 c.values[c.count] = pos2;
340 c.count++;
341 pos = strchr(pos2, ',');
342 if (pos)
343 *pos++ = '\0';
344 }
345 while (pos) {
346 pos2 = strchr(pos, ',');
347 if (pos2 == NULL)
348 goto invalid_params;
349 *pos2++ = '\0';
350 if (c.count == MAX_PARAMS) {
351 sigma_dut_print(dut, DUT_MSG_INFO, "Too many "
352 "parameters");
353 goto invalid_params;
354 }
355 c.params[c.count] = pos;
356 c.values[c.count] = pos2;
357 c.count++;
358 pos = strchr(pos2, ',');
359 if (pos)
360 *pos++ = '\0';
361 }
362 }
363 h = dut->cmds;
364 while (h) {
365 if (strcasecmp(cmd, h->cmd) == 0)
366 break;
367 h = h->next;
368 }
369
370 if (h == NULL) {
371 sigma_dut_print(dut, DUT_MSG_INFO, "Unknown command: '%s'",
372 cmd);
373 send_resp(dut, conn, SIGMA_INVALID,
374 "errorCode,Unknown command");
375 goto out;
376 }
377
378 if (h->validate && h->validate(&c) < 0) {
379 invalid_params:
380 sigma_dut_print(dut, DUT_MSG_INFO, "Invalid parameters");
381 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid "
382 "parameters");
383 goto out;
384 }
385
386 send_resp(dut, conn, SIGMA_RUNNING, NULL);
387 sigma_dut_print(dut, DUT_MSG_INFO, "Run command: %s", cmd);
388 res = h->process(dut, conn, &c);
389 if (res == -2)
390 send_resp(dut, conn, SIGMA_ERROR, NULL);
391 else if (res == -1)
392 send_resp(dut, conn, SIGMA_INVALID, NULL);
393 else if (res == 1)
394 send_resp(dut, conn, SIGMA_COMPLETE, NULL);
395
396out:
397 if (dut->debug_level < DUT_MSG_INFO) {
398 pos2 = txt;
399 *pos2++ = '\\';
400 memset(pos2, '-', 69);
401 pos2 += 69;
402 *pos2++ = '/';
403 *pos2 = '\0';
404 printf("\n%s\n\n", txt);
405 }
406}
407
408
409static void process_conn(struct sigma_dut *dut, struct sigma_conn *conn)
410{
411 ssize_t res;
412 int i;
413
414 sigma_dut_print(dut, DUT_MSG_DEBUG, "Read from %s:%d",
415 inet_ntoa(conn->addr.sin_addr),
416 ntohs(conn->addr.sin_port));
417
418 res = recv(conn->s, conn->buf + conn->pos, MAX_CMD_LEN + 5 - conn->pos,
419 0);
420 if (res < 0) {
421 sigma_dut_print(dut, DUT_MSG_INFO, "recv: %s",
422 strerror(errno));
423 }
424 if (res <= 0) {
425 sigma_dut_print(dut, DUT_MSG_DEBUG, "Close connection from "
426 "%s:%d",
427 inet_ntoa(conn->addr.sin_addr),
428 ntohs(conn->addr.sin_port));
429 shutdown(conn->s, SHUT_RDWR);
430 close(conn->s);
431 conn->s = -1;
432 return;
433 }
434
435 sigma_dut_print(dut, DUT_MSG_DEBUG, "Received %d bytes",
436 (int) res);
437
438 for (;;) {
439 for (i = conn->pos; i < conn->pos + res; i++) {
440 if (conn->buf[i] == '\r' || conn->buf[i] == '\n')
441 break;
442 }
443
444 if (i == conn->pos + res) {
445 /* Full command not yet received */
446 conn->pos += res;
447 if (conn->pos >= MAX_CMD_LEN + 5) {
448 sigma_dut_print(dut, DUT_MSG_INFO, "Too long "
449 "command dropped");
450 conn->pos = 0;
451 }
452 break;
453 }
454
455 /* Full command received */
456 conn->buf[i++] = '\0';
457 process_cmd(dut, conn, conn->buf);
458 while (i < conn->pos + res &&
459 (conn->buf[i] == '\r' || conn->buf[i] == '\n'))
460 i++;
461 memmove(conn->buf, &conn->buf[i], conn->pos + res - i);
462 res = conn->pos + res - i;
463 conn->pos = 0;
464 }
465}
466
467
468static int stop_loop = 0;
469
470#ifdef __linux__
471static void handle_term(int sig)
472{
473 stop_loop = 1;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530474 stop_event_thread();
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200475 printf("sigma_dut terminating\n");
476}
477#endif /* __linux__ */
478
479static void run_loop(struct sigma_dut *dut)
480{
481 struct sigma_conn conn[MAX_CONNECTIONS];
482 int i, res, maxfd, can_accept;
483 fd_set rfds;
484
485 memset(&conn, 0, sizeof(conn));
486 for (i = 0; i < MAX_CONNECTIONS; i++)
487 conn[i].s = -1;
488
489#ifdef __linux__
490 signal(SIGINT, handle_term);
491 signal(SIGTERM, handle_term);
492 signal(SIGPIPE, SIG_IGN);
493#endif /* __linux__ */
494
495 while (!stop_loop) {
496 FD_ZERO(&rfds);
497 maxfd = -1;
498 can_accept = 0;
499 for (i = 0; i < MAX_CONNECTIONS; i++) {
500 if (conn[i].s >= 0) {
501 FD_SET(conn[i].s, &rfds);
502 if (conn[i].s > maxfd)
503 maxfd = conn[i].s;
504 } else if (!conn[i].waiting_completion)
505 can_accept = 1;
506 }
507
508 if (can_accept) {
509 FD_SET(dut->s, &rfds);
510 if (dut->s > maxfd)
511 maxfd = dut->s;
512 }
513
514
515 sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for next "
516 "command (can_accept=%d)", can_accept);
517 res = select(maxfd + 1, &rfds, NULL, NULL, NULL);
518 if (res < 0) {
519 perror("select");
520 if (!stop_loop)
521 sleep(1);
522 continue;
523 }
524
525 if (!res) {
526 sigma_dut_print(dut, DUT_MSG_DEBUG, "Nothing ready");
527 sleep(1);
528 continue;
529 }
530
531 if (FD_ISSET(dut->s, &rfds)) {
532 for (i = 0; i < MAX_CONNECTIONS; i++) {
533 if (conn[i].s < 0 &&
534 !conn[i].waiting_completion)
535 break;
536 }
537 if (i == MAX_CONNECTIONS) {
538 /*
539 * This cannot really happen since can_accept
540 * would not be set to one.
541 */
542 sigma_dut_print(dut, DUT_MSG_DEBUG,
543 "No room for new connection");
544 continue;
545 }
546 conn[i].addrlen = sizeof(conn[i].addr);
547 conn[i].s = accept(dut->s,
548 (struct sockaddr *) &conn[i].addr,
549 &conn[i].addrlen);
550 if (conn[i].s < 0) {
551 sigma_dut_print(dut, DUT_MSG_INFO,
552 "accept: %s",
553 strerror(errno));
554 continue;
555 }
556
557 sigma_dut_print(dut, DUT_MSG_DEBUG,
558 "Connection %d from %s:%d", i,
559 inet_ntoa(conn[i].addr.sin_addr),
560 ntohs(conn[i].addr.sin_port));
561 conn[i].pos = 0;
562 }
563
564 for (i = 0; i < MAX_CONNECTIONS; i++) {
565 if (conn[i].s < 0)
566 continue;
567 if (FD_ISSET(conn[i].s, &rfds))
568 process_conn(dut, &conn[i]);
569 }
570 }
571}
572
573
574static int run_local_cmd(int port, char *lcmd)
575{
576 int s, len;
577 struct sockaddr_in addr;
578 char cmd[MAX_CMD_LEN];
579 ssize_t res;
580 int count;
581 char resp[MAX_CMD_LEN];
582 int pos;
583
584
585 if (strlen(lcmd) > sizeof(cmd) - 4) {
586 printf("Too long command\n");
587 return -1;
588 }
589 len = snprintf(cmd, sizeof(cmd), "%s \r\n", lcmd);
590
591 memset(&addr, 0, sizeof(addr));
592 addr.sin_family = AF_INET;
593 inet_aton("127.0.0.1", &addr.sin_addr);
594 addr.sin_port = htons(port);
595
596 /* Make sure we do not get stuck indefinitely */
597 alarm(150);
598
599 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
600 if (s < 0) {
601 perror("socket");
602 return -1;
603 }
604
605 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
606 perror("connect");
607 close(s);
608 return -1;
609 }
610
611 res = send(s, cmd, len, 0);
612 if (res < 0) {
613 perror("send");
614 close(s);
615 return -1;
616 }
617 if (res != len) {
618 printf("Unexpected send result: %d (expected %d)\n",
619 (int) res, len);
620 close(s);
621 return -1;
622 }
623
624 count = 0;
625 pos = 0;
626 len = 0;
627 for (;;) {
628 char *e;
629 res = recv(s, resp + len, sizeof(resp) - len, 0);
630 if (res < 0) {
631 perror("recv");
632 close(s);
633 return -1;
634 }
635 if (res == 0) {
636 printf("Could not read response\n");
637 close(s);
638 return -1;
639 }
640 len += res;
641 next_line:
642 e = memchr(resp + pos, '\r', len - pos);
643 if (e == NULL)
644 continue;
645 *e++ = '\0';
646 if (e - resp < len && *e == '\n')
647 *e++ = '\n';
648 printf("%s\n", resp + pos);
649 if (strncasecmp(resp + pos, "status,RUNNING", 14) != 0)
650 break;
651 count++;
652 if (count == 2)
653 break;
654 pos = e - resp;
655 goto next_line;
656 }
657
658 close(s);
659
660 return 0;
661}
662
663
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530664static char * determine_sigma_p2p_ifname(void)
Danny Segalf2af39b2016-04-10 16:23:11 +0300665{
666 char buf[256];
667 struct wpa_ctrl *ctrl;
668
669 if (sigma_p2p_ifname)
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530670 return sigma_p2p_ifname;
Danny Segalf2af39b2016-04-10 16:23:11 +0300671
672 snprintf(buf, sizeof(buf), "p2p-dev-%s", get_station_ifname());
673 ctrl = open_wpa_mon(buf);
674 if (ctrl) {
675 wpa_ctrl_detach(ctrl);
676 wpa_ctrl_close(ctrl);
677 sigma_p2p_ifname_buf = strdup(buf);
678 sigma_p2p_ifname = sigma_p2p_ifname_buf;
679 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
680 "Using interface %s for P2P operations instead of interface %s",
681 sigma_p2p_ifname ? sigma_p2p_ifname : "NULL",
682 get_station_ifname());
683 } else {
684 sigma_p2p_ifname = get_station_ifname();
685 }
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530686
687 return sigma_p2p_ifname;
Danny Segalf2af39b2016-04-10 16:23:11 +0300688}
689
690
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200691static void set_defaults(struct sigma_dut *dut)
692{
693 dut->ap_p2p_cross_connect = -1;
694 dut->ap_chwidth = AP_AUTO;
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530695 dut->default_11na_ap_chwidth = AP_AUTO;
696 dut->default_11ng_ap_chwidth = AP_AUTO;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200697 /* by default, enable writing of traffic stream stats */
698 dut->write_stats = 1;
699}
700
701
702static const char * const license1 =
703"sigma_dut - WFA Sigma DUT/CA\n"
704"----------------------------\n"
705"\n"
706"Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
707"Copyright (c) 2011-2015, Qualcomm Atheros, Inc.\n"
708"All Rights Reserved.\n"
709"Licensed under the Clear BSD license.\n"
710"\n";
711static const char * const license2 =
712"Redistribution and use in source and binary forms, with or without\n"
713"modification, are permitted (subject to the limitations in the\n"
714"disclaimer below) provided that the following conditions are met:\n"
715"\n";
716static const char * const license3 =
717"* Redistributions of source code must retain the above copyright notice,\n"
718" this list of conditions and the following disclaimer.\n"
719"\n"
720"* Redistributions in binary form must reproduce the above copyright\n"
721" notice, this list of conditions and the following disclaimer in the\n"
722" documentation and/or other materials provided with the distribution.\n"
723"\n"
724"* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
725" contributors may be used to endorse or promote products derived from\n"
726" this software without specific prior written permission.\n"
727"\n";
728static const char * const license4 =
729"NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
730"BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
731"CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
732"BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
733"FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
734"COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
735"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
736"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
737"USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
738"ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
739"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
740"THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
741
742
743static void print_license(void)
744{
745 printf("%s%s%s%s\n",
746 license1, license2, license3, license4);
747}
748
749
750int main(int argc, char *argv[])
751{
752 int c;
753 int daemonize = 0;
754 int port = SIGMA_DUT_PORT;
755 char *local_cmd = NULL;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530756 int internal_dhcp_enabled = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200757#ifdef __QNXNTO__
758 char *env_str = NULL;
759 char buf[20];
760 char *sigma_ctrl_sock = NULL; /* env used for QNX */
761#endif /* __QNXNTO__ */
762
763 memset(&sigma_dut, 0, sizeof(sigma_dut));
764 sigma_dut.debug_level = DUT_MSG_INFO;
765 sigma_dut.default_timeout = 120;
766 sigma_dut.dialog_token = 0;
Jouni Malinend86e5822017-08-29 03:55:32 +0300767 sigma_dut.dpp_conf_id = -1;
Jouni Malinen63d50412017-11-24 11:55:38 +0200768 sigma_dut.dpp_local_bootstrap = -1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200769 set_defaults(&sigma_dut);
770
771 for (;;) {
772 c = getopt(argc, argv,
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300773 "aAb:Bc:C:dDE:e:fF:gGhH:j:i:Ik:l:L:m:M:nN:o:O:p:P:qr:R:s:S:tT:uv:VWw:x:y:");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200774 if (c < 0)
775 break;
776 switch (c) {
777 case 'a':
778 sigma_dut.ap_anqpserver = 1;
779 break;
780 case 'b':
781 sigma_dut.bridge = optarg;
782 break;
783 case 'B':
784 daemonize++;
785 break;
786 case 'C':
787 sigma_cert_path = optarg;
788 break;
789 case 'd':
790 if (sigma_dut.debug_level > 0)
791 sigma_dut.debug_level--;
792 break;
793#ifdef __QNXNTO__
794 case 'E':
795 sigma_ctrl_sock = optarg;
796 break;
797#endif /* __QNXNTO__ */
798 case 'D':
799 sigma_dut.stdout_debug = 1;
800 break;
801 case 'e':
802 sigma_dut.hostapd_entropy_log = optarg;
803 break;
804 case 'f':
805 /* Disable writing stats */
806 sigma_dut.write_stats = 0;
807 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300808 case 'F':
809 sigma_dut.hostapd_bin = optarg;
810 break;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530811 case 'g':
812 /* Enable internal processing of P2P group formation
813 * events to start/stop DHCP server/client. */
814 internal_dhcp_enabled = 1;
815 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300816 case 'G':
817 sigma_dut.use_hostapd_pid_file = 1;
818 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200819 case 'H':
820 sigma_dut.hostapd_debug_log = optarg;
821 break;
822 case 'I':
823 print_license();
824 exit(0);
825 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300826 case 'j':
827 sigma_dut.hostapd_ifname = optarg;
828 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200829 case 'l':
830 local_cmd = optarg;
831 break;
832 case 'L':
833 sigma_dut.summary_log = optarg;
834 break;
835 case 'p':
836 port = atoi(optarg);
837 break;
Danny Segalf2af39b2016-04-10 16:23:11 +0300838 case 'P':
839 sigma_p2p_ifname = optarg;
840 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200841 case 'q':
842 sigma_dut.debug_level++;
843 break;
844 case 'r':
845 if (strcmp(optarg, "HT40") == 0) {
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530846 sigma_dut.default_11na_ap_chwidth = AP_40;
847 } else if (strcmp(optarg, "2.4_HT40") == 0) {
848 sigma_dut.default_11ng_ap_chwidth = AP_40;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200849 } else {
850 printf("Unsupported -r value\n");
851 exit(1);
852 }
853 break;
854 case 'R': {
855 static int num_radio = 0;
856 static char **radio_ptr = sigma_radio_ifname;
857
858 num_radio++;
859 if (num_radio > MAX_RADIO) {
860 printf("Multiple radio support limit (%d) exceeded\n",
861 MAX_RADIO);
862 exit(1);
863 }
864 *radio_ptr++ = optarg;
865 break;
866 }
867 case 's':
868 sigma_dut.sniffer_ifname = optarg;
869 break;
870 case 't':
871 sigma_dut.no_timestamps = 1;
872 break;
873 case 'T':
874 sigma_dut.throughput_pktsize = atoi(optarg);
Jouni Malinenc2493f82016-06-05 18:01:33 +0300875 if (sigma_dut.throughput_pktsize == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200876 printf("Invalid -T value\n");
877 exit(0);
878 }
879 break;
880 case 'm':
881 sigma_dut.set_macaddr = optarg;
882 break;
883 case 'M':
884 sigma_main_ifname = optarg;
885 break;
886 case 'n':
887 sigma_dut.no_ip_addr_set = 1;
888 break;
Jouni Malinen5db3b102016-08-04 12:27:18 +0300889 case 'N':
890 sigma_dut.vendor_name = optarg;
891 break;
892 case 'o':
893 sigma_dut.model_name = optarg;
894 break;
895 case 'O':
896 sigma_dut.version_name = optarg;
897 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200898 case 'S':
899 sigma_station_ifname = optarg;
900 break;
901 case 'w':
902 sigma_hapd_ctrl = optarg;
903 sigma_wpas_ctrl = optarg;
904 break;
905 case 'i':
906 ap_inet_addr = optarg;
907 break;
908 case 'k':
909 ap_inet_mask = optarg;
910 break;
911 case 'c':
912 printf("%s", optarg);
913 if (set_wifi_chip(optarg) < 0)
914 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
915 "WRONG CHIP TYPE: SAP will "
916 "not load");
917 break;
918 case 'v':
919 sigma_dut.version = optarg;
920 break;
921 case 'V':
922 printf("sigma_dut " SIGMA_DUT_VER "\n");
923 exit(0);
924 break;
925 case 'W':
926 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
927 "Running WMM-AC test suite");
928 sigma_wmm_ac = 1;
929 break;
930 case 'u':
931 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
932 "Use iface down/up in reset cmd");
933 sigma_dut.iface_down_on_reset = 1;
934 break;
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530935 case 'A':
936 sigma_dut.sim_no_username = 1;
937 break;
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700938#ifdef MIRACAST
939 case 'x':
940 if (strcmp(optarg, "sink") == 0) {
941 sigma_dut.wfd_device_type = 1;
942 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
943 "Device Type is SINK");
944 } else if (strcmp(optarg, "source") == 0) {
945 sigma_dut.wfd_device_type = 0;
946 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
947 "Device Type is SOURCE");
948 }
949 break;
950 case 'y':
951 sigma_dut.miracast_lib_path = optarg;
952 break;
953#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200954 case 'h':
955 default:
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300956 printf("usage: sigma_dut [-aABdfGqDIntuVW] [-p<port>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200957 "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
958 " [-M<main ifname>] [-R<radio ifname>] "
Danny Segalf2af39b2016-04-10 16:23:11 +0300959 "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200960 " [-T<throughput pktsize>] \\\n"
961 " [-w<wpa_supplicant/hostapd ctrl_iface "
962 "dir>] \\\n"
963 " [-H <hostapd log file>] \\\n"
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300964 " [-F <hostapd binary path>] \\\n"
965 " [-j <hostapd ifname>] \\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200966 " [-C <certificate path>] \\\n"
967 " [-v <version string>] \\\n"
968 " [-L <summary log>] \\\n"
969 " [-c <wifi chip type: WCN or ATHEROS or "
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +0530970 "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
971 "LINUX-WCN>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200972 "\\\n"
973 " [-i <IP address of the AP>] \\\n"
974 " [-k <subnet mask for the AP>] \\\n"
975 " [-e <hostapd entropy file>] \\\n"
Jouni Malinen5db3b102016-08-04 12:27:18 +0300976 " [-N <device_get_info vendor>] \\\n"
977 " [-o <device_get_info model>] \\\n"
978 " [-O <device_get_info version>] \\\n"
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700979#ifdef MIRACAST
980 " [-x <sink|source>] \\\n"
981 " [-y <Miracast library path>] \\\n"
982#endif /* MIRACAST */
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530983 " [-r <HT40 or 2.4_HT40>]\n");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200984 printf("local command: sigma_dut [-p<port>] "
985 "<-l<cmd>>\n");
986 exit(0);
987 break;
988 }
989 }
990
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530991 sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700992#ifdef MIRACAST
993 miracast_init(&sigma_dut);
994#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200995 if (local_cmd)
996 return run_local_cmd(port, local_cmd);
997
Pradeep Reddy Potteti08eaeba2017-06-14 12:43:19 +0530998 if ((wifi_chip_type == DRIVER_QNXNTO ||
999 wifi_chip_type == DRIVER_LINUX_WCN) &&
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001000 (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
1001 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
Pradeep Reddy Potteti08eaeba2017-06-14 12:43:19 +05301002 "Interface should be provided for QNX/LINUX-WCN driver - check option M and S");
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001003 }
1004
1005 sigma_dut_register_cmds();
1006
1007#ifdef __QNXNTO__
1008 /* Try to open socket in other env dev */
1009 if (sigma_ctrl_sock) {
1010 env_str = getenv("SOCK");
1011 if (env_str) {
1012 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1013 "SOCK=%s", env_str);
1014 }
1015 snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
1016 if (putenv(buf) != 0) {
1017 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1018 "putenv() failed setting SOCK");
1019 return EXIT_FAILURE;
1020 }
1021 }
1022#endif /* __QNXNTO__ */
1023
1024 if (open_socket(&sigma_dut, port) < 0)
1025 return -1;
1026
1027#ifdef __QNXNTO__
1028 /* restore back the SOCK */
1029 if (sigma_ctrl_sock) {
1030 if (env_str) {
1031 snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
1032 if (putenv(buf) != 0) {
1033 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1034 "putenv() failed setting SOCK");
1035 return EXIT_FAILURE;
1036 }
1037 } else {
1038 /* unset the env for sock */
1039 unsetenv("SOCK");
1040 }
1041 }
1042#endif /* __QNXNTO__ */
1043
1044 if (daemonize) {
1045 if (daemon(0, 0) < 0) {
1046 perror("daemon");
1047 exit(-1);
1048 }
1049 } else {
1050#ifdef __linux__
1051 setlinebuf(stdout);
1052#endif /* __linux__ */
1053 }
1054
Purushottam Kushwaha091e2532016-08-23 11:52:21 +05301055 if (internal_dhcp_enabled)
1056 p2p_create_event_thread(&sigma_dut);
1057
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001058 run_loop(&sigma_dut);
1059
1060#ifdef CONFIG_SNIFFER
1061 sniffer_close(&sigma_dut);
1062#endif /* CONFIG_SNIFFER */
1063
Danny Segalf2af39b2016-04-10 16:23:11 +03001064 free(sigma_p2p_ifname_buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001065 close_socket(&sigma_dut);
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07001066#ifdef MIRACAST
1067 miracast_deinit(&sigma_dut);
1068#endif /* MIRACAST */
Ashwini Patil00402582017-04-13 12:29:39 +05301069 free(sigma_dut.non_pref_ch_list);
1070 sigma_dut.non_pref_ch_list = NULL;
Ashwini Patil5acd7382017-04-13 15:55:04 +05301071 free(sigma_dut.btm_query_cand_list);
1072 sigma_dut.btm_query_cand_list = NULL;
Jouni Malinen3c367e82017-06-23 17:01:47 +03001073 free(sigma_dut.rsne_override);
Jouni Malinened670f42017-08-31 01:39:28 +03001074 free(sigma_dut.ap_sae_groups);
Jouni Malinenb1dd21f2017-11-13 19:14:29 +02001075 free(sigma_dut.dpp_peer_uri);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001076 sigma_dut_unreg_cmds(&sigma_dut);
1077
1078 return 0;
1079}