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