blob: a2ec281f5813fd749f3846830a01fa383cb870c6 [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;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530470 stop_event_thread();
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200471 printf("sigma_dut terminating\n");
472}
473#endif /* __linux__ */
474
475static void run_loop(struct sigma_dut *dut)
476{
477 struct sigma_conn conn[MAX_CONNECTIONS];
478 int i, res, maxfd, can_accept;
479 fd_set rfds;
480
481 memset(&conn, 0, sizeof(conn));
482 for (i = 0; i < MAX_CONNECTIONS; i++)
483 conn[i].s = -1;
484
485#ifdef __linux__
486 signal(SIGINT, handle_term);
487 signal(SIGTERM, handle_term);
488 signal(SIGPIPE, SIG_IGN);
489#endif /* __linux__ */
490
491 while (!stop_loop) {
492 FD_ZERO(&rfds);
493 maxfd = -1;
494 can_accept = 0;
495 for (i = 0; i < MAX_CONNECTIONS; i++) {
496 if (conn[i].s >= 0) {
497 FD_SET(conn[i].s, &rfds);
498 if (conn[i].s > maxfd)
499 maxfd = conn[i].s;
500 } else if (!conn[i].waiting_completion)
501 can_accept = 1;
502 }
503
504 if (can_accept) {
505 FD_SET(dut->s, &rfds);
506 if (dut->s > maxfd)
507 maxfd = dut->s;
508 }
509
510
511 sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for next "
512 "command (can_accept=%d)", can_accept);
513 res = select(maxfd + 1, &rfds, NULL, NULL, NULL);
514 if (res < 0) {
515 perror("select");
516 if (!stop_loop)
517 sleep(1);
518 continue;
519 }
520
521 if (!res) {
522 sigma_dut_print(dut, DUT_MSG_DEBUG, "Nothing ready");
523 sleep(1);
524 continue;
525 }
526
527 if (FD_ISSET(dut->s, &rfds)) {
528 for (i = 0; i < MAX_CONNECTIONS; i++) {
529 if (conn[i].s < 0 &&
530 !conn[i].waiting_completion)
531 break;
532 }
533 if (i == MAX_CONNECTIONS) {
534 /*
535 * This cannot really happen since can_accept
536 * would not be set to one.
537 */
538 sigma_dut_print(dut, DUT_MSG_DEBUG,
539 "No room for new connection");
540 continue;
541 }
542 conn[i].addrlen = sizeof(conn[i].addr);
543 conn[i].s = accept(dut->s,
544 (struct sockaddr *) &conn[i].addr,
545 &conn[i].addrlen);
546 if (conn[i].s < 0) {
547 sigma_dut_print(dut, DUT_MSG_INFO,
548 "accept: %s",
549 strerror(errno));
550 continue;
551 }
552
553 sigma_dut_print(dut, DUT_MSG_DEBUG,
554 "Connection %d from %s:%d", i,
555 inet_ntoa(conn[i].addr.sin_addr),
556 ntohs(conn[i].addr.sin_port));
557 conn[i].pos = 0;
558 }
559
560 for (i = 0; i < MAX_CONNECTIONS; i++) {
561 if (conn[i].s < 0)
562 continue;
563 if (FD_ISSET(conn[i].s, &rfds))
564 process_conn(dut, &conn[i]);
565 }
566 }
567}
568
569
570static int run_local_cmd(int port, char *lcmd)
571{
572 int s, len;
573 struct sockaddr_in addr;
574 char cmd[MAX_CMD_LEN];
575 ssize_t res;
576 int count;
577 char resp[MAX_CMD_LEN];
578 int pos;
579
580
581 if (strlen(lcmd) > sizeof(cmd) - 4) {
582 printf("Too long command\n");
583 return -1;
584 }
585 len = snprintf(cmd, sizeof(cmd), "%s \r\n", lcmd);
586
587 memset(&addr, 0, sizeof(addr));
588 addr.sin_family = AF_INET;
589 inet_aton("127.0.0.1", &addr.sin_addr);
590 addr.sin_port = htons(port);
591
592 /* Make sure we do not get stuck indefinitely */
593 alarm(150);
594
595 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
596 if (s < 0) {
597 perror("socket");
598 return -1;
599 }
600
601 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
602 perror("connect");
603 close(s);
604 return -1;
605 }
606
607 res = send(s, cmd, len, 0);
608 if (res < 0) {
609 perror("send");
610 close(s);
611 return -1;
612 }
613 if (res != len) {
614 printf("Unexpected send result: %d (expected %d)\n",
615 (int) res, len);
616 close(s);
617 return -1;
618 }
619
620 count = 0;
621 pos = 0;
622 len = 0;
623 for (;;) {
624 char *e;
625 res = recv(s, resp + len, sizeof(resp) - len, 0);
626 if (res < 0) {
627 perror("recv");
628 close(s);
629 return -1;
630 }
631 if (res == 0) {
632 printf("Could not read response\n");
633 close(s);
634 return -1;
635 }
636 len += res;
637 next_line:
638 e = memchr(resp + pos, '\r', len - pos);
639 if (e == NULL)
640 continue;
641 *e++ = '\0';
642 if (e - resp < len && *e == '\n')
643 *e++ = '\n';
644 printf("%s\n", resp + pos);
645 if (strncasecmp(resp + pos, "status,RUNNING", 14) != 0)
646 break;
647 count++;
648 if (count == 2)
649 break;
650 pos = e - resp;
651 goto next_line;
652 }
653
654 close(s);
655
656 return 0;
657}
658
659
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530660static char * determine_sigma_p2p_ifname(void)
Danny Segalf2af39b2016-04-10 16:23:11 +0300661{
662 char buf[256];
663 struct wpa_ctrl *ctrl;
664
665 if (sigma_p2p_ifname)
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530666 return sigma_p2p_ifname;
Danny Segalf2af39b2016-04-10 16:23:11 +0300667
668 snprintf(buf, sizeof(buf), "p2p-dev-%s", get_station_ifname());
669 ctrl = open_wpa_mon(buf);
670 if (ctrl) {
671 wpa_ctrl_detach(ctrl);
672 wpa_ctrl_close(ctrl);
673 sigma_p2p_ifname_buf = strdup(buf);
674 sigma_p2p_ifname = sigma_p2p_ifname_buf;
675 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
676 "Using interface %s for P2P operations instead of interface %s",
677 sigma_p2p_ifname ? sigma_p2p_ifname : "NULL",
678 get_station_ifname());
679 } else {
680 sigma_p2p_ifname = get_station_ifname();
681 }
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530682
683 return sigma_p2p_ifname;
Danny Segalf2af39b2016-04-10 16:23:11 +0300684}
685
686
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200687static void set_defaults(struct sigma_dut *dut)
688{
689 dut->ap_p2p_cross_connect = -1;
690 dut->ap_chwidth = AP_AUTO;
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530691 dut->default_11na_ap_chwidth = AP_AUTO;
692 dut->default_11ng_ap_chwidth = AP_AUTO;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200693 /* by default, enable writing of traffic stream stats */
694 dut->write_stats = 1;
695}
696
697
698static const char * const license1 =
699"sigma_dut - WFA Sigma DUT/CA\n"
700"----------------------------\n"
701"\n"
702"Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
703"Copyright (c) 2011-2015, Qualcomm Atheros, Inc.\n"
704"All Rights Reserved.\n"
705"Licensed under the Clear BSD license.\n"
706"\n";
707static const char * const license2 =
708"Redistribution and use in source and binary forms, with or without\n"
709"modification, are permitted (subject to the limitations in the\n"
710"disclaimer below) provided that the following conditions are met:\n"
711"\n";
712static const char * const license3 =
713"* Redistributions of source code must retain the above copyright notice,\n"
714" this list of conditions and the following disclaimer.\n"
715"\n"
716"* Redistributions in binary form must reproduce the above copyright\n"
717" notice, this list of conditions and the following disclaimer in the\n"
718" documentation and/or other materials provided with the distribution.\n"
719"\n"
720"* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
721" contributors may be used to endorse or promote products derived from\n"
722" this software without specific prior written permission.\n"
723"\n";
724static const char * const license4 =
725"NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
726"BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
727"CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
728"BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
729"FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
730"COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
731"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
732"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
733"USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
734"ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
735"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
736"THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
737
738
739static void print_license(void)
740{
741 printf("%s%s%s%s\n",
742 license1, license2, license3, license4);
743}
744
745
746int main(int argc, char *argv[])
747{
748 int c;
749 int daemonize = 0;
750 int port = SIGMA_DUT_PORT;
751 char *local_cmd = NULL;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530752 int internal_dhcp_enabled = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200753#ifdef __QNXNTO__
754 char *env_str = NULL;
755 char buf[20];
756 char *sigma_ctrl_sock = NULL; /* env used for QNX */
757#endif /* __QNXNTO__ */
758
759 memset(&sigma_dut, 0, sizeof(sigma_dut));
760 sigma_dut.debug_level = DUT_MSG_INFO;
761 sigma_dut.default_timeout = 120;
762 sigma_dut.dialog_token = 0;
763 set_defaults(&sigma_dut);
764
765 for (;;) {
766 c = getopt(argc, argv,
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530767 "aAb:Bc:C:dDE:e:fghH:i:Ik:l:L:m:M:nN:o:O:p:P:qr:R:s:S:tT:uv:VWw:");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200768 if (c < 0)
769 break;
770 switch (c) {
771 case 'a':
772 sigma_dut.ap_anqpserver = 1;
773 break;
774 case 'b':
775 sigma_dut.bridge = optarg;
776 break;
777 case 'B':
778 daemonize++;
779 break;
780 case 'C':
781 sigma_cert_path = optarg;
782 break;
783 case 'd':
784 if (sigma_dut.debug_level > 0)
785 sigma_dut.debug_level--;
786 break;
787#ifdef __QNXNTO__
788 case 'E':
789 sigma_ctrl_sock = optarg;
790 break;
791#endif /* __QNXNTO__ */
792 case 'D':
793 sigma_dut.stdout_debug = 1;
794 break;
795 case 'e':
796 sigma_dut.hostapd_entropy_log = optarg;
797 break;
798 case 'f':
799 /* Disable writing stats */
800 sigma_dut.write_stats = 0;
801 break;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530802 case 'g':
803 /* Enable internal processing of P2P group formation
804 * events to start/stop DHCP server/client. */
805 internal_dhcp_enabled = 1;
806 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200807 case 'H':
808 sigma_dut.hostapd_debug_log = optarg;
809 break;
810 case 'I':
811 print_license();
812 exit(0);
813 break;
814 case 'l':
815 local_cmd = optarg;
816 break;
817 case 'L':
818 sigma_dut.summary_log = optarg;
819 break;
820 case 'p':
821 port = atoi(optarg);
822 break;
Danny Segalf2af39b2016-04-10 16:23:11 +0300823 case 'P':
824 sigma_p2p_ifname = optarg;
825 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200826 case 'q':
827 sigma_dut.debug_level++;
828 break;
829 case 'r':
830 if (strcmp(optarg, "HT40") == 0) {
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530831 sigma_dut.default_11na_ap_chwidth = AP_40;
832 } else if (strcmp(optarg, "2.4_HT40") == 0) {
833 sigma_dut.default_11ng_ap_chwidth = AP_40;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200834 } else {
835 printf("Unsupported -r value\n");
836 exit(1);
837 }
838 break;
839 case 'R': {
840 static int num_radio = 0;
841 static char **radio_ptr = sigma_radio_ifname;
842
843 num_radio++;
844 if (num_radio > MAX_RADIO) {
845 printf("Multiple radio support limit (%d) exceeded\n",
846 MAX_RADIO);
847 exit(1);
848 }
849 *radio_ptr++ = optarg;
850 break;
851 }
852 case 's':
853 sigma_dut.sniffer_ifname = optarg;
854 break;
855 case 't':
856 sigma_dut.no_timestamps = 1;
857 break;
858 case 'T':
859 sigma_dut.throughput_pktsize = atoi(optarg);
Jouni Malinenc2493f82016-06-05 18:01:33 +0300860 if (sigma_dut.throughput_pktsize == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200861 printf("Invalid -T value\n");
862 exit(0);
863 }
864 break;
865 case 'm':
866 sigma_dut.set_macaddr = optarg;
867 break;
868 case 'M':
869 sigma_main_ifname = optarg;
870 break;
871 case 'n':
872 sigma_dut.no_ip_addr_set = 1;
873 break;
Jouni Malinen5db3b102016-08-04 12:27:18 +0300874 case 'N':
875 sigma_dut.vendor_name = optarg;
876 break;
877 case 'o':
878 sigma_dut.model_name = optarg;
879 break;
880 case 'O':
881 sigma_dut.version_name = optarg;
882 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200883 case 'S':
884 sigma_station_ifname = optarg;
885 break;
886 case 'w':
887 sigma_hapd_ctrl = optarg;
888 sigma_wpas_ctrl = optarg;
889 break;
890 case 'i':
891 ap_inet_addr = optarg;
892 break;
893 case 'k':
894 ap_inet_mask = optarg;
895 break;
896 case 'c':
897 printf("%s", optarg);
898 if (set_wifi_chip(optarg) < 0)
899 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
900 "WRONG CHIP TYPE: SAP will "
901 "not load");
902 break;
903 case 'v':
904 sigma_dut.version = optarg;
905 break;
906 case 'V':
907 printf("sigma_dut " SIGMA_DUT_VER "\n");
908 exit(0);
909 break;
910 case 'W':
911 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
912 "Running WMM-AC test suite");
913 sigma_wmm_ac = 1;
914 break;
915 case 'u':
916 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
917 "Use iface down/up in reset cmd");
918 sigma_dut.iface_down_on_reset = 1;
919 break;
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530920 case 'A':
921 sigma_dut.sim_no_username = 1;
922 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200923 case 'h':
924 default:
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530925 printf("usage: sigma_dut [-aABdfqDIntuVW] [-p<port>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200926 "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
927 " [-M<main ifname>] [-R<radio ifname>] "
Danny Segalf2af39b2016-04-10 16:23:11 +0300928 "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200929 " [-T<throughput pktsize>] \\\n"
930 " [-w<wpa_supplicant/hostapd ctrl_iface "
931 "dir>] \\\n"
932 " [-H <hostapd log file>] \\\n"
933 " [-C <certificate path>] \\\n"
934 " [-v <version string>] \\\n"
935 " [-L <summary log>] \\\n"
936 " [-c <wifi chip type: WCN or ATHEROS or "
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +0530937 "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
938 "LINUX-WCN>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200939 "\\\n"
940 " [-i <IP address of the AP>] \\\n"
941 " [-k <subnet mask for the AP>] \\\n"
942 " [-e <hostapd entropy file>] \\\n"
Jouni Malinen5db3b102016-08-04 12:27:18 +0300943 " [-N <device_get_info vendor>] \\\n"
944 " [-o <device_get_info model>] \\\n"
945 " [-O <device_get_info version>] \\\n"
Pradeep Reddy Pottetibf8af292017-02-15 15:28:39 +0530946 " [-r <HT40 or 2.4_HT40>]\n");
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200947 printf("local command: sigma_dut [-p<port>] "
948 "<-l<cmd>>\n");
949 exit(0);
950 break;
951 }
952 }
953
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530954 sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200955 if (local_cmd)
956 return run_local_cmd(port, local_cmd);
957
958 if (wifi_chip_type == DRIVER_QNXNTO &&
959 (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
960 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
961 "Interface should be provided for QNX driver check option M and S");
962 }
963
964 sigma_dut_register_cmds();
965
966#ifdef __QNXNTO__
967 /* Try to open socket in other env dev */
968 if (sigma_ctrl_sock) {
969 env_str = getenv("SOCK");
970 if (env_str) {
971 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
972 "SOCK=%s", env_str);
973 }
974 snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
975 if (putenv(buf) != 0) {
976 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
977 "putenv() failed setting SOCK");
978 return EXIT_FAILURE;
979 }
980 }
981#endif /* __QNXNTO__ */
982
983 if (open_socket(&sigma_dut, port) < 0)
984 return -1;
985
986#ifdef __QNXNTO__
987 /* restore back the SOCK */
988 if (sigma_ctrl_sock) {
989 if (env_str) {
990 snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
991 if (putenv(buf) != 0) {
992 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
993 "putenv() failed setting SOCK");
994 return EXIT_FAILURE;
995 }
996 } else {
997 /* unset the env for sock */
998 unsetenv("SOCK");
999 }
1000 }
1001#endif /* __QNXNTO__ */
1002
1003 if (daemonize) {
1004 if (daemon(0, 0) < 0) {
1005 perror("daemon");
1006 exit(-1);
1007 }
1008 } else {
1009#ifdef __linux__
1010 setlinebuf(stdout);
1011#endif /* __linux__ */
1012 }
1013
Purushottam Kushwaha091e2532016-08-23 11:52:21 +05301014 if (internal_dhcp_enabled)
1015 p2p_create_event_thread(&sigma_dut);
1016
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001017 run_loop(&sigma_dut);
1018
1019#ifdef CONFIG_SNIFFER
1020 sniffer_close(&sigma_dut);
1021#endif /* CONFIG_SNIFFER */
1022
Danny Segalf2af39b2016-04-10 16:23:11 +03001023 free(sigma_p2p_ifname_buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001024 close_socket(&sigma_dut);
1025 sigma_dut_unreg_cmds(&sigma_dut);
1026
1027 return 0;
1028}