blob: 7e2d50c3050f6dbbe11b34eafd70e828d1ae251b [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 Malinencd4e3c32015-10-29 12:39:56 +0200768 set_defaults(&sigma_dut);
769
770 for (;;) {
771 c = getopt(argc, argv,
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300772 "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 +0200773 if (c < 0)
774 break;
775 switch (c) {
776 case 'a':
777 sigma_dut.ap_anqpserver = 1;
778 break;
779 case 'b':
780 sigma_dut.bridge = optarg;
781 break;
782 case 'B':
783 daemonize++;
784 break;
785 case 'C':
786 sigma_cert_path = optarg;
787 break;
788 case 'd':
789 if (sigma_dut.debug_level > 0)
790 sigma_dut.debug_level--;
791 break;
792#ifdef __QNXNTO__
793 case 'E':
794 sigma_ctrl_sock = optarg;
795 break;
796#endif /* __QNXNTO__ */
797 case 'D':
798 sigma_dut.stdout_debug = 1;
799 break;
800 case 'e':
801 sigma_dut.hostapd_entropy_log = optarg;
802 break;
803 case 'f':
804 /* Disable writing stats */
805 sigma_dut.write_stats = 0;
806 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300807 case 'F':
808 sigma_dut.hostapd_bin = optarg;
809 break;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530810 case 'g':
811 /* Enable internal processing of P2P group formation
812 * events to start/stop DHCP server/client. */
813 internal_dhcp_enabled = 1;
814 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300815 case 'G':
816 sigma_dut.use_hostapd_pid_file = 1;
817 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200818 case 'H':
819 sigma_dut.hostapd_debug_log = optarg;
820 break;
821 case 'I':
822 print_license();
823 exit(0);
824 break;
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300825 case 'j':
826 sigma_dut.hostapd_ifname = optarg;
827 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200828 case 'l':
829 local_cmd = optarg;
830 break;
831 case 'L':
832 sigma_dut.summary_log = optarg;
833 break;
834 case 'p':
835 port = atoi(optarg);
836 break;
Danny Segalf2af39b2016-04-10 16:23:11 +0300837 case 'P':
838 sigma_p2p_ifname = optarg;
839 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200840 case 'q':
841 sigma_dut.debug_level++;
842 break;
843 case 'r':
844 if (strcmp(optarg, "HT40") == 0) {
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530845 sigma_dut.default_11na_ap_chwidth = AP_40;
846 } else if (strcmp(optarg, "2.4_HT40") == 0) {
847 sigma_dut.default_11ng_ap_chwidth = AP_40;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200848 } else {
849 printf("Unsupported -r value\n");
850 exit(1);
851 }
852 break;
853 case 'R': {
854 static int num_radio = 0;
855 static char **radio_ptr = sigma_radio_ifname;
856
857 num_radio++;
858 if (num_radio > MAX_RADIO) {
859 printf("Multiple radio support limit (%d) exceeded\n",
860 MAX_RADIO);
861 exit(1);
862 }
863 *radio_ptr++ = optarg;
864 break;
865 }
866 case 's':
867 sigma_dut.sniffer_ifname = optarg;
868 break;
869 case 't':
870 sigma_dut.no_timestamps = 1;
871 break;
872 case 'T':
873 sigma_dut.throughput_pktsize = atoi(optarg);
Jouni Malinenc2493f82016-06-05 18:01:33 +0300874 if (sigma_dut.throughput_pktsize == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200875 printf("Invalid -T value\n");
876 exit(0);
877 }
878 break;
879 case 'm':
880 sigma_dut.set_macaddr = optarg;
881 break;
882 case 'M':
883 sigma_main_ifname = optarg;
884 break;
885 case 'n':
886 sigma_dut.no_ip_addr_set = 1;
887 break;
Jouni Malinen5db3b102016-08-04 12:27:18 +0300888 case 'N':
889 sigma_dut.vendor_name = optarg;
890 break;
891 case 'o':
892 sigma_dut.model_name = optarg;
893 break;
894 case 'O':
895 sigma_dut.version_name = optarg;
896 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200897 case 'S':
898 sigma_station_ifname = optarg;
899 break;
900 case 'w':
901 sigma_hapd_ctrl = optarg;
902 sigma_wpas_ctrl = optarg;
903 break;
904 case 'i':
905 ap_inet_addr = optarg;
906 break;
907 case 'k':
908 ap_inet_mask = optarg;
909 break;
910 case 'c':
911 printf("%s", optarg);
912 if (set_wifi_chip(optarg) < 0)
913 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
914 "WRONG CHIP TYPE: SAP will "
915 "not load");
916 break;
917 case 'v':
918 sigma_dut.version = optarg;
919 break;
920 case 'V':
921 printf("sigma_dut " SIGMA_DUT_VER "\n");
922 exit(0);
923 break;
924 case 'W':
925 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
926 "Running WMM-AC test suite");
927 sigma_wmm_ac = 1;
928 break;
929 case 'u':
930 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
931 "Use iface down/up in reset cmd");
932 sigma_dut.iface_down_on_reset = 1;
933 break;
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530934 case 'A':
935 sigma_dut.sim_no_username = 1;
936 break;
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700937#ifdef MIRACAST
938 case 'x':
939 if (strcmp(optarg, "sink") == 0) {
940 sigma_dut.wfd_device_type = 1;
941 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
942 "Device Type is SINK");
943 } else if (strcmp(optarg, "source") == 0) {
944 sigma_dut.wfd_device_type = 0;
945 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
946 "Device Type is SOURCE");
947 }
948 break;
949 case 'y':
950 sigma_dut.miracast_lib_path = optarg;
951 break;
952#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200953 case 'h':
954 default:
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300955 printf("usage: sigma_dut [-aABdfGqDIntuVW] [-p<port>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200956 "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
957 " [-M<main ifname>] [-R<radio ifname>] "
Danny Segalf2af39b2016-04-10 16:23:11 +0300958 "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200959 " [-T<throughput pktsize>] \\\n"
960 " [-w<wpa_supplicant/hostapd ctrl_iface "
961 "dir>] \\\n"
962 " [-H <hostapd log file>] \\\n"
Jouni Malinend6bf1b42017-06-23 17:51:01 +0300963 " [-F <hostapd binary path>] \\\n"
964 " [-j <hostapd ifname>] \\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200965 " [-C <certificate path>] \\\n"
966 " [-v <version string>] \\\n"
967 " [-L <summary log>] \\\n"
968 " [-c <wifi chip type: WCN or ATHEROS or "
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +0530969 "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
970 "LINUX-WCN>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200971 "\\\n"
972 " [-i <IP address of the AP>] \\\n"
973 " [-k <subnet mask for the AP>] \\\n"
974 " [-e <hostapd entropy file>] \\\n"
Jouni Malinen5db3b102016-08-04 12:27:18 +0300975 " [-N <device_get_info vendor>] \\\n"
976 " [-o <device_get_info model>] \\\n"
977 " [-O <device_get_info version>] \\\n"
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700978#ifdef MIRACAST
979 " [-x <sink|source>] \\\n"
980 " [-y <Miracast library path>] \\\n"
981#endif /* MIRACAST */
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530982 " [-r <HT40 or 2.4_HT40>]\n");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200983 printf("local command: sigma_dut [-p<port>] "
984 "<-l<cmd>>\n");
985 exit(0);
986 break;
987 }
988 }
989
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530990 sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700991#ifdef MIRACAST
992 miracast_init(&sigma_dut);
993#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200994 if (local_cmd)
995 return run_local_cmd(port, local_cmd);
996
Pradeep Reddy Potteti08eaeba2017-06-14 12:43:19 +0530997 if ((wifi_chip_type == DRIVER_QNXNTO ||
998 wifi_chip_type == DRIVER_LINUX_WCN) &&
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200999 (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
1000 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
Pradeep Reddy Potteti08eaeba2017-06-14 12:43:19 +05301001 "Interface should be provided for QNX/LINUX-WCN driver - check option M and S");
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001002 }
1003
1004 sigma_dut_register_cmds();
1005
1006#ifdef __QNXNTO__
1007 /* Try to open socket in other env dev */
1008 if (sigma_ctrl_sock) {
1009 env_str = getenv("SOCK");
1010 if (env_str) {
1011 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
1012 "SOCK=%s", env_str);
1013 }
1014 snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
1015 if (putenv(buf) != 0) {
1016 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1017 "putenv() failed setting SOCK");
1018 return EXIT_FAILURE;
1019 }
1020 }
1021#endif /* __QNXNTO__ */
1022
1023 if (open_socket(&sigma_dut, port) < 0)
1024 return -1;
1025
1026#ifdef __QNXNTO__
1027 /* restore back the SOCK */
1028 if (sigma_ctrl_sock) {
1029 if (env_str) {
1030 snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
1031 if (putenv(buf) != 0) {
1032 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1033 "putenv() failed setting SOCK");
1034 return EXIT_FAILURE;
1035 }
1036 } else {
1037 /* unset the env for sock */
1038 unsetenv("SOCK");
1039 }
1040 }
1041#endif /* __QNXNTO__ */
1042
1043 if (daemonize) {
1044 if (daemon(0, 0) < 0) {
1045 perror("daemon");
1046 exit(-1);
1047 }
1048 } else {
1049#ifdef __linux__
1050 setlinebuf(stdout);
1051#endif /* __linux__ */
1052 }
1053
Purushottam Kushwaha091e2532016-08-23 11:52:21 +05301054 if (internal_dhcp_enabled)
1055 p2p_create_event_thread(&sigma_dut);
1056
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001057 run_loop(&sigma_dut);
1058
1059#ifdef CONFIG_SNIFFER
1060 sniffer_close(&sigma_dut);
1061#endif /* CONFIG_SNIFFER */
1062
Danny Segalf2af39b2016-04-10 16:23:11 +03001063 free(sigma_p2p_ifname_buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001064 close_socket(&sigma_dut);
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07001065#ifdef MIRACAST
1066 miracast_deinit(&sigma_dut);
1067#endif /* MIRACAST */
Ashwini Patil00402582017-04-13 12:29:39 +05301068 free(sigma_dut.non_pref_ch_list);
1069 sigma_dut.non_pref_ch_list = NULL;
Ashwini Patil5acd7382017-04-13 15:55:04 +05301070 free(sigma_dut.btm_query_cand_list);
1071 sigma_dut.btm_query_cand_list = NULL;
Jouni Malinen3c367e82017-06-23 17:01:47 +03001072 free(sigma_dut.rsne_override);
Jouni Malinened670f42017-08-31 01:39:28 +03001073 free(sigma_dut.ap_sae_groups);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001074 sigma_dut_unreg_cmds(&sigma_dut);
1075
1076 return 0;
1077}