blob: 637945cca723f593edd0c3e13f87dfec4191348e [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;
691 dut->default_ap_chwidth = AP_AUTO;
692 /* by default, enable writing of traffic stream stats */
693 dut->write_stats = 1;
694}
695
696
697static const char * const license1 =
698"sigma_dut - WFA Sigma DUT/CA\n"
699"----------------------------\n"
700"\n"
701"Copyright (c) 2010-2011, Atheros Communications, Inc.\n"
702"Copyright (c) 2011-2015, Qualcomm Atheros, Inc.\n"
703"All Rights Reserved.\n"
704"Licensed under the Clear BSD license.\n"
705"\n";
706static const char * const license2 =
707"Redistribution and use in source and binary forms, with or without\n"
708"modification, are permitted (subject to the limitations in the\n"
709"disclaimer below) provided that the following conditions are met:\n"
710"\n";
711static const char * const license3 =
712"* Redistributions of source code must retain the above copyright notice,\n"
713" this list of conditions and the following disclaimer.\n"
714"\n"
715"* Redistributions in binary form must reproduce the above copyright\n"
716" notice, this list of conditions and the following disclaimer in the\n"
717" documentation and/or other materials provided with the distribution.\n"
718"\n"
719"* Neither the name of Qualcomm Atheros, Inc. nor the names of its\n"
720" contributors may be used to endorse or promote products derived from\n"
721" this software without specific prior written permission.\n"
722"\n";
723static const char * const license4 =
724"NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED\n"
725"BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n"
726"CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\n"
727"BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n"
728"FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n"
729"COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
730"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
731"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n"
732"USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n"
733"ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
734"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
735"THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
736
737
738static void print_license(void)
739{
740 printf("%s%s%s%s\n",
741 license1, license2, license3, license4);
742}
743
744
745int main(int argc, char *argv[])
746{
747 int c;
748 int daemonize = 0;
749 int port = SIGMA_DUT_PORT;
750 char *local_cmd = NULL;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530751 int internal_dhcp_enabled = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200752#ifdef __QNXNTO__
753 char *env_str = NULL;
754 char buf[20];
755 char *sigma_ctrl_sock = NULL; /* env used for QNX */
756#endif /* __QNXNTO__ */
757
758 memset(&sigma_dut, 0, sizeof(sigma_dut));
759 sigma_dut.debug_level = DUT_MSG_INFO;
760 sigma_dut.default_timeout = 120;
761 sigma_dut.dialog_token = 0;
762 set_defaults(&sigma_dut);
763
764 for (;;) {
765 c = getopt(argc, argv,
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530766 "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 +0200767 if (c < 0)
768 break;
769 switch (c) {
770 case 'a':
771 sigma_dut.ap_anqpserver = 1;
772 break;
773 case 'b':
774 sigma_dut.bridge = optarg;
775 break;
776 case 'B':
777 daemonize++;
778 break;
779 case 'C':
780 sigma_cert_path = optarg;
781 break;
782 case 'd':
783 if (sigma_dut.debug_level > 0)
784 sigma_dut.debug_level--;
785 break;
786#ifdef __QNXNTO__
787 case 'E':
788 sigma_ctrl_sock = optarg;
789 break;
790#endif /* __QNXNTO__ */
791 case 'D':
792 sigma_dut.stdout_debug = 1;
793 break;
794 case 'e':
795 sigma_dut.hostapd_entropy_log = optarg;
796 break;
797 case 'f':
798 /* Disable writing stats */
799 sigma_dut.write_stats = 0;
800 break;
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530801 case 'g':
802 /* Enable internal processing of P2P group formation
803 * events to start/stop DHCP server/client. */
804 internal_dhcp_enabled = 1;
805 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200806 case 'H':
807 sigma_dut.hostapd_debug_log = optarg;
808 break;
809 case 'I':
810 print_license();
811 exit(0);
812 break;
813 case 'l':
814 local_cmd = optarg;
815 break;
816 case 'L':
817 sigma_dut.summary_log = optarg;
818 break;
819 case 'p':
820 port = atoi(optarg);
821 break;
Danny Segalf2af39b2016-04-10 16:23:11 +0300822 case 'P':
823 sigma_p2p_ifname = optarg;
824 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200825 case 'q':
826 sigma_dut.debug_level++;
827 break;
828 case 'r':
829 if (strcmp(optarg, "HT40") == 0) {
830 sigma_dut.default_ap_chwidth = AP_40;
831 } else {
832 printf("Unsupported -r value\n");
833 exit(1);
834 }
835 break;
836 case 'R': {
837 static int num_radio = 0;
838 static char **radio_ptr = sigma_radio_ifname;
839
840 num_radio++;
841 if (num_radio > MAX_RADIO) {
842 printf("Multiple radio support limit (%d) exceeded\n",
843 MAX_RADIO);
844 exit(1);
845 }
846 *radio_ptr++ = optarg;
847 break;
848 }
849 case 's':
850 sigma_dut.sniffer_ifname = optarg;
851 break;
852 case 't':
853 sigma_dut.no_timestamps = 1;
854 break;
855 case 'T':
856 sigma_dut.throughput_pktsize = atoi(optarg);
Jouni Malinenc2493f82016-06-05 18:01:33 +0300857 if (sigma_dut.throughput_pktsize == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200858 printf("Invalid -T value\n");
859 exit(0);
860 }
861 break;
862 case 'm':
863 sigma_dut.set_macaddr = optarg;
864 break;
865 case 'M':
866 sigma_main_ifname = optarg;
867 break;
868 case 'n':
869 sigma_dut.no_ip_addr_set = 1;
870 break;
Jouni Malinen5db3b102016-08-04 12:27:18 +0300871 case 'N':
872 sigma_dut.vendor_name = optarg;
873 break;
874 case 'o':
875 sigma_dut.model_name = optarg;
876 break;
877 case 'O':
878 sigma_dut.version_name = optarg;
879 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200880 case 'S':
881 sigma_station_ifname = optarg;
882 break;
883 case 'w':
884 sigma_hapd_ctrl = optarg;
885 sigma_wpas_ctrl = optarg;
886 break;
887 case 'i':
888 ap_inet_addr = optarg;
889 break;
890 case 'k':
891 ap_inet_mask = optarg;
892 break;
893 case 'c':
894 printf("%s", optarg);
895 if (set_wifi_chip(optarg) < 0)
896 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
897 "WRONG CHIP TYPE: SAP will "
898 "not load");
899 break;
900 case 'v':
901 sigma_dut.version = optarg;
902 break;
903 case 'V':
904 printf("sigma_dut " SIGMA_DUT_VER "\n");
905 exit(0);
906 break;
907 case 'W':
908 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
909 "Running WMM-AC test suite");
910 sigma_wmm_ac = 1;
911 break;
912 case 'u':
913 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
914 "Use iface down/up in reset cmd");
915 sigma_dut.iface_down_on_reset = 1;
916 break;
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530917 case 'A':
918 sigma_dut.sim_no_username = 1;
919 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200920 case 'h':
921 default:
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +0530922 printf("usage: sigma_dut [-aABdfqDIntuVW] [-p<port>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200923 "[-s<sniffer>] [-m<set_maccaddr.sh>] \\\n"
924 " [-M<main ifname>] [-R<radio ifname>] "
Danny Segalf2af39b2016-04-10 16:23:11 +0300925 "[-S<station ifname>] [-P<p2p_ifname>]\\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200926 " [-T<throughput pktsize>] \\\n"
927 " [-w<wpa_supplicant/hostapd ctrl_iface "
928 "dir>] \\\n"
929 " [-H <hostapd log file>] \\\n"
930 " [-C <certificate path>] \\\n"
931 " [-v <version string>] \\\n"
932 " [-L <summary log>] \\\n"
933 " [-c <wifi chip type: WCN or ATHEROS or "
Sreelakshmi Konamkib692f102016-04-26 19:47:00 +0530934 "AR6003 or MAC80211 or QNXNTO or OPENWRT or "
935 "LINUX-WCN>] "
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200936 "\\\n"
937 " [-i <IP address of the AP>] \\\n"
938 " [-k <subnet mask for the AP>] \\\n"
939 " [-e <hostapd entropy file>] \\\n"
Jouni Malinen5db3b102016-08-04 12:27:18 +0300940 " [-N <device_get_info vendor>] \\\n"
941 " [-o <device_get_info model>] \\\n"
942 " [-O <device_get_info version>] \\\n"
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200943 " [-r <HT40>]\n");
944 printf("local command: sigma_dut [-p<port>] "
945 "<-l<cmd>>\n");
946 exit(0);
947 break;
948 }
949 }
950
Purushottam Kushwaha091e2532016-08-23 11:52:21 +0530951 sigma_dut.p2p_ifname = determine_sigma_p2p_ifname();
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200952 if (local_cmd)
953 return run_local_cmd(port, local_cmd);
954
955 if (wifi_chip_type == DRIVER_QNXNTO &&
956 (sigma_main_ifname == NULL || sigma_station_ifname == NULL)) {
957 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
958 "Interface should be provided for QNX driver check option M and S");
959 }
960
961 sigma_dut_register_cmds();
962
963#ifdef __QNXNTO__
964 /* Try to open socket in other env dev */
965 if (sigma_ctrl_sock) {
966 env_str = getenv("SOCK");
967 if (env_str) {
968 sigma_dut_print(&sigma_dut, DUT_MSG_INFO,
969 "SOCK=%s", env_str);
970 }
971 snprintf(buf, sizeof(buf), "SOCK=%s", sigma_ctrl_sock);
972 if (putenv(buf) != 0) {
973 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
974 "putenv() failed setting SOCK");
975 return EXIT_FAILURE;
976 }
977 }
978#endif /* __QNXNTO__ */
979
980 if (open_socket(&sigma_dut, port) < 0)
981 return -1;
982
983#ifdef __QNXNTO__
984 /* restore back the SOCK */
985 if (sigma_ctrl_sock) {
986 if (env_str) {
987 snprintf(buf, sizeof(buf), "SOCK=%s", env_str);
988 if (putenv(buf) != 0) {
989 sigma_dut_print(&sigma_dut, DUT_MSG_ERROR,
990 "putenv() failed setting SOCK");
991 return EXIT_FAILURE;
992 }
993 } else {
994 /* unset the env for sock */
995 unsetenv("SOCK");
996 }
997 }
998#endif /* __QNXNTO__ */
999
1000 if (daemonize) {
1001 if (daemon(0, 0) < 0) {
1002 perror("daemon");
1003 exit(-1);
1004 }
1005 } else {
1006#ifdef __linux__
1007 setlinebuf(stdout);
1008#endif /* __linux__ */
1009 }
1010
Purushottam Kushwaha091e2532016-08-23 11:52:21 +05301011 if (internal_dhcp_enabled)
1012 p2p_create_event_thread(&sigma_dut);
1013
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001014 run_loop(&sigma_dut);
1015
1016#ifdef CONFIG_SNIFFER
1017 sniffer_close(&sigma_dut);
1018#endif /* CONFIG_SNIFFER */
1019
Danny Segalf2af39b2016-04-10 16:23:11 +03001020 free(sigma_p2p_ifname_buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001021 close_socket(&sigma_dut);
1022 sigma_dut_unreg_cmds(&sigma_dut);
1023
1024 return 0;
1025}