blob: 7c174d6527596a6faeacb6d3b31f800743db06c1 [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;
767 set_defaults(&sigma_dut);
768
769 for (;;) {
770 c = getopt(argc, argv,
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300771 "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 +0200772 if (c < 0)
773 break;
774 switch (c) {
775 case 'a':
776 sigma_dut.ap_anqpserver = 1;
777 break;
778 case 'b':
779 sigma_dut.bridge = optarg;
780 break;
781 case 'B':
782 daemonize++;
783 break;
784 case 'C':
785 sigma_cert_path = optarg;
786 break;
787 case 'd':
788 if (sigma_dut.debug_level > 0)
789 sigma_dut.debug_level--;
790 break;
791#ifdef __QNXNTO__
792 case 'E':
793 sigma_ctrl_sock = optarg;
794 break;
795#endif /* __QNXNTO__ */
796 case 'D':
797 sigma_dut.stdout_debug = 1;
798 break;
799 case 'e':
800 sigma_dut.hostapd_entropy_log = optarg;
801 break;
802 case 'f':
803 /* Disable writing stats */
804 sigma_dut.write_stats = 0;
805 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300806 case 'F':
807 sigma_dut.hostapd_bin = optarg;
808 break;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530809 case 'g':
810 /* Enable internal processing of P2P group formation
811 * events to start/stop DHCP server/client. */
812 internal_dhcp_enabled = 1;
813 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300814 case 'G':
815 sigma_dut.use_hostapd_pid_file = 1;
816 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200817 case 'H':
818 sigma_dut.hostapd_debug_log = optarg;
819 break;
820 case 'I':
821 print_license();
822 exit(0);
823 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300824 case 'j':
825 sigma_dut.hostapd_ifname = optarg;
826 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200827 case 'l':
828 local_cmd = optarg;
829 break;
830 case 'L':
831 sigma_dut.summary_log = optarg;
832 break;
833 case 'p':
834 port = atoi(optarg);
835 break;
Danny Segalf2af39b2016-04-10 16:23:11 +0300836 case 'P':
837 sigma_p2p_ifname = optarg;
838 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200839 case 'q':
840 sigma_dut.debug_level++;
841 break;
842 case 'r':
843 if (strcmp(optarg, "HT40") == 0) {
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530844 sigma_dut.default_11na_ap_chwidth = AP_40;
845 } else if (strcmp(optarg, "2.4_HT40") == 0) {
846 sigma_dut.default_11ng_ap_chwidth = AP_40;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200847 } else {
848 printf("Unsupported -r value\n");
849 exit(1);
850 }
851 break;
852 case 'R': {
853 static int num_radio = 0;
854 static char **radio_ptr = sigma_radio_ifname;
855
856 num_radio++;
857 if (num_radio > MAX_RADIO) {
858 printf("Multiple radio support limit (%d) exceeded\n",
859 MAX_RADIO);
860 exit(1);
861 }
862 *radio_ptr++ = optarg;
863 break;
864 }
865 case 's':
866 sigma_dut.sniffer_ifname = optarg;
867 break;
868 case 't':
869 sigma_dut.no_timestamps = 1;
870 break;
871 case 'T':
872 sigma_dut.throughput_pktsize = atoi(optarg);
Jouni Malinenc2493f82016-06-05 18:01:33 +0300873 if (sigma_dut.throughput_pktsize == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200874 printf("Invalid -T value\n");
875 exit(0);
876 }
877 break;
878 case 'm':
879 sigma_dut.set_macaddr = optarg;
880 break;
881 case 'M':
882 sigma_main_ifname = optarg;
883 break;
884 case 'n':
885 sigma_dut.no_ip_addr_set = 1;
886 break;
Jouni Malinen5db3b102016-08-04 12:27:18 +0300887 case 'N':
888 sigma_dut.vendor_name = optarg;
889 break;
890 case 'o':
891 sigma_dut.model_name = optarg;
892 break;
893 case 'O':
894 sigma_dut.version_name = optarg;
895 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200896 case 'S':
897 sigma_station_ifname = optarg;
898 break;
899 case 'w':
900 sigma_hapd_ctrl = optarg;
901 sigma_wpas_ctrl = optarg;
902 break;
903 case 'i':
904 ap_inet_addr = optarg;
905 break;
906 case 'k':
907 ap_inet_mask = optarg;
908 break;
909 case 'c':
910 printf("%s", optarg);
911 if (set_wifi_chip(optarg) < 0)
912 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
913 "WRONG CHIP TYPE: SAP will "
914 "not load");
915 break;
916 case 'v':
917 sigma_dut.version = optarg;
918 break;
919 case 'V':
920 printf("sigma_dut " SIGMA_DUT_VER "\n");
921 exit(0);
922 break;
923 case 'W':
924 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
925 "Running WMM-AC test suite");
926 sigma_wmm_ac = 1;
927 break;
928 case 'u':
929 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
930 "Use iface down/up in reset cmd");
931 sigma_dut.iface_down_on_reset = 1;
932 break;
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530933 case 'A':
934 sigma_dut.sim_no_username = 1;
935 break;
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700936#ifdef MIRACAST
937 case 'x':
938 if (strcmp(optarg, "sink") == 0) {
939 sigma_dut.wfd_device_type = 1;
940 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
941 "Device Type is SINK");
942 } else if (strcmp(optarg, "source") == 0) {
943 sigma_dut.wfd_device_type = 0;
944 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
945 "Device Type is SOURCE");
946 }
947 break;
948 case 'y':
949 sigma_dut.miracast_lib_path = optarg;
950 break;
951#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200952 case 'h':
953 default:
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300954 printf("usage: sigma_dut [-aABdfGqDIntuVW] [-p<port>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200955 "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
956 " [-M<main ifname>] [-R<radio ifname>] "
Danny Segalf2af39b2016-04-10 16:23:11 +0300957 "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200958 " [-T<throughput pktsize>] \\\n"
959 " [-w<wpa_supplicant/hostapd ctrl_iface "
960 "dir>] \\\n"
961 " [-H <hostapd log file>] \\\n"
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300962 " [-F <hostapd binary path>] \\\n"
963 " [-j <hostapd ifname>] \\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200964 " [-C <certificate path>] \\\n"
965 " [-v <version string>] \\\n"
966 " [-L <summary log>] \\\n"
967 " [-c <wifi chip type: WCN or ATHEROS or "
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +0530968 "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
969 "LINUX-WCN>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200970 "\\\n"
971 " [-i <IP address of the AP>] \\\n"
972 " [-k <subnet mask for the AP>] \\\n"
973 " [-e <hostapd entropy file>] \\\n"
Jouni Malinen5db3b102016-08-04 12:27:18 +0300974 " [-N <device_get_info vendor>] \\\n"
975 " [-o <device_get_info model>] \\\n"
976 " [-O <device_get_info version>] \\\n"
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700977#ifdef MIRACAST
978 " [-x <sink|source>] \\\n"
979 " [-y <Miracast library path>] \\\n"
980#endif /* MIRACAST */
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530981 " [-r <HT40 or 2.4_HT40>]\n");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200982 printf("local command: sigma_dut [-p<port>] "
983 "<-l<cmd>>\n");
984 exit(0);
985 break;
986 }
987 }
988
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530989 sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700990#ifdef MIRACAST
991 miracast_init(&sigma_dut);
992#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200993 if (local_cmd)
994 return run_local_cmd(port, local_cmd);
995
Pradeep Reddy Potteti08eaeba2017-06-14 12:43:19 +0530996 if ((wifi_chip_type == DRIVER_QNXNTO ||
997 wifi_chip_type == DRIVER_LINUX_WCN) &&
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200998 (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
999 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
Pradeep Reddy Potteti08eaeba2017-06-14 12:43:19 +05301000 "Interface should be provided for QNX/LINUX-WCN driver - check option M and S");
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001001 }
1002
1003 sigma_dut_register_cmds();
1004
1005#ifdef __QNXNTO__
1006 /* Try to open socket in other env dev */
1007 if (sigma_ctrl_sock) {
1008 env_str = getenv("SOCK");
1009 if (env_str) {
1010 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1011 "SOCK=%s", env_str);
1012 }
1013 snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
1014 if (putenv(buf) != 0) {
1015 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1016 "putenv() failed setting SOCK");
1017 return EXIT_FAILURE;
1018 }
1019 }
1020#endif /* __QNXNTO__ */
1021
1022 if (open_socket(&sigma_dut, port) < 0)
1023 return -1;
1024
1025#ifdef __QNXNTO__
1026 /* restore back the SOCK */
1027 if (sigma_ctrl_sock) {
1028 if (env_str) {
1029 snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
1030 if (putenv(buf) != 0) {
1031 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1032 "putenv() failed setting SOCK");
1033 return EXIT_FAILURE;
1034 }
1035 } else {
1036 /* unset the env for sock */
1037 unsetenv("SOCK");
1038 }
1039 }
1040#endif /* __QNXNTO__ */
1041
1042 if (daemonize) {
1043 if (daemon(0, 0) < 0) {
1044 perror("daemon");
1045 exit(-1);
1046 }
1047 } else {
1048#ifdef __linux__
1049 setlinebuf(stdout);
1050#endif /* __linux__ */
1051 }
1052
Purushottam Kushwaha091e2532016-08-23 11:52:21 +05301053 if (internal_dhcp_enabled)
1054 p2p_create_event_thread(&sigma_dut);
1055
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001056 run_loop(&sigma_dut);
1057
1058#ifdef CONFIG_SNIFFER
1059 sniffer_close(&sigma_dut);
1060#endif /* CONFIG_SNIFFER */
1061
Danny Segalf2af39b2016-04-10 16:23:11 +03001062 free(sigma_p2p_ifname_buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001063 close_socket(&sigma_dut);
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07001064#ifdef MIRACAST
1065 miracast_deinit(&sigma_dut);
1066#endif /* MIRACAST */
Ashwini Patil00402582017-04-13 12:29:39 +05301067 free(sigma_dut.non_pref_ch_list);
1068 sigma_dut.non_pref_ch_list = NULL;
Ashwini Patil5acd7382017-04-13 15:55:04 +05301069 free(sigma_dut.btm_query_cand_list);
1070 sigma_dut.btm_query_cand_list = NULL;
Jouni Malinen3c367e82017-06-23 17:01:47 +03001071 free(sigma_dut.rsne_override);
Jouni Malinened670f42017-08-31 01:39:28 +03001072 free(sigma_dut.ap_sae_groups);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001073 sigma_dut_unreg_cmds(&sigma_dut);
1074
1075 return 0;
1076}