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