blob: 5401f4eb045c094be965ca8ccb12b6f73e56fe0c [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
222 sigma_dut_print(dut, DUT_MSG_INFO, "resp: status=%d buf=%s",
223 status, buf ? buf : "N/A");
224
225 iov[0].iov_base = "status,";
226 iov[0].iov_len = 7;
227 switch (status) {
228 case SIGMA_RUNNING:
229 iov[1].iov_base = "RUNNING,";
230 iov[1].iov_len = 8;
231 break;
232 case SIGMA_INVALID:
233 iov[1].iov_base = "INVALID,";
234 iov[1].iov_len = 8;
235 break;
236 case SIGMA_ERROR:
237 iov[1].iov_base = "ERROR,";
238 iov[1].iov_len = 6;
239 break;
240 case SIGMA_COMPLETE:
241 iov[1].iov_base = "COMPLETE,";
242 iov[1].iov_len = 9;
243 break;
244 }
245 if (status != SIGMA_RUNNING) {
246 sigma_dut_summary(dut, "CAPI resp: status,%s%s",
247 (char *) iov[1].iov_base, buf ? buf : "");
248 }
249 if (buf) {
Jouni Malinen76401f52017-03-18 01:04:55 +0200250 iov[2].iov_base = (void *) buf;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200251 iov[2].iov_len = strlen(buf);
252 iov[3].iov_base = "\r\n";
253 iov[3].iov_len = 2;
254 elems = 4;
255 } else {
256 iov[1].iov_len--;
257 iov[2].iov_base = "\r\n";
258 iov[2].iov_len = 2;
259 elems = 3;
260 }
261
262 memset(&msg, 0, sizeof(msg));
263 msg.msg_iov = iov;
264 msg.msg_iovlen = elems;
265 if (sendmsg(conn->s, &msg, 0) < 0)
266 sigma_dut_print(dut, DUT_MSG_INFO, "sendmsg: %s",
267 strerror(errno));
268}
269
270
271const char * get_param(struct sigma_cmd *cmd, const char *name)
272{
273 int i;
274 for (i = 0; i < cmd->count; i++) {
275 if (strcasecmp(name, cmd->params[i]) == 0)
276 return cmd->values[i];
277 }
278 return NULL;
279}
280
281
282static void process_cmd(struct sigma_dut *dut, struct sigma_conn *conn,
283 char *buf)
284{
285 struct sigma_cmd_handler *h;
286 struct sigma_cmd c;
287 char *cmd, *pos, *pos2;
288 int len;
289 char txt[200];
290 int res;
291
292 while (*buf == '\r' || *buf == '\n' || *buf == '\t' || *buf == ' ')
293 buf++;
294 len = strlen(buf);
295 while (len > 0 && buf[len - 1] == ' ') {
296 buf[len - 1] = '\0';
297 len--;
298 }
299
300 if (dut->debug_level < DUT_MSG_INFO) {
301 pos = strchr(buf, ',');
302 if (pos == NULL)
303 pos = buf + len;
304 if (pos - buf > 50)
305 pos = buf + 50;
306 memcpy(txt, "/====[ ", 7);
307 pos2 = txt + 7;
308 memcpy(pos2, buf, pos - buf);
309 pos2 += pos - buf;
310 *pos2++ = ' ';
311 *pos2++ = ']';
312 while (pos2 - txt < 70)
313 *pos2++ = '=';
314 *pos2++ = '\\';
315 *pos2 = '\0';
316 printf("\n%s\n\n", txt);
317 }
318
319 sigma_dut_print(dut, DUT_MSG_INFO, "cmd: %s", buf);
320 sigma_dut_summary(dut, "CAPI cmd: %s", buf);
321 snprintf(txt, sizeof(txt), "NOTE CAPI:%s", buf);
322 txt[sizeof(txt) - 1] = '\0';
323 wpa_command(get_main_ifname(), txt);
324
325 memset(&c, 0, sizeof(c));
326 cmd = buf;
327 pos = strchr(cmd, ',');
328 if (pos) {
329 *pos++ = '\0';
330 if (strcasecmp(cmd, "AccessPoint") == 0 ||
331 strcasecmp(cmd, "PowerSwitch") == 0) {
332 pos2 = strchr(pos, ',');
333 if (pos2 == NULL)
334 goto invalid_params;
335 c.params[c.count] = pos;
336 c.values[c.count] = pos2;
337 c.count++;
338 pos = strchr(pos2, ',');
339 if (pos)
340 *pos++ = '\0';
341 }
342 while (pos) {
343 pos2 = strchr(pos, ',');
344 if (pos2 == NULL)
345 goto invalid_params;
346 *pos2++ = '\0';
347 if (c.count == MAX_PARAMS) {
348 sigma_dut_print(dut, DUT_MSG_INFO, "Too many "
349 "parameters");
350 goto invalid_params;
351 }
352 c.params[c.count] = pos;
353 c.values[c.count] = pos2;
354 c.count++;
355 pos = strchr(pos2, ',');
356 if (pos)
357 *pos++ = '\0';
358 }
359 }
360 h = dut->cmds;
361 while (h) {
362 if (strcasecmp(cmd, h->cmd) == 0)
363 break;
364 h = h->next;
365 }
366
367 if (h == NULL) {
368 sigma_dut_print(dut, DUT_MSG_INFO, "Unknown command: '%s'",
369 cmd);
370 send_resp(dut, conn, SIGMA_INVALID,
371 "errorCode,Unknown command");
372 goto out;
373 }
374
375 if (h->validate && h->validate(&c) < 0) {
376 invalid_params:
377 sigma_dut_print(dut, DUT_MSG_INFO, "Invalid parameters");
378 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid "
379 "parameters");
380 goto out;
381 }
382
383 send_resp(dut, conn, SIGMA_RUNNING, NULL);
384 sigma_dut_print(dut, DUT_MSG_INFO, "Run command: %s", cmd);
385 res = h->process(dut, conn, &c);
386 if (res == -2)
387 send_resp(dut, conn, SIGMA_ERROR, NULL);
388 else if (res == -1)
389 send_resp(dut, conn, SIGMA_INVALID, NULL);
390 else if (res == 1)
391 send_resp(dut, conn, SIGMA_COMPLETE, NULL);
392
393out:
394 if (dut->debug_level < DUT_MSG_INFO) {
395 pos2 = txt;
396 *pos2++ = '\\';
397 memset(pos2, '-', 69);
398 pos2 += 69;
399 *pos2++ = '/';
400 *pos2 = '\0';
401 printf("\n%s\n\n", txt);
402 }
403}
404
405
406static void process_conn(struct sigma_dut *dut, struct sigma_conn *conn)
407{
408 ssize_t res;
409 int i;
410
411 sigma_dut_print(dut, DUT_MSG_DEBUG, "Read from %s:%d",
412 inet_ntoa(conn->addr.sin_addr),
413 ntohs(conn->addr.sin_port));
414
415 res = recv(conn->s, conn->buf + conn->pos, MAX_CMD_LEN + 5 - conn->pos,
416 0);
417 if (res < 0) {
418 sigma_dut_print(dut, DUT_MSG_INFO, "recv: %s",
419 strerror(errno));
420 }
421 if (res <= 0) {
422 sigma_dut_print(dut, DUT_MSG_DEBUG, "Close connection from "
423 "%s:%d",
424 inet_ntoa(conn->addr.sin_addr),
425 ntohs(conn->addr.sin_port));
426 shutdown(conn->s, SHUT_RDWR);
427 close(conn->s);
428 conn->s = -1;
429 return;
430 }
431
432 sigma_dut_print(dut, DUT_MSG_DEBUG, "Received %d bytes",
433 (int) res);
434
435 for (;;) {
436 for (i = conn->pos; i < conn->pos + res; i++) {
437 if (conn->buf[i] == '\r' || conn->buf[i] == '\n')
438 break;
439 }
440
441 if (i == conn->pos + res) {
442 /* Full command not yet received */
443 conn->pos += res;
444 if (conn->pos >= MAX_CMD_LEN + 5) {
445 sigma_dut_print(dut, DUT_MSG_INFO, "Too long "
446 "command dropped");
447 conn->pos = 0;
448 }
449 break;
450 }
451
452 /* Full command received */
453 conn->buf[i++] = '\0';
454 process_cmd(dut, conn, conn->buf);
455 while (i < conn->pos + res &&
456 (conn->buf[i] == '\r' || conn->buf[i] == '\n'))
457 i++;
458 memmove(conn->buf, &conn->buf[i], conn->pos + res - i);
459 res = conn->pos + res - i;
460 conn->pos = 0;
461 }
462}
463
464
465static int stop_loop = 0;
466
467#ifdef __linux__
468static void handle_term(int sig)
469{
470 stop_loop = 1;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530471 stop_event_thread();
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200472 printf("sigma_dut terminating\n");
473}
474#endif /* __linux__ */
475
476static void run_loop(struct sigma_dut *dut)
477{
478 struct sigma_conn conn[MAX_CONNECTIONS];
479 int i, res, maxfd, can_accept;
480 fd_set rfds;
481
482 memset(&conn, 0, sizeof(conn));
483 for (i = 0; i < MAX_CONNECTIONS; i++)
484 conn[i].s = -1;
485
486#ifdef __linux__
487 signal(SIGINT, handle_term);
488 signal(SIGTERM, handle_term);
489 signal(SIGPIPE, SIG_IGN);
490#endif /* __linux__ */
491
492 while (!stop_loop) {
493 FD_ZERO(&rfds);
494 maxfd = -1;
495 can_accept = 0;
496 for (i = 0; i < MAX_CONNECTIONS; i++) {
497 if (conn[i].s >= 0) {
498 FD_SET(conn[i].s, &rfds);
499 if (conn[i].s > maxfd)
500 maxfd = conn[i].s;
501 } else if (!conn[i].waiting_completion)
502 can_accept = 1;
503 }
504
505 if (can_accept) {
506 FD_SET(dut->s, &rfds);
507 if (dut->s > maxfd)
508 maxfd = dut->s;
509 }
510
511
512 sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for next "
513 "command (can_accept=%d)", can_accept);
514 res = select(maxfd + 1, &rfds, NULL, NULL, NULL);
515 if (res < 0) {
516 perror("select");
517 if (!stop_loop)
518 sleep(1);
519 continue;
520 }
521
522 if (!res) {
523 sigma_dut_print(dut, DUT_MSG_DEBUG, "Nothing ready");
524 sleep(1);
525 continue;
526 }
527
528 if (FD_ISSET(dut->s, &rfds)) {
529 for (i = 0; i < MAX_CONNECTIONS; i++) {
530 if (conn[i].s < 0 &&
531 !conn[i].waiting_completion)
532 break;
533 }
534 if (i == MAX_CONNECTIONS) {
535 /*
536 * This cannot really happen since can_accept
537 * would not be set to one.
538 */
539 sigma_dut_print(dut, DUT_MSG_DEBUG,
540 "No room for new connection");
541 continue;
542 }
543 conn[i].addrlen = sizeof(conn[i].addr);
544 conn[i].s = accept(dut->s,
545 (struct sockaddr *) &conn[i].addr,
546 &conn[i].addrlen);
547 if (conn[i].s < 0) {
548 sigma_dut_print(dut, DUT_MSG_INFO,
549 "accept: %s",
550 strerror(errno));
551 continue;
552 }
553
554 sigma_dut_print(dut, DUT_MSG_DEBUG,
555 "Connection %d from %s:%d", i,
556 inet_ntoa(conn[i].addr.sin_addr),
557 ntohs(conn[i].addr.sin_port));
558 conn[i].pos = 0;
559 }
560
561 for (i = 0; i < MAX_CONNECTIONS; i++) {
562 if (conn[i].s < 0)
563 continue;
564 if (FD_ISSET(conn[i].s, &rfds))
565 process_conn(dut, &conn[i]);
566 }
567 }
568}
569
570
571static int run_local_cmd(int port, char *lcmd)
572{
573 int s, len;
574 struct sockaddr_in addr;
575 char cmd[MAX_CMD_LEN];
576 ssize_t res;
577 int count;
578 char resp[MAX_CMD_LEN];
579 int pos;
580
581
582 if (strlen(lcmd) > sizeof(cmd) - 4) {
583 printf("Too long command\n");
584 return -1;
585 }
586 len = snprintf(cmd, sizeof(cmd), "%s \r\n", lcmd);
587
588 memset(&addr, 0, sizeof(addr));
589 addr.sin_family = AF_INET;
590 inet_aton("127.0.0.1", &addr.sin_addr);
591 addr.sin_port = htons(port);
592
593 /* Make sure we do not get stuck indefinitely */
594 alarm(150);
595
596 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
597 if (s < 0) {
598 perror("socket");
599 return -1;
600 }
601
602 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
603 perror("connect");
604 close(s);
605 return -1;
606 }
607
608 res = send(s, cmd, len, 0);
609 if (res < 0) {
610 perror("send");
611 close(s);
612 return -1;
613 }
614 if (res != len) {
615 printf("Unexpected send result: %d (expected %d)\n",
616 (int) res, len);
617 close(s);
618 return -1;
619 }
620
621 count = 0;
622 pos = 0;
623 len = 0;
624 for (;;) {
625 char *e;
626 res = recv(s, resp + len, sizeof(resp) - len, 0);
627 if (res < 0) {
628 perror("recv");
629 close(s);
630 return -1;
631 }
632 if (res == 0) {
633 printf("Could not read response\n");
634 close(s);
635 return -1;
636 }
637 len += res;
638 next_line:
639 e = memchr(resp + pos, '\r', len - pos);
640 if (e == NULL)
641 continue;
642 *e++ = '\0';
643 if (e - resp < len && *e == '\n')
644 *e++ = '\n';
645 printf("%s\n", resp + pos);
646 if (strncasecmp(resp + pos, "status,RUNNING", 14) != 0)
647 break;
648 count++;
649 if (count == 2)
650 break;
651 pos = e - resp;
652 goto next_line;
653 }
654
655 close(s);
656
657 return 0;
658}
659
660
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530661static char * determine_sigma_p2p_ifname(void)
Danny Segalf2af39b2016-04-10 16:23:11 +0300662{
663 char buf[256];
664 struct wpa_ctrl *ctrl;
665
666 if (sigma_p2p_ifname)
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530667 return sigma_p2p_ifname;
Danny Segalf2af39b2016-04-10 16:23:11 +0300668
669 snprintf(buf, sizeof(buf), "p2p-dev-%s", get_station_ifname());
670 ctrl = open_wpa_mon(buf);
671 if (ctrl) {
672 wpa_ctrl_detach(ctrl);
673 wpa_ctrl_close(ctrl);
674 sigma_p2p_ifname_buf = strdup(buf);
675 sigma_p2p_ifname = sigma_p2p_ifname_buf;
676 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
677 "Using interface %s for P2P operations instead of interface %s",
678 sigma_p2p_ifname ? sigma_p2p_ifname : "NULL",
679 get_station_ifname());
680 } else {
681 sigma_p2p_ifname = get_station_ifname();
682 }
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530683
684 return sigma_p2p_ifname;
Danny Segalf2af39b2016-04-10 16:23:11 +0300685}
686
687
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200688static void set_defaults(struct sigma_dut *dut)
689{
690 dut->ap_p2p_cross_connect = -1;
691 dut->ap_chwidth = AP_AUTO;
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530692 dut->default_11na_ap_chwidth = AP_AUTO;
693 dut->default_11ng_ap_chwidth = AP_AUTO;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200694 /* by default, enable writing of traffic stream stats */
695 dut->write_stats = 1;
696}
697
698
699static const char * const license1 =
700"sigma_dut - WFA Sigma DUT/CA\n"
701"----------------------------\n"
702"\n"
703"Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
704"Copyright (c) 2011-2015, Qualcomm Atheros, Inc.\n"
705"All Rights Reserved.\n"
706"Licensed under the Clear BSD license.\n"
707"\n";
708static const char * const license2 =
709"Redistribution and use in source and binary forms, with or without\n"
710"modification, are permitted (subject to the limitations in the\n"
711"disclaimer below) provided that the following conditions are met:\n"
712"\n";
713static const char * const license3 =
714"* Redistributions of source code must retain the above copyright notice,\n"
715" this list of conditions and the following disclaimer.\n"
716"\n"
717"* Redistributions in binary form must reproduce the above copyright\n"
718" notice, this list of conditions and the following disclaimer in the\n"
719" documentation and/or other materials provided with the distribution.\n"
720"\n"
721"* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
722" contributors may be used to endorse or promote products derived from\n"
723" this software without specific prior written permission.\n"
724"\n";
725static const char * const license4 =
726"NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
727"BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
728"CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
729"BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
730"FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
731"COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
732"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
733"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
734"USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
735"ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
736"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
737"THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
738
739
740static void print_license(void)
741{
742 printf("%s%s%s%s\n",
743 license1, license2, license3, license4);
744}
745
746
747int main(int argc, char *argv[])
748{
749 int c;
750 int daemonize = 0;
751 int port = SIGMA_DUT_PORT;
752 char *local_cmd = NULL;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530753 int internal_dhcp_enabled = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200754#ifdef __QNXNTO__
755 char *env_str = NULL;
756 char buf[20];
757 char *sigma_ctrl_sock = NULL; /* env used for QNX */
758#endif /* __QNXNTO__ */
759
760 memset(&sigma_dut, 0, sizeof(sigma_dut));
761 sigma_dut.debug_level = DUT_MSG_INFO;
762 sigma_dut.default_timeout = 120;
763 sigma_dut.dialog_token = 0;
764 set_defaults(&sigma_dut);
765
766 for (;;) {
767 c = getopt(argc, argv,
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700768 "aAb:Bc:C:dDE:e:fghH: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 +0200769 if (c < 0)
770 break;
771 switch (c) {
772 case 'a':
773 sigma_dut.ap_anqpserver = 1;
774 break;
775 case 'b':
776 sigma_dut.bridge = optarg;
777 break;
778 case 'B':
779 daemonize++;
780 break;
781 case 'C':
782 sigma_cert_path = optarg;
783 break;
784 case 'd':
785 if (sigma_dut.debug_level > 0)
786 sigma_dut.debug_level--;
787 break;
788#ifdef __QNXNTO__
789 case 'E':
790 sigma_ctrl_sock = optarg;
791 break;
792#endif /* __QNXNTO__ */
793 case 'D':
794 sigma_dut.stdout_debug = 1;
795 break;
796 case 'e':
797 sigma_dut.hostapd_entropy_log = optarg;
798 break;
799 case 'f':
800 /* Disable writing stats */
801 sigma_dut.write_stats = 0;
802 break;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530803 case 'g':
804 /* Enable internal processing of P2P group formation
805 * events to start/stop DHCP server/client. */
806 internal_dhcp_enabled = 1;
807 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200808 case 'H':
809 sigma_dut.hostapd_debug_log = optarg;
810 break;
811 case 'I':
812 print_license();
813 exit(0);
814 break;
815 case 'l':
816 local_cmd = optarg;
817 break;
818 case 'L':
819 sigma_dut.summary_log = optarg;
820 break;
821 case 'p':
822 port = atoi(optarg);
823 break;
Danny Segalf2af39b2016-04-10 16:23:11 +0300824 case 'P':
825 sigma_p2p_ifname = optarg;
826 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200827 case 'q':
828 sigma_dut.debug_level++;
829 break;
830 case 'r':
831 if (strcmp(optarg, "HT40") == 0) {
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530832 sigma_dut.default_11na_ap_chwidth = AP_40;
833 } else if (strcmp(optarg, "2.4_HT40") == 0) {
834 sigma_dut.default_11ng_ap_chwidth = AP_40;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200835 } else {
836 printf("Unsupported -r value\n");
837 exit(1);
838 }
839 break;
840 case 'R': {
841 static int num_radio = 0;
842 static char **radio_ptr = sigma_radio_ifname;
843
844 num_radio++;
845 if (num_radio > MAX_RADIO) {
846 printf("Multiple radio support limit (%d) exceeded\n",
847 MAX_RADIO);
848 exit(1);
849 }
850 *radio_ptr++ = optarg;
851 break;
852 }
853 case 's':
854 sigma_dut.sniffer_ifname = optarg;
855 break;
856 case 't':
857 sigma_dut.no_timestamps = 1;
858 break;
859 case 'T':
860 sigma_dut.throughput_pktsize = atoi(optarg);
Jouni Malinenc2493f82016-06-05 18:01:33 +0300861 if (sigma_dut.throughput_pktsize == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200862 printf("Invalid -T value\n");
863 exit(0);
864 }
865 break;
866 case 'm':
867 sigma_dut.set_macaddr = optarg;
868 break;
869 case 'M':
870 sigma_main_ifname = optarg;
871 break;
872 case 'n':
873 sigma_dut.no_ip_addr_set = 1;
874 break;
Jouni Malinen5db3b102016-08-04 12:27:18 +0300875 case 'N':
876 sigma_dut.vendor_name = optarg;
877 break;
878 case 'o':
879 sigma_dut.model_name = optarg;
880 break;
881 case 'O':
882 sigma_dut.version_name = optarg;
883 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200884 case 'S':
885 sigma_station_ifname = optarg;
886 break;
887 case 'w':
888 sigma_hapd_ctrl = optarg;
889 sigma_wpas_ctrl = optarg;
890 break;
891 case 'i':
892 ap_inet_addr = optarg;
893 break;
894 case 'k':
895 ap_inet_mask = optarg;
896 break;
897 case 'c':
898 printf("%s", optarg);
899 if (set_wifi_chip(optarg) < 0)
900 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
901 "WRONG CHIP TYPE: SAP will "
902 "not load");
903 break;
904 case 'v':
905 sigma_dut.version = optarg;
906 break;
907 case 'V':
908 printf("sigma_dut " SIGMA_DUT_VER "\n");
909 exit(0);
910 break;
911 case 'W':
912 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
913 "Running WMM-AC test suite");
914 sigma_wmm_ac = 1;
915 break;
916 case 'u':
917 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
918 "Use iface down/up in reset cmd");
919 sigma_dut.iface_down_on_reset = 1;
920 break;
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530921 case 'A':
922 sigma_dut.sim_no_username = 1;
923 break;
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700924#ifdef MIRACAST
925 case 'x':
926 if (strcmp(optarg, "sink") == 0) {
927 sigma_dut.wfd_device_type = 1;
928 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
929 "Device Type is SINK");
930 } else if (strcmp(optarg, "source") == 0) {
931 sigma_dut.wfd_device_type = 0;
932 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
933 "Device Type is SOURCE");
934 }
935 break;
936 case 'y':
937 sigma_dut.miracast_lib_path = optarg;
938 break;
939#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200940 case 'h':
941 default:
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530942 printf("usage: sigma_dut [-aABdfqDIntuVW] [-p<port>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200943 "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
944 " [-M<main ifname>] [-R<radio ifname>] "
Danny Segalf2af39b2016-04-10 16:23:11 +0300945 "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200946 " [-T<throughput pktsize>] \\\n"
947 " [-w<wpa_supplicant/hostapd ctrl_iface "
948 "dir>] \\\n"
949 " [-H <hostapd log file>] \\\n"
950 " [-C <certificate path>] \\\n"
951 " [-v <version string>] \\\n"
952 " [-L <summary log>] \\\n"
953 " [-c <wifi chip type: WCN or ATHEROS or "
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +0530954 "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
955 "LINUX-WCN>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200956 "\\\n"
957 " [-i <IP address of the AP>] \\\n"
958 " [-k <subnet mask for the AP>] \\\n"
959 " [-e <hostapd entropy file>] \\\n"
Jouni Malinen5db3b102016-08-04 12:27:18 +0300960 " [-N <device_get_info vendor>] \\\n"
961 " [-o <device_get_info model>] \\\n"
962 " [-O <device_get_info version>] \\\n"
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700963#ifdef MIRACAST
964 " [-x <sink|source>] \\\n"
965 " [-y <Miracast library path>] \\\n"
966#endif /* MIRACAST */
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530967 " [-r <HT40 or 2.4_HT40>]\n");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200968 printf("local command: sigma_dut [-p<port>] "
969 "<-l<cmd>>\n");
970 exit(0);
971 break;
972 }
973 }
974
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530975 sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -0700976#ifdef MIRACAST
977 miracast_init(&sigma_dut);
978#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200979 if (local_cmd)
980 return run_local_cmd(port, local_cmd);
981
982 if (wifi_chip_type == DRIVER_QNXNTO &&
983 (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
984 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
985 "Interface should be provided for QNX driver check option M and S");
986 }
987
988 sigma_dut_register_cmds();
989
990#ifdef __QNXNTO__
991 /* Try to open socket in other env dev */
992 if (sigma_ctrl_sock) {
993 env_str = getenv("SOCK");
994 if (env_str) {
995 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
996 "SOCK=%s", env_str);
997 }
998 snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
999 if (putenv(buf) != 0) {
1000 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
1001 "putenv() failed setting SOCK");
1002 return EXIT_FAILURE;
1003 }
1004 }
1005#endif /* __QNXNTO__ */
1006
1007 if (open_socket(&sigma_dut, port) < 0)
1008 return -1;
1009
1010#ifdef __QNXNTO__
1011 /* restore back the SOCK */
1012 if (sigma_ctrl_sock) {
1013 if (env_str) {
1014 snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
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 } else {
1021 /* unset the env for sock */
1022 unsetenv("SOCK");
1023 }
1024 }
1025#endif /* __QNXNTO__ */
1026
1027 if (daemonize) {
1028 if (daemon(0, 0) < 0) {
1029 perror("daemon");
1030 exit(-1);
1031 }
1032 } else {
1033#ifdef __linux__
1034 setlinebuf(stdout);
1035#endif /* __linux__ */
1036 }
1037
Purushottam Kushwaha091e2532016-08-23 11:52:21 +05301038 if (internal_dhcp_enabled)
1039 p2p_create_event_thread(&sigma_dut);
1040
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001041 run_loop(&sigma_dut);
1042
1043#ifdef CONFIG_SNIFFER
1044 sniffer_close(&sigma_dut);
1045#endif /* CONFIG_SNIFFER */
1046
Danny Segalf2af39b2016-04-10 16:23:11 +03001047 free(sigma_p2p_ifname_buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001048 close_socket(&sigma_dut);
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07001049#ifdef MIRACAST
1050 miracast_deinit(&sigma_dut);
1051#endif /* MIRACAST */
Ashwini Patil00402582017-04-13 12:29:39 +05301052 free(sigma_dut.non_pref_ch_list);
1053 sigma_dut.non_pref_ch_list = NULL;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001054 sigma_dut_unreg_cmds(&sigma_dut);
1055
1056 return 0;
1057}