blob: 10f87c97d06cd8e8209b74ed4d778259d8dae1db [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#include <sys/ioctl.h>
11#include <sys/stat.h>
12#ifdef __linux__
13#include <sys/time.h>
14#include <netpacket/packet.h>
15#include <linux/if_ether.h>
16#ifdef ANDROID
17#include <cutils/properties.h>
18#include <android/log.h>
19#include "keystore_get.h"
20#else /* ANDROID */
21#include <ifaddrs.h>
22#endif /* ANDROID */
23#include <netdb.h>
24#endif /* __linux__ */
25#ifdef __QNXNTO__
26#include <net/if_dl.h>
27#endif /* __QNXNTO__ */
28#include "wpa_ctrl.h"
29#include "wpa_helpers.h"
30
31/* Temporary files for sta_send_addba */
32#define VI_QOS_TMP_FILE "/tmp/vi-qos.tmp"
33#define VI_QOS_FILE "/tmp/vi-qos.txt"
34#define VI_QOS_REFFILE "/etc/vi-qos.txt"
35
36/*
37 * MTU for Ethernet need to take into account 8-byte SNAP header
38 * to be added when encapsulating Ethernet frame into 802.11
39 */
40#ifndef IEEE80211_MAX_DATA_LEN_DMG
41#define IEEE80211_MAX_DATA_LEN_DMG 7920
42#endif
43#ifndef IEEE80211_SNAP_LEN_DMG
44#define IEEE80211_SNAP_LEN_DMG 8
45#endif
46
47extern char *sigma_wpas_ctrl;
48extern char *sigma_cert_path;
49extern enum driver_type wifi_chip_type;
50extern char *sigma_radio_ifname[];
51
52
53#ifdef ANDROID
54
55static int add_ipv6_rule(struct sigma_dut *dut, const char *ifname);
56
57#define ANDROID_KEYSTORE_GET 'g'
58#define ANDROID_KEYSTORE_GET_PUBKEY 'b'
59
60static int android_keystore_get(char cmd, const char *key, unsigned char *val)
61{
62#ifdef ANDROID43
63 /* Android 4.3 changed keystore design, so need to use keystore_get() */
64#ifndef KEYSTORE_MESSAGE_SIZE
65#define KEYSTORE_MESSAGE_SIZE 65535
66#endif /* KEYSTORE_MESSAGE_SIZE */
67
68 ssize_t len;
69 uint8_t *value = NULL;
70
71 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
72 "keystore command '%c' key '%s' --> keystore_get",
73 cmd, key);
74
75 len = keystore_get(key, strlen(key), &value);
76 if (len < 0) {
77 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
78 "keystore_get() failed");
79 return -1;
80 }
81
82 if (len > KEYSTORE_MESSAGE_SIZE)
83 len = KEYSTORE_MESSAGE_SIZE;
84 memcpy(val, value, len);
85 free(value);
86 return len;
87#else /* ANDROID43 */
88 int s, res, reslen = -1, received;
89 size_t keylen;
90 unsigned char hdr[3];
91
92 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
93 "keystore command '%c' key '%s'", cmd, key);
94 keylen = strlen(key);
95 if (keylen > KEYSTORE_MESSAGE_SIZE)
96 return -1;
97
98 s = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
99 SOCK_STREAM);
100 if (s < 0) {
101 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
102 "could not connect to keystore");
103 return -1;
104 }
105
106 hdr[0] = cmd;
107 hdr[1] = keylen >> 8;
108 hdr[2] = keylen & 0xff;
109
110 if (send(s, hdr, sizeof(hdr), MSG_NOSIGNAL) != sizeof(hdr) ||
111 send(s, key, keylen, MSG_NOSIGNAL) != (int) keylen ||
112 shutdown(s, SHUT_WR) != 0) {
113 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
114 "could not send keystore command");
115 goto fail;
116 }
117
118 if (recv(s, hdr, 1, 0) != 1)
119 goto fail;
120 if (hdr[0] != 1) {
121 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
122 "unexpected keystore response %u", hdr[0]);
123 goto fail;
124 }
125 if (recv(s, hdr + 1, 2, 0) != 2)
126 goto fail;
127 reslen = hdr[1] * 256 + hdr[2];
128 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
129 "keystore response length %d", reslen);
130 if (reslen > KEYSTORE_MESSAGE_SIZE) {
131 reslen = -1;
132 goto fail;
133 }
134
135 received = 0;
136 while (received < reslen) {
137 res = recv(s, val + received, reslen - received, 0);
138 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
139 "keystore recv -> %d", res);
140 if (res <= 0) {
141 reslen = -1;
142 break;
143 }
144 received += res;
145 }
146
147fail:
148 close(s);
149 __android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
150 "keystore get -> %d", reslen);
151 return reslen;
152#endif /* ANDROID43 */
153}
154#endif /* ANDROID */
155
156
157int set_ps(const char *intf, struct sigma_dut *dut, int enabled)
158{
159#ifdef __linux__
160 char buf[100];
161
162 if (wifi_chip_type == DRIVER_WCN) {
163 if (enabled) {
164 snprintf(buf, sizeof(buf), "iwpriv wlan0 dump 906");
165 if (system(buf) != 0) {
166 sigma_dut_print(dut, DUT_MSG_ERROR,
167 "Failed to enable power save");
168 return -1;
169 }
170 } else {
171 snprintf(buf, sizeof(buf), "iwpriv wlan0 dump 905");
172 if (system(buf) != 0) {
173 sigma_dut_print(dut, DUT_MSG_ERROR,
174 "Failed to stop power save timer");
175 return -1;
176 }
177 snprintf(buf, sizeof(buf), "iwpriv wlan0 dump 912");
178 if (system(buf) != 0) {
179 sigma_dut_print(dut, DUT_MSG_ERROR,
180 "Failed to disable power save");
181 return -1;
182 }
183 }
184
185 return 0;
186 }
187
188 snprintf(buf, sizeof(buf), "./iw dev %s set power_save %s",
189 intf, enabled ? "on" : "off");
190 if (system(buf) != 0) {
191 snprintf(buf, sizeof(buf), "iw dev %s set power_save %s",
192 intf, enabled ? "on" : "off");
193 if (system(buf) != 0)
194 return -1;
195 }
196
197 return 0;
198#else /* __linux__ */
199 return -1;
200#endif /* __linux__ */
201}
202
203
204static void static_ip_file(int proto, const char *addr, const char *mask,
205 const char *gw)
206{
207 if (proto) {
208 FILE *f = fopen("static-ip", "w");
209 if (f) {
210 fprintf(f, "%d %s %s %s\n", proto, addr,
211 mask ? mask : "N/A",
212 gw ? gw : "N/A");
213 fclose(f);
214 }
215 } else {
216 unlink("static-ip");
217 }
218}
219
220
221static int send_neighbor_request(struct sigma_dut *dut, const char *intf,
222 const char *ssid)
223{
224#ifdef __linux__
225 char buf[100];
226
227 snprintf(buf, sizeof(buf), "iwpriv %s neighbor %s",
228 intf, ssid);
229 sigma_dut_print(dut, DUT_MSG_INFO, "Request: %s", buf);
230
231 if (system(buf) != 0) {
232 sigma_dut_print(dut, DUT_MSG_ERROR,
233 "iwpriv neighbor request failed");
234 return -1;
235 }
236
237 sigma_dut_print(dut, DUT_MSG_INFO, "iwpriv neighbor request send");
238
239 return 0;
240#else /* __linux__ */
241 return -1;
242#endif /* __linux__ */
243}
244
245
246static int send_trans_mgmt_query(struct sigma_dut *dut, const char *intf,
247 const char *ssid)
248{
249 /*
250 * In the earlier builds we used WNM_QUERY and in later
251 * builds used WNM_BSS_QUERY.
252 */
253
254 if (wpa_command(intf, "WNM_BSS_QUERY 0") != 0) {
255 sigma_dut_print(dut, DUT_MSG_ERROR,
256 "transition management query failed");
257 return -1;
258 }
259
260 sigma_dut_print(dut, DUT_MSG_DEBUG,
261 "transition management query sent");
262
263 return 0;
264}
265
266
267int is_ip_addr(const char *str)
268{
269 const char *pos = str;
270 struct in_addr addr;
271
272 while (*pos) {
273 if (*pos != '.' && (*pos < '0' || *pos > '9'))
274 return 0;
275 pos++;
276 }
277
278 return inet_aton(str, &addr);
279}
280
281
282int is_ipv6_addr(const char *str)
283{
284 struct sockaddr_in6 addr;
285
286 return inet_pton(AF_INET6, str, &(addr.sin6_addr));
287}
288
289
290int get_ip_config(struct sigma_dut *dut, const char *ifname, char *buf,
291 size_t buf_len)
292{
293 char tmp[256], *pos, *pos2;
294 FILE *f;
295 char ip[16], mask[15], dns[16], sec_dns[16];
296 int is_dhcp = 0;
297 int s;
298#ifdef ANDROID
299 char prop[PROPERTY_VALUE_MAX];
300#endif /* ANDROID */
301
302 ip[0] = '\0';
303 mask[0] = '\0';
304 dns[0] = '\0';
305 sec_dns[0] = '\0';
306
307 s = socket(PF_INET, SOCK_DGRAM, 0);
308 if (s >= 0) {
309 struct ifreq ifr;
310 struct sockaddr_in saddr;
311
312 memset(&ifr, 0, sizeof(ifr));
313 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
314 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
315 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
316 "%s IP address: %s",
317 ifname, strerror(errno));
318 } else {
319 memcpy(&saddr, &ifr.ifr_addr,
320 sizeof(struct sockaddr_in));
321 strncpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
322 }
323
324 if (ioctl(s, SIOCGIFNETMASK, &ifr) == 0) {
325 memcpy(&saddr, &ifr.ifr_addr,
326 sizeof(struct sockaddr_in));
327 strncpy(mask, inet_ntoa(saddr.sin_addr), sizeof(mask));
328 }
329 close(s);
330 }
331
332#ifdef ANDROID
333 snprintf(tmp, sizeof(tmp), "dhcp.%s.pid", ifname);
334 if (property_get(tmp, prop, NULL) != 0 && atoi(prop) > 0) {
335 snprintf(tmp, sizeof(tmp), "dhcp.%s.result", ifname);
336 if (property_get(tmp, prop, NULL) != 0 &&
337 strcmp(prop, "ok") == 0) {
338 snprintf(tmp, sizeof(tmp), "dhcp.%s.ipaddress",
339 ifname);
340 if (property_get(tmp, prop, NULL) != 0 &&
341 strcmp(ip, prop) == 0)
342 is_dhcp = 1;
343 }
344 }
345
346 snprintf(tmp, sizeof(tmp), "dhcp.%s.dns1", ifname);
347 if (property_get(tmp, prop, NULL) != 0) {
348 strncpy(dns, prop, sizeof(dns));
349 dns[sizeof(dns) - 1] = '\0';
350 } else {
351 if (property_get("net.dns1", prop, NULL) != 0) {
352 strncpy(dns, prop, sizeof(dns));
353 dns[sizeof(dns) - 1] = '\0';
354 }
355 }
356
357 snprintf(tmp, sizeof(tmp), "dhcp.%s.dns2", ifname);
358 if (property_get(tmp, prop, NULL) != 0) {
359 strncpy(sec_dns, prop, sizeof(sec_dns));
360 sec_dns[sizeof(sec_dns) - 1] = '\0';
361 }
362#else /* ANDROID */
363#ifdef __linux__
364 snprintf(tmp, sizeof(tmp), "ps ax | grep dhclient | grep -v grep | "
365 "grep -q %s", ifname);
366 if (system(tmp) == 0)
367 is_dhcp = 1;
368 else {
369 snprintf(tmp, sizeof(tmp), "ps ax | grep udhcpc | "
370 "grep -v grep | grep -q %s", ifname);
371 if (system(tmp) == 0)
372 is_dhcp = 1;
373 else {
374 snprintf(tmp, sizeof(tmp), "ps ax | grep dhcpcd | "
375 "grep -v grep | grep -q %s", ifname);
376 if (system(tmp) == 0)
377 is_dhcp = 1;
378 }
379 }
380#endif /* __linux__ */
381
382 f = fopen("/etc/resolv.conf", "r");
383 if (f) {
384 while (fgets(tmp, sizeof(tmp), f)) {
385 if (strncmp(tmp, "nameserver", 10) != 0)
386 continue;
387 pos = tmp + 10;
388 while (*pos == ' ' || *pos == '\t')
389 pos++;
390 pos2 = pos;
391 while (*pos2) {
392 if (*pos2 == '\n' || *pos2 == '\r') {
393 *pos2 = '\0';
394 break;
395 }
396 pos2++;
397 }
398 if (!dns[0]) {
399 strncpy(dns, pos, sizeof(dns));
400 dns[sizeof(dns) - 1] = '\0';
401 } else if (!sec_dns[0]) {
402 strncpy(sec_dns, pos, sizeof(sec_dns));
403 sec_dns[sizeof(sec_dns) - 1] = '\0';
404 }
405 }
406 fclose(f);
407 }
408#endif /* ANDROID */
409
410 snprintf(buf, buf_len, "dhcp,%d,ip,%s,mask,%s,primary-dns,%s",
411 is_dhcp, ip, mask, dns);
412 buf[buf_len - 1] = '\0';
413
414 return 0;
415}
416
417
418
419
420int get_ipv6_config(struct sigma_dut *dut, const char *ifname, char *buf,
421 size_t buf_len)
422{
423#ifdef __linux__
424#ifdef ANDROID
425 char cmd[200], result[1000], *pos, *end;
426 FILE *f;
427 size_t len;
428
429 snprintf(cmd, sizeof(cmd), "ip addr show dev %s scope global", ifname);
430 f = popen(cmd, "r");
431 if (f == NULL)
432 return -1;
433 len = fread(result, 1, sizeof(result) - 1, f);
434 pclose(f);
435 if (len == 0)
436 return -1;
437 result[len] = '\0';
438 sigma_dut_print(dut, DUT_MSG_DEBUG, "%s result: %s\n", cmd, result);
439
440 pos = strstr(result, "inet6 ");
441 if (pos == NULL)
442 return -1;
443 pos += 6;
444 end = strchr(pos, ' ');
445 if (end)
446 *end = '\0';
447 end = strchr(pos, '/');
448 if (end)
449 *end = '\0';
450 snprintf(buf, buf_len, "ip,%s", pos);
451 buf[buf_len - 1] = '\0';
452 return 0;
453#else /* ANDROID */
454 struct ifaddrs *ifaddr, *ifa;
455 int res, found = 0;
456 char host[NI_MAXHOST];
457
458 if (getifaddrs(&ifaddr) < 0) {
459 perror("getifaddrs");
460 return -1;
461 }
462
463 for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
464 if (strcasecmp(ifname, ifa->ifa_name) != 0)
465 continue;
466 if (ifa->ifa_addr == NULL ||
467 ifa->ifa_addr->sa_family != AF_INET6)
468 continue;
469
470 res = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
471 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
472 if (res != 0) {
473 sigma_dut_print(dut, DUT_MSG_DEBUG, "getnameinfo: %s",
474 gai_strerror(res));
475 continue;
476 }
477 if (strncmp(host, "fe80::", 6) == 0)
478 continue; /* skip link-local */
479
480 sigma_dut_print(dut, DUT_MSG_DEBUG, "ifaddr: %s", host);
481 found = 1;
482 break;
483 }
484
485 freeifaddrs(ifaddr);
486
487 if (found) {
488 char *pos;
489 pos = strchr(host, '%');
490 if (pos)
491 *pos = '\0';
492 snprintf(buf, buf_len, "ip,%s", host);
493 buf[buf_len - 1] = '\0';
494 return 0;
495 }
496
497#endif /* ANDROID */
498#endif /* __linux__ */
499 return -1;
500}
501
502
503static int cmd_sta_get_ip_config(struct sigma_dut *dut,
504 struct sigma_conn *conn,
505 struct sigma_cmd *cmd)
506{
507 const char *intf = get_param(cmd, "Interface");
508 const char *ifname;
509 char buf[200];
510 const char *val;
511 int type = 1;
512
513 if (intf == NULL)
514 return -1;
515
516 if (strcmp(intf, get_main_ifname()) == 0)
517 ifname = get_station_ifname();
518 else
519 ifname = intf;
520
521 /*
522 * UCC may assume the IP address to be available immediately after
523 * association without trying to run sta_get_ip_config multiple times.
524 * Sigma CAPI does not specify this command as a block command that
525 * would wait for the address to become available, but to pass tests
526 * more reliably, it looks like such a wait may be needed here.
527 */
528 if (wait_ip_addr(dut, ifname, 15) < 0) {
529 sigma_dut_print(dut, DUT_MSG_INFO, "Could not get IP address "
530 "for sta_get_ip_config");
531 /*
532 * Try to continue anyway since many UCC tests do not really
533 * care about the return value from here..
534 */
535 }
536
537 val = get_param(cmd, "Type");
538 if (val)
539 type = atoi(val);
540 if (type == 2 || dut->last_set_ip_config_ipv6) {
541 int i;
542
543 /*
544 * Since we do not have proper wait for IPv6 addresses, use a
545 * fixed two second delay here as a workaround for UCC script
546 * assuming IPv6 address is available when this command returns.
547 * Some scripts did not use Type,2 properly for IPv6, so include
548 * also the cases where the previous sta_set_ip_config indicated
549 * use of IPv6.
550 */
551 sigma_dut_print(dut, DUT_MSG_INFO, "Wait up to extra ten seconds in sta_get_ip_config for IPv6 address");
552 for (i = 0; i < 10; i++) {
553 sleep(1);
554 if (get_ipv6_config(dut, ifname, buf, sizeof(buf)) == 0)
555 {
556 sigma_dut_print(dut, DUT_MSG_INFO, "Found IPv6 address");
557 send_resp(dut, conn, SIGMA_COMPLETE, buf);
558#ifdef ANDROID
559 sigma_dut_print(dut, DUT_MSG_INFO,
560 "Adding IPv6 rule on Android");
561 add_ipv6_rule(dut, intf);
562#endif /* ANDROID */
563
564 return 0;
565 }
566 }
567 }
568 if (type == 1) {
569 if (get_ip_config(dut, ifname, buf, sizeof(buf)) < 0)
570 return -2;
571 } else if (type == 2) {
572 if (get_ipv6_config(dut, ifname, buf, sizeof(buf)) < 0)
573 return -2;
574 } else {
575 send_resp(dut, conn, SIGMA_ERROR,
576 "errorCode,Unsupported address type");
577 return 0;
578 }
579
580 send_resp(dut, conn, SIGMA_COMPLETE, buf);
581 return 0;
582}
583
584
585static void kill_dhcp_client(struct sigma_dut *dut, const char *ifname)
586{
587#ifdef __linux__
588 char buf[200];
589 char path[128];
590 struct stat s;
591
592#ifdef ANDROID
593 snprintf(path, sizeof(path), "/data/misc/dhcp/dhcpcd-%s.pid", ifname);
594#else /* ANDROID */
595 snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid", ifname);
596#endif /* ANDROID */
597 if (stat(path, &s) == 0) {
598 snprintf(buf, sizeof(buf), "kill `cat %s`", path);
599 sigma_dut_print(dut, DUT_MSG_INFO,
600 "Kill previous DHCP client: %s", buf);
601 if (system(buf) != 0)
602 sigma_dut_print(dut, DUT_MSG_INFO,
603 "Failed to kill DHCP client");
604 unlink(path);
605 sleep(1);
606 } else {
607 snprintf(path, sizeof(path), "/var/run/dhcpcd-%s.pid", ifname);
608
609 if (stat(path, &s) == 0) {
610 snprintf(buf, sizeof(buf), "kill `cat %s`", path);
611 sigma_dut_print(dut, DUT_MSG_INFO,
612 "Kill previous DHCP client: %s", buf);
613 if (system(buf) != 0)
614 sigma_dut_print(dut, DUT_MSG_INFO,
615 "Failed to kill DHCP client");
616 unlink(path);
617 sleep(1);
618 }
619 }
620#endif /* __linux__ */
621}
622
623
624static int start_dhcp_client(struct sigma_dut *dut, const char *ifname)
625{
626#ifdef __linux__
627 char buf[200];
628
629#ifdef ANDROID
630 snprintf(buf, sizeof(buf),
631 "/system/bin/dhcpcd -b %s", ifname);
632#else /* ANDROID */
633 snprintf(buf, sizeof(buf),
634 "dhclient -nw -pf /var/run/dhclient-%s.pid %s",
635 ifname, ifname);
636#endif /* ANDROID */
637 sigma_dut_print(dut, DUT_MSG_INFO, "Start DHCP client: %s", buf);
638 if (system(buf) != 0) {
639 snprintf(buf, sizeof(buf), "dhcpcd -t 0 %s &", ifname);
640 if (system(buf) != 0) {
641 sigma_dut_print(dut, DUT_MSG_INFO,
642 "Failed to start DHCP client");
643#ifndef ANDROID
644 return -1;
645#endif /* ANDROID */
646 }
647 }
648#endif /* __linux__ */
649
650 return 0;
651}
652
653
654static int clear_ip_addr(struct sigma_dut *dut, const char *ifname)
655{
656#ifdef __linux__
657 char buf[200];
658
659 snprintf(buf, sizeof(buf), "ip addr flush dev %s", ifname);
660 if (system(buf) != 0) {
661 sigma_dut_print(dut, DUT_MSG_INFO,
662 "Failed to clear IP addresses");
663 return -1;
664 }
665#endif /* __linux__ */
666
667 return 0;
668}
669
670
671#ifdef ANDROID
672static int add_ipv6_rule(struct sigma_dut *dut, const char *ifname)
673{
674 char cmd[200], *result, *pos;
675 FILE *fp;
676 int len, tableid, result_len = 1000;
677
678 snprintf(cmd, sizeof(cmd), "ip -6 route list table all | grep %s",
679 ifname);
680 fp = popen(cmd, "r");
681 if (fp == NULL)
682 return -1;
683
684 result = malloc(result_len);
685 if (result == NULL)
686 return -1;
687
688 len = fread(result, 1, result_len, fp);
689 fclose(fp);
690
691 if (len == 0) {
692 free(result);
693 return -1;
694 }
695
696 pos = strstr(result, "table ");
697 if (pos == NULL) {
698 free(result);
699 return -1;
700 }
701
702 pos += strlen("table ");
703 tableid = atoi(pos);
704 if (tableid != 0) {
705 if (system("ip -6 rule del prio 22000") != 0) {
706 /* ignore any error */
707 }
708 snprintf(cmd, sizeof(cmd),
709 "ip -6 rule add from all lookup %d prio 22000",
710 tableid);
711 if (system(cmd) != 0) {
712 sigma_dut_print(dut, DUT_MSG_INFO,
713 "Failed to run %s", cmd);
714 free(result);
715 return -1;
716 }
717 } else {
718 sigma_dut_print(dut, DUT_MSG_INFO,
719 "No Valid Table Id found %s", pos);
720 free(result);
721 return -1;
722 }
723 free(result);
724
725 return 0;
726}
727#endif /* ANDROID */
728
729
730static int cmd_sta_set_ip_config(struct sigma_dut *dut,
731 struct sigma_conn *conn,
732 struct sigma_cmd *cmd)
733{
734 const char *intf = get_param(cmd, "Interface");
735 const char *ifname;
736 char buf[200];
737 const char *val, *ip, *mask, *gw;
738 int type = 1;
739
740 if (intf == NULL)
741 return -1;
742
743 if (strcmp(intf, get_main_ifname()) == 0)
744 ifname = get_station_ifname();
745 else
746 ifname = intf;
747
748 if (if_nametoindex(ifname) == 0) {
749 send_resp(dut, conn, SIGMA_ERROR,
750 "ErrorCode,Unknown interface");
751 return 0;
752 }
753
754 val = get_param(cmd, "Type");
755 if (val) {
756 type = atoi(val);
757 if (type != 1 && type != 2) {
758 send_resp(dut, conn, SIGMA_ERROR,
759 "ErrorCode,Unsupported address type");
760 return 0;
761 }
762 }
763
764 dut->last_set_ip_config_ipv6 = 0;
765
766 val = get_param(cmd, "dhcp");
767 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "true") == 0)) {
768 static_ip_file(0, NULL, NULL, NULL);
769#ifdef __linux__
770 if (type == 2) {
771 dut->last_set_ip_config_ipv6 = 1;
772 sigma_dut_print(dut, DUT_MSG_INFO, "Using IPv6 "
773 "stateless address autoconfiguration");
774#ifdef ANDROID
775 /*
776 * This sleep is required as the assignment in case of
777 * Android is taking time and is done by the kernel.
778 * The subsequent ping for IPv6 is impacting HS20 test
779 * case.
780 */
781 sleep(2);
782 add_ipv6_rule(dut, intf);
783#endif /* ANDROID */
784 /* Assume this happens by default */
785 return 1;
786 }
787
788 kill_dhcp_client(dut, ifname);
789 if (start_dhcp_client(dut, ifname) < 0)
790 return -2;
791 return 1;
792#endif /* __linux__ */
793 return -2;
794 }
795
796 ip = get_param(cmd, "ip");
797 mask = get_param(cmd, "mask");
798
799 if (type == 2) {
800 int net = atoi(mask);
801
802 if ((net < 0 && net > 64) || !is_ipv6_addr(ip))
803 return -1;
804
805 if (dut->no_ip_addr_set) {
806 snprintf(buf, sizeof(buf),
807 "sysctl net.ipv6.conf.%s.disable_ipv6=1",
808 ifname);
809 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
810 if (system(buf) != 0) {
811 sigma_dut_print(dut, DUT_MSG_DEBUG,
812 "Failed to disable IPv6 address before association");
813 }
814 } else {
815 snprintf(buf, sizeof(buf),
816 "ip -6 addr del %s/%s dev %s",
817 ip, mask, ifname);
818 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
819 if (system(buf) != 0) {
820 /*
821 * This command may fail if the address being
822 * deleted does not exist. Inaction here is
823 * intentional.
824 */
825 }
826
827 snprintf(buf, sizeof(buf),
828 "ip -6 addr add %s/%s dev %s",
829 ip, mask, ifname);
830 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
831 if (system(buf) != 0) {
832 send_resp(dut, conn, SIGMA_ERROR,
833 "ErrorCode,Failed to set IPv6 address");
834 return 0;
835 }
836 }
837
838 dut->last_set_ip_config_ipv6 = 1;
839 static_ip_file(6, ip, mask, NULL);
840 return 1;
841 } else if (type == 1) {
842 if (ip == NULL || !is_ip_addr(ip) ||
843 mask == NULL || !is_ip_addr(mask))
844 return -1;
845 }
846
847 kill_dhcp_client(dut, ifname);
848
849 if (!dut->no_ip_addr_set) {
850 snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s",
851 ifname, ip, mask);
852 if (system(buf) != 0) {
853 send_resp(dut, conn, SIGMA_ERROR,
854 "ErrorCode,Failed to set IP address");
855 return 0;
856 }
857 }
858
859 gw = get_param(cmd, "defaultGateway");
860 if (gw) {
861 if (!is_ip_addr(gw))
862 return -1;
863 snprintf(buf, sizeof(buf), "route add default gw %s", gw);
864 if (!dut->no_ip_addr_set && system(buf) != 0) {
865 snprintf(buf, sizeof(buf), "ip ro re default via %s",
866 gw);
867 if (system(buf) != 0) {
868 send_resp(dut, conn, SIGMA_ERROR,
869 "ErrorCode,Failed "
870 "to set default gateway");
871 return 0;
872 }
873 }
874 }
875
876 val = get_param(cmd, "primary-dns");
877 if (val) {
878 /* TODO */
879 sigma_dut_print(dut, DUT_MSG_INFO, "Ignored primary-dns %s "
880 "setting", val);
881 }
882
883 val = get_param(cmd, "secondary-dns");
884 if (val) {
885 /* TODO */
886 sigma_dut_print(dut, DUT_MSG_INFO, "Ignored secondary-dns %s "
887 "setting", val);
888 }
889
890 static_ip_file(4, ip, mask, gw);
891
892 return 1;
893}
894
895
896static int cmd_sta_get_info(struct sigma_dut *dut, struct sigma_conn *conn,
897 struct sigma_cmd *cmd)
898{
899 /* const char *intf = get_param(cmd, "Interface"); */
900 /* TODO: could report more details here */
901 send_resp(dut, conn, SIGMA_COMPLETE, "vendor,Atheros");
902 return 0;
903}
904
905
906static int cmd_sta_get_mac_address(struct sigma_dut *dut,
907 struct sigma_conn *conn,
908 struct sigma_cmd *cmd)
909{
910 /* const char *intf = get_param(cmd, "Interface"); */
911 char addr[20], resp[50];
912
913 if (get_wpa_status(get_station_ifname(), "address", addr, sizeof(addr))
914 < 0)
915 return -2;
916
917 snprintf(resp, sizeof(resp), "mac,%s", addr);
918 send_resp(dut, conn, SIGMA_COMPLETE, resp);
919 return 0;
920}
921
922
923static int cmd_sta_is_connected(struct sigma_dut *dut, struct sigma_conn *conn,
924 struct sigma_cmd *cmd)
925{
926 /* const char *intf = get_param(cmd, "Interface"); */
927 int connected = 0;
928 char result[32];
929 if (get_wpa_status(get_station_ifname(), "wpa_state", result,
930 sizeof(result)) < 0) {
931 sigma_dut_print(dut, DUT_MSG_INFO, "Could not get interface "
932 "%s status", get_station_ifname());
933 return -2;
934 }
935
936 sigma_dut_print(dut, DUT_MSG_DEBUG, "wpa_state=%s", result);
937 if (strncmp(result, "COMPLETED", 9) == 0)
938 connected = 1;
939
940 if (connected)
941 send_resp(dut, conn, SIGMA_COMPLETE, "connected,1");
942 else
943 send_resp(dut, conn, SIGMA_COMPLETE, "connected,0");
944
945 return 0;
946}
947
948
949static int cmd_sta_verify_ip_connection(struct sigma_dut *dut,
950 struct sigma_conn *conn,
951 struct sigma_cmd *cmd)
952{
953 /* const char *intf = get_param(cmd, "Interface"); */
954 const char *dst, *timeout;
955 int wait_time = 90;
956 char buf[100];
957 int res;
958
959 dst = get_param(cmd, "destination");
960 if (dst == NULL || !is_ip_addr(dst))
961 return -1;
962
963 timeout = get_param(cmd, "timeout");
964 if (timeout) {
965 wait_time = atoi(timeout);
966 if (wait_time < 1)
967 wait_time = 1;
968 }
969
970 /* TODO: force renewal of IP lease if DHCP is enabled */
971
972 snprintf(buf, sizeof(buf), "ping %s -c 3 -W %d", dst, wait_time);
973 res = system(buf);
974 sigma_dut_print(dut, DUT_MSG_DEBUG, "ping returned: %d", res);
975 if (res == 0)
976 send_resp(dut, conn, SIGMA_COMPLETE, "connected,1");
977 else if (res == 256)
978 send_resp(dut, conn, SIGMA_COMPLETE, "connected,0");
979 else
980 return -2;
981
982 return 0;
983}
984
985
986static int cmd_sta_get_bssid(struct sigma_dut *dut, struct sigma_conn *conn,
987 struct sigma_cmd *cmd)
988{
989 /* const char *intf = get_param(cmd, "Interface"); */
990 char bssid[20], resp[50];
991
992 if (get_wpa_status(get_station_ifname(), "bssid", bssid, sizeof(bssid))
993 < 0)
994 strncpy(bssid, "00:00:00:00:00:00", sizeof(bssid));
995
996 snprintf(resp, sizeof(resp), "bssid,%s", bssid);
997 send_resp(dut, conn, SIGMA_COMPLETE, resp);
998 return 0;
999}
1000
1001
1002#ifdef __SAMSUNG__
1003static int add_use_network(const char *ifname)
1004{
1005 char buf[100];
1006
1007 snprintf(buf, sizeof(buf), "USE_NETWORK ON");
1008 wpa_command(ifname, buf);
1009 return 0;
1010}
1011#endif /* __SAMSUNG__ */
1012
1013
1014static int add_network_common(struct sigma_dut *dut, struct sigma_conn *conn,
1015 const char *ifname, struct sigma_cmd *cmd)
1016{
1017 const char *ssid = get_param(cmd, "ssid");
1018 int id;
1019 const char *val;
1020
1021 if (ssid == NULL)
1022 return -1;
1023
1024 start_sta_mode(dut);
1025
1026#ifdef __SAMSUNG__
1027 add_use_network(ifname);
1028#endif /* __SAMSUNG__ */
1029
1030 id = add_network(ifname);
1031 if (id < 0)
1032 return -2;
1033 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding network %d", id);
1034
1035 if (set_network_quoted(ifname, id, "ssid", ssid) < 0)
1036 return -2;
1037
1038 dut->infra_network_id = id;
1039 snprintf(dut->infra_ssid, sizeof(dut->infra_ssid), "%s", ssid);
1040
1041 val = get_param(cmd, "program");
1042 if (!val)
1043 val = get_param(cmd, "prog");
1044 if (val && strcasecmp(val, "hs2") == 0) {
1045 char buf[100];
1046 snprintf(buf, sizeof(buf), "ENABLE_NETWORK %d no-connect", id);
1047 wpa_command(ifname, buf);
1048
1049 val = get_param(cmd, "prefer");
1050 if (val && atoi(val) > 0)
1051 set_network(ifname, id, "priority", "1");
1052 }
1053
1054 return id;
1055}
1056
1057
1058static int cmd_sta_set_encryption(struct sigma_dut *dut,
1059 struct sigma_conn *conn,
1060 struct sigma_cmd *cmd)
1061{
1062 const char *intf = get_param(cmd, "Interface");
1063 const char *ssid = get_param(cmd, "ssid");
1064 const char *type = get_param(cmd, "encpType");
1065 const char *ifname;
1066 char buf[200];
1067 int id;
1068
1069 if (intf == NULL || ssid == NULL)
1070 return -1;
1071
1072 if (strcmp(intf, get_main_ifname()) == 0)
1073 ifname = get_station_ifname();
1074 else
1075 ifname = intf;
1076
1077 id = add_network_common(dut, conn, ifname, cmd);
1078 if (id < 0)
1079 return id;
1080
1081 if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
1082 return -2;
1083
1084 if (type && strcasecmp(type, "wep") == 0) {
1085 const char *val;
1086 int i;
1087
1088 val = get_param(cmd, "activeKey");
1089 if (val) {
1090 int keyid;
1091 keyid = atoi(val);
1092 if (keyid < 1 || keyid > 4)
1093 return -1;
1094 snprintf(buf, sizeof(buf), "%d", keyid - 1);
1095 if (set_network(ifname, id, "wep_tx_keyidx", buf) < 0)
1096 return -2;
1097 }
1098
1099 for (i = 0; i < 4; i++) {
1100 snprintf(buf, sizeof(buf), "key%d", i + 1);
1101 val = get_param(cmd, buf);
1102 if (val == NULL)
1103 continue;
1104 snprintf(buf, sizeof(buf), "wep_key%d", i);
1105 if (set_network(ifname, id, buf, val) < 0)
1106 return -2;
1107 }
1108 }
1109
1110 return 1;
1111}
1112
1113
1114static int set_wpa_common(struct sigma_dut *dut, struct sigma_conn *conn,
1115 const char *ifname, struct sigma_cmd *cmd)
1116{
1117 const char *val;
1118 int id;
1119
1120 id = add_network_common(dut, conn, ifname, cmd);
1121 if (id < 0)
1122 return id;
1123
1124 val = get_param(cmd, "keyMgmtType");
1125 if (val == NULL) {
1126 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Missing keyMgmtType");
1127 return 0;
1128 }
1129 if (strcasecmp(val, "wpa") == 0 ||
1130 strcasecmp(val, "wpa-psk") == 0) {
1131 if (set_network(ifname, id, "proto", "WPA") < 0)
1132 return -2;
1133 } else if (strcasecmp(val, "wpa2") == 0 ||
1134 strcasecmp(val, "wpa2-psk") == 0 ||
1135 strcasecmp(val, "wpa2-ft") == 0 ||
1136 strcasecmp(val, "wpa2-sha256") == 0) {
1137 if (set_network(ifname, id, "proto", "WPA2") < 0)
1138 return -2;
1139 } else if (strcasecmp(val, "wpa2-wpa-psk") == 0) {
1140 if (set_network(ifname, id, "proto", "WPA WPA2") < 0)
1141 return -2;
1142 } else {
1143 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized keyMgmtType value");
1144 return 0;
1145 }
1146
1147 val = get_param(cmd, "encpType");
1148 if (val == NULL) {
1149 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Missing encpType");
1150 return 0;
1151 }
1152 if (strcasecmp(val, "tkip") == 0) {
1153 if (set_network(ifname, id, "pairwise", "TKIP") < 0)
1154 return -2;
1155 } else if (strcasecmp(val, "aes-ccmp") == 0) {
1156 if (set_network(ifname, id, "pairwise", "CCMP") < 0)
1157 return -2;
1158 } else if (strcasecmp(val, "aes-ccmp-tkip") == 0) {
1159 if (set_network(ifname, id, "pairwise", "CCMP TKIP") < 0)
1160 return -2;
1161 } else if (strcasecmp(val, "aes-gcmp") == 0) {
1162 if (set_network(ifname, id, "pairwise", "GCMP") < 0)
1163 return -2;
1164 if (set_network(ifname, id, "group", "GCMP") < 0)
1165 return -2;
1166 } else {
1167 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized encpType value");
1168 return 0;
1169 }
1170
1171 dut->sta_pmf = STA_PMF_DISABLED;
1172 val = get_param(cmd, "PMF");
1173 if (val) {
1174 if (strcasecmp(val, "Required") == 0 ||
1175 strcasecmp(val, "Forced_Required") == 0) {
1176 dut->sta_pmf = STA_PMF_REQUIRED;
1177 if (set_network(ifname, id, "ieee80211w", "2") < 0)
1178 return -2;
1179 } else if (strcasecmp(val, "Optional") == 0) {
1180 dut->sta_pmf = STA_PMF_OPTIONAL;
1181 if (set_network(ifname, id, "ieee80211w", "1") < 0)
1182 return -2;
1183 } else if (strcasecmp(val, "Disabled") == 0 ||
1184 strcasecmp(val, "Forced_Disabled") == 0) {
1185 dut->sta_pmf = STA_PMF_DISABLED;
1186 } else {
1187 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized PMF value");
1188 return 0;
1189 }
1190 }
1191
1192 return id;
1193}
1194
1195
1196static int cmd_sta_set_psk(struct sigma_dut *dut, struct sigma_conn *conn,
1197 struct sigma_cmd *cmd)
1198{
1199 const char *intf = get_param(cmd, "Interface");
1200 const char *ifname, *val, *alg;
1201 int id;
1202
1203 if (intf == NULL)
1204 return -1;
1205
1206 if (strcmp(intf, get_main_ifname()) == 0)
1207 ifname = get_station_ifname();
1208 else
1209 ifname = intf;
1210
1211 id = set_wpa_common(dut, conn, ifname, cmd);
1212 if (id < 0)
1213 return id;
1214
1215 val = get_param(cmd, "keyMgmtType");
1216 alg = get_param(cmd, "micAlg");
1217
1218 if (alg && strcasecmp(alg, "SHA-256") == 0) {
1219 if (set_network(ifname, id, "key_mgmt", "WPA-PSK-SHA256") < 0)
1220 return -2;
1221 } else if (alg && strcasecmp(alg, "SHA-1") == 0) {
1222 if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
1223 return -2;
1224 } else if ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
1225 dut->sta_pmf == STA_PMF_REQUIRED) {
1226 if (set_network(ifname, id, "key_mgmt",
1227 "WPA-PSK WPA-PSK-SHA256") < 0)
1228 return -2;
1229 } else if (dut->sta_pmf == STA_PMF_OPTIONAL) {
1230 if (set_network(ifname, id, "key_mgmt",
1231 "WPA-PSK WPA-PSK-SHA256") < 0)
1232 return -2;
1233 } else {
1234 if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
1235 return -2;
1236 }
1237
1238 val = get_param(cmd, "passPhrase");
1239 if (val == NULL)
1240 return -1;
1241 if (set_network_quoted(ifname, id, "psk", val) < 0)
1242 return -2;
1243
1244 return 1;
1245}
1246
1247
1248static int set_eap_common(struct sigma_dut *dut, struct sigma_conn *conn,
1249 const char *ifname, struct sigma_cmd *cmd)
1250{
1251 const char *val, *alg;
1252 int id;
1253 char buf[200];
1254#ifdef ANDROID
1255 unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
1256 int length;
1257#endif /* ANDROID */
1258
1259 id = set_wpa_common(dut, conn, ifname, cmd);
1260 if (id < 0)
1261 return id;
1262
1263 val = get_param(cmd, "keyMgmtType");
1264 alg = get_param(cmd, "micAlg");
1265
1266 if (alg && strcasecmp(alg, "SHA-256") == 0) {
1267 if (set_network(ifname, id, "key_mgmt", "WPA-EAP-SHA256") < 0)
1268 return -2;
1269 } else if (alg && strcasecmp(alg, "SHA-1") == 0) {
1270 if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
1271 return -2;
1272 } else if (val && strcasecmp(val, "wpa2-ft") == 0) {
1273 if (set_network(ifname, id, "key_mgmt", "FT-EAP") < 0)
1274 return -2;
1275 } else if ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
1276 dut->sta_pmf == STA_PMF_REQUIRED) {
1277 if (set_network(ifname, id, "key_mgmt",
1278 "WPA-EAP WPA-EAP-SHA256") < 0)
1279 return -2;
1280 } else if (dut->sta_pmf == STA_PMF_OPTIONAL) {
1281 if (set_network(ifname, id, "key_mgmt",
1282 "WPA-EAP WPA-EAP-SHA256") < 0)
1283 return -2;
1284 } else {
1285 if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
1286 return -2;
1287 }
1288
1289 val = get_param(cmd, "trustedRootCA");
1290 if (val) {
1291#ifdef ANDROID
1292 snprintf(buf, sizeof(buf), "CACERT_%s", val);
1293 length = android_keystore_get(ANDROID_KEYSTORE_GET, buf,
1294 kvalue);
1295 if (length > 0) {
1296 sigma_dut_print(dut, DUT_MSG_INFO,
1297 "Use Android keystore [%s]", buf);
1298 snprintf(buf, sizeof(buf), "keystore://CACERT_%s",
1299 val);
1300 goto ca_cert_selected;
1301 }
1302#endif /* ANDROID */
1303
1304 snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
1305#ifdef __linux__
1306 if (!file_exists(buf)) {
1307 char msg[300];
1308 snprintf(msg, sizeof(msg), "ErrorCode,trustedRootCA "
1309 "file (%s) not found", buf);
1310 send_resp(dut, conn, SIGMA_ERROR, msg);
1311 return -3;
1312 }
1313#endif /* __linux__ */
1314#ifdef ANDROID
1315ca_cert_selected:
1316#endif /* ANDROID */
1317 if (set_network_quoted(ifname, id, "ca_cert", buf) < 0)
1318 return -2;
1319 }
1320
1321 val = get_param(cmd, "username");
1322 if (val) {
1323 if (set_network_quoted(ifname, id, "identity", val) < 0)
1324 return -2;
1325 }
1326
1327 val = get_param(cmd, "password");
1328 if (val) {
1329 if (set_network_quoted(ifname, id, "password", val) < 0)
1330 return -2;
1331 }
1332
1333 return id;
1334}
1335
1336
1337static int cmd_sta_set_eaptls(struct sigma_dut *dut, struct sigma_conn *conn,
1338 struct sigma_cmd *cmd)
1339{
1340 const char *intf = get_param(cmd, "Interface");
1341 const char *ifname, *val;
1342 int id;
1343 char buf[200];
1344#ifdef ANDROID
1345 unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
1346 int length;
1347 int jb_or_newer = 0;
1348 char prop[PROPERTY_VALUE_MAX];
1349#endif /* ANDROID */
1350
1351 if (intf == NULL)
1352 return -1;
1353
1354 if (strcmp(intf, get_main_ifname()) == 0)
1355 ifname = get_station_ifname();
1356 else
1357 ifname = intf;
1358
1359 id = set_eap_common(dut, conn, ifname, cmd);
1360 if (id < 0)
1361 return id;
1362
1363 if (set_network(ifname, id, "eap", "TLS") < 0)
1364 return -2;
1365
1366 if (set_network_quoted(ifname, id, "identity",
1367 "wifi-user@wifilabs.local") < 0)
1368 return -2;
1369
1370 val = get_param(cmd, "clientCertificate");
1371 if (val == NULL)
1372 return -1;
1373#ifdef ANDROID
1374 snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
1375 length = android_keystore_get(ANDROID_KEYSTORE_GET, buf, kvalue);
1376 if (length < 0) {
1377 /*
1378 * JB started reporting keystore type mismatches, so retry with
1379 * the GET_PUBKEY command if the generic GET fails.
1380 */
1381 length = android_keystore_get(ANDROID_KEYSTORE_GET_PUBKEY,
1382 buf, kvalue);
1383 }
1384
1385 if (property_get("ro.build.version.release", prop, NULL) != 0) {
1386 sigma_dut_print(dut, DUT_MSG_DEBUG, "Android release %s", prop);
1387 if (strncmp(prop, "4.0", 3) != 0)
1388 jb_or_newer = 1;
1389 } else
1390 jb_or_newer = 1; /* assume newer */
1391
1392 if (jb_or_newer && length > 0) {
1393 sigma_dut_print(dut, DUT_MSG_INFO,
1394 "Use Android keystore [%s]", buf);
1395 if (set_network(ifname, id, "engine", "1") < 0)
1396 return -2;
1397 if (set_network_quoted(ifname, id, "engine_id", "keystore") < 0)
1398 return -2;
1399 snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
1400 if (set_network_quoted(ifname, id, "key_id", buf) < 0)
1401 return -2;
1402 snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
1403 if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
1404 return -2;
1405 return 1;
1406 } else if (length > 0) {
1407 sigma_dut_print(dut, DUT_MSG_INFO,
1408 "Use Android keystore [%s]", buf);
1409 snprintf(buf, sizeof(buf), "keystore://USRPKEY_%s", val);
1410 if (set_network_quoted(ifname, id, "private_key", buf) < 0)
1411 return -2;
1412 snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
1413 if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
1414 return -2;
1415 return 1;
1416 }
1417#endif /* ANDROID */
1418
1419 snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
1420#ifdef __linux__
1421 if (!file_exists(buf)) {
1422 char msg[300];
1423 snprintf(msg, sizeof(msg), "ErrorCode,clientCertificate file "
1424 "(%s) not found", buf);
1425 send_resp(dut, conn, SIGMA_ERROR, msg);
1426 return -3;
1427 }
1428#endif /* __linux__ */
1429 if (set_network_quoted(ifname, id, "private_key", buf) < 0)
1430 return -2;
1431 if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
1432 return -2;
1433
1434 if (set_network_quoted(ifname, id, "private_key_passwd", "wifi") < 0)
1435 return -2;
1436
1437 return 1;
1438}
1439
1440
1441static int cmd_sta_set_eapttls(struct sigma_dut *dut, struct sigma_conn *conn,
1442 struct sigma_cmd *cmd)
1443{
1444 const char *intf = get_param(cmd, "Interface");
1445 const char *ifname;
1446 int id;
1447
1448 if (intf == NULL)
1449 return -1;
1450
1451 if (strcmp(intf, get_main_ifname()) == 0)
1452 ifname = get_station_ifname();
1453 else
1454 ifname = intf;
1455
1456 id = set_eap_common(dut, conn, ifname, cmd);
1457 if (id < 0)
1458 return id;
1459
1460 if (set_network(ifname, id, "eap", "TTLS") < 0) {
1461 send_resp(dut, conn, SIGMA_ERROR,
1462 "errorCode,Failed to set TTLS method");
1463 return 0;
1464 }
1465
1466 if (set_network_quoted(ifname, id, "phase2", "auth=MSCHAPV2") < 0) {
1467 send_resp(dut, conn, SIGMA_ERROR,
1468 "errorCode,Failed to set MSCHAPv2 for TTLS Phase 2");
1469 return 0;
1470 }
1471
1472 return 1;
1473}
1474
1475
1476static int cmd_sta_set_eapsim(struct sigma_dut *dut, struct sigma_conn *conn,
1477 struct sigma_cmd *cmd)
1478{
1479 const char *intf = get_param(cmd, "Interface");
1480 const char *ifname;
1481 int id;
1482
1483 if (intf == NULL)
1484 return -1;
1485
1486 if (strcmp(intf, get_main_ifname()) == 0)
1487 ifname = get_station_ifname();
1488 else
1489 ifname = intf;
1490
1491 id = set_eap_common(dut, conn, ifname, cmd);
1492 if (id < 0)
1493 return id;
1494
1495 if (set_network(ifname, id, "eap", "SIM") < 0)
1496 return -2;
1497
1498 return 1;
1499}
1500
1501
1502static int cmd_sta_set_peap(struct sigma_dut *dut, struct sigma_conn *conn,
1503 struct sigma_cmd *cmd)
1504{
1505 const char *intf = get_param(cmd, "Interface");
1506 const char *ifname, *val;
1507 int id;
1508 char buf[100];
1509
1510 if (intf == NULL)
1511 return -1;
1512
1513 if (strcmp(intf, get_main_ifname()) == 0)
1514 ifname = get_station_ifname();
1515 else
1516 ifname = intf;
1517
1518 id = set_eap_common(dut, conn, ifname, cmd);
1519 if (id < 0)
1520 return id;
1521
1522 if (set_network(ifname, id, "eap", "PEAP") < 0)
1523 return -2;
1524
1525 val = get_param(cmd, "innerEAP");
1526 if (val) {
1527 if (strcasecmp(val, "MSCHAPv2") == 0) {
1528 if (set_network_quoted(ifname, id, "phase2",
1529 "auth=MSCHAPV2") < 0)
1530 return -2;
1531 } else if (strcasecmp(val, "GTC") == 0) {
1532 if (set_network_quoted(ifname, id, "phase2",
1533 "auth=GTC") < 0)
1534 return -2;
1535 } else
1536 return -1;
1537 }
1538
1539 val = get_param(cmd, "peapVersion");
1540 if (val) {
1541 int ver = atoi(val);
1542 if (ver < 0 || ver > 1)
1543 return -1;
1544 snprintf(buf, sizeof(buf), "peapver=%d", ver);
1545 if (set_network_quoted(ifname, id, "phase1", buf) < 0)
1546 return -2;
1547 }
1548
1549 return 1;
1550}
1551
1552
1553static int cmd_sta_set_eapfast(struct sigma_dut *dut, struct sigma_conn *conn,
1554 struct sigma_cmd *cmd)
1555{
1556 const char *intf = get_param(cmd, "Interface");
1557 const char *ifname, *val;
1558 int id;
1559 char buf[100];
1560
1561 if (intf == NULL)
1562 return -1;
1563
1564 if (strcmp(intf, get_main_ifname()) == 0)
1565 ifname = get_station_ifname();
1566 else
1567 ifname = intf;
1568
1569 id = set_eap_common(dut, conn, ifname, cmd);
1570 if (id < 0)
1571 return id;
1572
1573 if (set_network(ifname, id, "eap", "FAST") < 0)
1574 return -2;
1575
1576 val = get_param(cmd, "innerEAP");
1577 if (val) {
1578 if (strcasecmp(val, "MSCHAPV2") == 0) {
1579 if (set_network_quoted(ifname, id, "phase2",
1580 "auth=MSCHAPV2") < 0)
1581 return -2;
1582 } else if (strcasecmp(val, "GTC") == 0) {
1583 if (set_network_quoted(ifname, id, "phase2",
1584 "auth=GTC") < 0)
1585 return -2;
1586 } else
1587 return -1;
1588 }
1589
1590 val = get_param(cmd, "validateServer");
1591 if (val) {
1592 /* TODO */
1593 sigma_dut_print(dut, DUT_MSG_INFO, "Ignored EAP-FAST "
1594 "validateServer=%s", val);
1595 }
1596
1597 val = get_param(cmd, "pacFile");
1598 if (val) {
1599 snprintf(buf, sizeof(buf), "blob://%s", val);
1600 if (set_network_quoted(ifname, id, "pac_file", buf) < 0)
1601 return -2;
1602 }
1603
1604 if (set_network_quoted(ifname, id, "phase1", "fast_provisioning=2") <
1605 0)
1606 return -2;
1607
1608 return 1;
1609}
1610
1611
1612static int cmd_sta_set_eapaka(struct sigma_dut *dut, struct sigma_conn *conn,
1613 struct sigma_cmd *cmd)
1614{
1615 const char *intf = get_param(cmd, "Interface");
1616 const char *ifname;
1617 int id;
1618
1619 if (intf == NULL)
1620 return -1;
1621
1622 if (strcmp(intf, get_main_ifname()) == 0)
1623 ifname = get_station_ifname();
1624 else
1625 ifname = intf;
1626
1627 id = set_eap_common(dut, conn, ifname, cmd);
1628 if (id < 0)
1629 return id;
1630
1631 if (set_network(ifname, id, "eap", "AKA") < 0)
1632 return -2;
1633
1634 return 1;
1635}
1636
1637
1638static int cmd_sta_set_eapakaprime(struct sigma_dut *dut,
1639 struct sigma_conn *conn,
1640 struct sigma_cmd *cmd)
1641{
1642 const char *intf = get_param(cmd, "Interface");
1643 const char *ifname;
1644 int id;
1645
1646 if (intf == NULL)
1647 return -1;
1648
1649 if (strcmp(intf, get_main_ifname()) == 0)
1650 ifname = get_station_ifname();
1651 else
1652 ifname = intf;
1653
1654 id = set_eap_common(dut, conn, ifname, cmd);
1655 if (id < 0)
1656 return id;
1657
1658 if (set_network(ifname, id, "eap", "AKA'") < 0)
1659 return -2;
1660
1661 return 1;
1662}
1663
1664
1665static int sta_set_open(struct sigma_dut *dut, struct sigma_conn *conn,
1666 struct sigma_cmd *cmd)
1667{
1668 const char *intf = get_param(cmd, "Interface");
1669 const char *ifname;
1670 int id;
1671
1672 if (strcmp(intf, get_main_ifname()) == 0)
1673 ifname = get_station_ifname();
1674 else
1675 ifname = intf;
1676
1677 id = add_network_common(dut, conn, ifname, cmd);
1678 if (id < 0)
1679 return id;
1680
1681 if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
1682 return -2;
1683
1684 return 1;
1685}
1686
1687
1688static int cmd_sta_set_security(struct sigma_dut *dut, struct sigma_conn *conn,
1689 struct sigma_cmd *cmd)
1690{
1691 const char *type = get_param(cmd, "Type");
1692
1693 if (type == NULL) {
1694 send_resp(dut, conn, SIGMA_ERROR,
1695 "ErrorCode,Missing Type argument");
1696 return 0;
1697 }
1698
1699 if (strcasecmp(type, "OPEN") == 0)
1700 return sta_set_open(dut, conn, cmd);
1701 if (strcasecmp(type, "PSK") == 0)
1702 return cmd_sta_set_psk(dut, conn, cmd);
1703 if (strcasecmp(type, "EAPTLS") == 0)
1704 return cmd_sta_set_eaptls(dut, conn, cmd);
1705 if (strcasecmp(type, "EAPTTLS") == 0)
1706 return cmd_sta_set_eapttls(dut, conn, cmd);
1707 if (strcasecmp(type, "EAPPEAP") == 0)
1708 return cmd_sta_set_peap(dut, conn, cmd);
1709 if (strcasecmp(type, "EAPSIM") == 0)
1710 return cmd_sta_set_eapsim(dut, conn, cmd);
1711 if (strcasecmp(type, "EAPFAST") == 0)
1712 return cmd_sta_set_eapfast(dut, conn, cmd);
1713 if (strcasecmp(type, "EAPAKA") == 0)
1714 return cmd_sta_set_eapaka(dut, conn, cmd);
1715 if (strcasecmp(type, "EAPAKAPRIME") == 0)
1716 return cmd_sta_set_eapakaprime(dut, conn, cmd);
1717
1718 send_resp(dut, conn, SIGMA_ERROR,
1719 "ErrorCode,Unsupported Type value");
1720 return 0;
1721}
1722
1723
1724int ath6kl_client_uapsd(struct sigma_dut *dut, const char *intf, int uapsd)
1725{
1726#ifdef __linux__
1727 /* special handling for ath6kl */
1728 char path[128], fname[128], *pos;
1729 ssize_t res;
1730 FILE *f;
1731
1732 snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", intf);
1733 res = readlink(path, path, sizeof(path));
1734 if (res < 0)
1735 return 0; /* not ath6kl */
1736
1737 if (res >= (int) sizeof(path))
1738 res = sizeof(path) - 1;
1739 path[res] = '\0';
1740 pos = strrchr(path, '/');
1741 if (pos == NULL)
1742 pos = path;
1743 else
1744 pos++;
1745 snprintf(fname, sizeof(fname),
1746 "/sys/kernel/debug/ieee80211/%s/ath6kl/"
1747 "create_qos", pos);
1748 if (!file_exists(fname))
1749 return 0; /* not ath6kl */
1750
1751 if (uapsd) {
1752 f = fopen(fname, "w");
1753 if (f == NULL)
1754 return -1;
1755
1756 sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl create_qos");
1757 fprintf(f, "4 2 2 1 2 9999999 9999999 9999999 7777777 0 4 "
1758 "45000 200 56789000 56789000 5678900 0 0 9999999 "
1759 "20000 0\n");
1760 fclose(f);
1761 } else {
1762 snprintf(fname, sizeof(fname),
1763 "/sys/kernel/debug/ieee80211/%s/ath6kl/"
1764 "delete_qos", pos);
1765
1766 f = fopen(fname, "w");
1767 if (f == NULL)
1768 return -1;
1769
1770 sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl delete_qos");
1771 fprintf(f, "2 4\n");
1772 fclose(f);
1773 }
1774#endif /* __linux__ */
1775
1776 return 0;
1777}
1778
1779
1780static int cmd_sta_set_uapsd(struct sigma_dut *dut, struct sigma_conn *conn,
1781 struct sigma_cmd *cmd)
1782{
1783 const char *intf = get_param(cmd, "Interface");
1784 /* const char *ssid = get_param(cmd, "ssid"); */
1785 const char *val;
1786 int max_sp_len = 4;
1787 int ac_be = 1, ac_bk = 1, ac_vi = 1, ac_vo = 1;
1788 char buf[100];
1789 int ret1, ret2;
1790
1791 val = get_param(cmd, "maxSPLength");
1792 if (val) {
1793 max_sp_len = atoi(val);
1794 if (max_sp_len != 0 && max_sp_len != 1 && max_sp_len != 2 &&
1795 max_sp_len != 4)
1796 return -1;
1797 }
1798
1799 val = get_param(cmd, "acBE");
1800 if (val)
1801 ac_be = atoi(val);
1802
1803 val = get_param(cmd, "acBK");
1804 if (val)
1805 ac_bk = atoi(val);
1806
1807 val = get_param(cmd, "acVI");
1808 if (val)
1809 ac_vi = atoi(val);
1810
1811 val = get_param(cmd, "acVO");
1812 if (val)
1813 ac_vo = atoi(val);
1814
1815 dut->client_uapsd = ac_be || ac_bk || ac_vi || ac_vo;
1816
1817 snprintf(buf, sizeof(buf), "P2P_SET client_apsd %d,%d,%d,%d;%d",
1818 ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
1819 ret1 = wpa_command(intf, buf);
1820
1821 snprintf(buf, sizeof(buf), "SET uapsd %d,%d,%d,%d;%d",
1822 ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
1823 ret2 = wpa_command(intf, buf);
1824
1825 if (ret1 && ret2) {
1826 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to set client mode "
1827 "UAPSD parameters.");
1828 return -2;
1829 }
1830
1831 if (ath6kl_client_uapsd(dut, intf, dut->client_uapsd) < 0) {
1832 send_resp(dut, conn, SIGMA_ERROR,
1833 "ErrorCode,Failed to set ath6kl QoS parameters");
1834 return 0;
1835 }
1836
1837 return 1;
1838}
1839
1840
1841static int cmd_sta_set_wmm(struct sigma_dut *dut, struct sigma_conn *conn,
1842 struct sigma_cmd *cmd)
1843{
1844 char buf[1000];
1845 const char *intf = get_param(cmd, "Interface");
1846 const char *grp = get_param(cmd, "Group");
1847 const char *act = get_param(cmd, "Action");
1848 const char *tid = get_param(cmd, "Tid");
1849 const char *dir = get_param(cmd, "Direction");
1850 const char *psb = get_param(cmd, "Psb");
1851 const char *up = get_param(cmd, "Up");
1852 const char *fixed = get_param(cmd, "Fixed");
1853 const char *size = get_param(cmd, "Size");
1854 const char *msize = get_param(cmd, "Maxsize");
1855 const char *minsi = get_param(cmd, "Min_srvc_intrvl");
1856 const char *maxsi = get_param(cmd, "Max_srvc_intrvl");
1857 const char *inact = get_param(cmd, "Inactivity");
1858 const char *sus = get_param(cmd, "Suspension");
1859 const char *mindr = get_param(cmd, "Mindatarate");
1860 const char *meandr = get_param(cmd, "Meandatarate");
1861 const char *peakdr = get_param(cmd, "Peakdatarate");
1862 const char *phyrate = get_param(cmd, "Phyrate");
1863 const char *burstsize = get_param(cmd, "Burstsize");
1864 const char *sba = get_param(cmd, "Sba");
1865 int direction;
1866 int handle;
1867 float sba_fv;
1868 int fixed_int;
1869 int psb_ts;
1870
1871 if (intf == NULL || grp == NULL || act == NULL )
1872 return -1;
1873
1874 if (strcasecmp(act, "addts") == 0) {
1875 if (tid == NULL || dir == NULL || psb == NULL ||
1876 up == NULL || fixed == NULL || size == NULL)
1877 return -1;
1878
1879 /*
1880 * Note: Sigma CAPI spec lists uplink, downlink, and bidi as the
1881 * possible values, but WMM-AC and V-E test scripts use "UP,
1882 * "DOWN", and "BIDI".
1883 */
1884 if (strcasecmp(dir, "uplink") == 0 ||
1885 strcasecmp(dir, "up") == 0) {
1886 direction = 0;
1887 } else if (strcasecmp(dir, "downlink") == 0 ||
1888 strcasecmp(dir, "down") == 0) {
1889 direction = 1;
1890 } else if (strcasecmp(dir, "bidi") == 0) {
1891 direction = 2;
1892 } else {
1893 sigma_dut_print(dut, DUT_MSG_ERROR,
1894 "Direction %s not supported", dir);
1895 return -1;
1896 }
1897
1898 if (strcasecmp(psb, "legacy") == 0) {
1899 psb_ts = 0;
1900 } else if (strcasecmp(psb, "uapsd") == 0) {
1901 psb_ts = 1;
1902 } else {
1903 sigma_dut_print(dut, DUT_MSG_ERROR,
1904 "PSB %s not supported", psb);
1905 return -1;
1906 }
1907
1908 if (atoi(tid) < 0 || atoi(tid) > 7) {
1909 sigma_dut_print(dut, DUT_MSG_ERROR,
1910 "TID %s not supported", tid);
1911 return -1;
1912 }
1913
1914 if (strcasecmp(fixed, "true") == 0) {
1915 fixed_int = 1;
1916 } else {
1917 fixed_int = 0;
1918 }
1919
1920 sba_fv = atof(sba);
1921
1922 dut->dialog_token++;
1923 handle = 7000 + dut->dialog_token;
1924
1925 /*
1926 * size: convert to hex
1927 * maxsi: convert to hex
1928 * mindr: convert to hex
1929 * meandr: convert to hex
1930 * peakdr: convert to hex
1931 * burstsize: convert to hex
1932 * phyrate: convert to hex
1933 * sba: convert to hex with modification
1934 * minsi: convert to integer
1935 * sus: convert to integer
1936 * inact: convert to integer
1937 * maxsi: convert to integer
1938 */
1939
1940 /*
1941 * The Nominal MSDU Size field is 2 octets long and contains an
1942 * unsigned integer that specifies the nominal size, in octets,
1943 * of MSDUs belonging to the traffic under this traffic
1944 * specification and is defined in Figure 16. If the Fixed
1945 * subfield is set to 1, then the size of the MSDU is fixed and
1946 * is indicated by the Size Subfield. If the Fixed subfield is
1947 * set to 0, then the size of the MSDU might not be fixed and
1948 * the Size indicates the nominal MSDU size.
1949 *
1950 * The Surplus Bandwidth Allowance Factor field is 2 octets long
1951 * and specifies the excess allocation of time (and bandwidth)
1952 * over and above the stated rates required to transport an MSDU
1953 * belonging to the traffic in this TSPEC. This field is
1954 * represented as an unsigned binary number with an implicit
1955 * binary point after the leftmost 3 bits. For example, an SBA
1956 * of 1.75 is represented as 0x3800. This field is included to
1957 * account for retransmissions. As such, the value of this field
1958 * must be greater than unity.
1959 */
1960
1961 snprintf(buf, sizeof(buf),
1962 "iwpriv %s addTspec %d %s %d %d %s 0x%X"
1963 " 0x%X 0x%X 0x%X"
1964 " 0x%X 0x%X 0x%X"
1965 " 0x%X %d %d %d %d"
1966 " %d %d",
1967 intf, handle, tid, direction, psb_ts, up,
1968 (unsigned int) ((fixed_int << 15) | atoi(size)),
1969 msize ? atoi(msize) : 0,
1970 mindr ? atoi(mindr) : 0,
1971 meandr ? atoi(meandr) : 0,
1972 peakdr ? atoi(peakdr) : 0,
1973 burstsize ? atoi(burstsize) : 0,
1974 phyrate ? atoi(phyrate) : 0,
1975 sba ? ((unsigned int) (((int) sba_fv << 13) |
1976 (int)((sba_fv - (int) sba_fv) *
1977 8192))) : 0,
1978 minsi ? atoi(minsi) : 0,
1979 sus ? atoi(sus) : 0,
1980 0, 0,
1981 inact ? atoi(inact) : 0,
1982 maxsi ? atoi(maxsi) : 0);
1983
1984 if (system(buf) != 0) {
1985 sigma_dut_print(dut, DUT_MSG_ERROR,
1986 "iwpriv addtspec request failed");
1987 send_resp(dut, conn, SIGMA_ERROR,
1988 "errorCode,Failed to execute addTspec command");
1989 return 0;
1990 }
1991
1992 sigma_dut_print(dut, DUT_MSG_INFO,
1993 "iwpriv addtspec request send");
1994
1995 /* Mapping handle to a TID */
1996 dut->tid_to_handle[atoi(tid)] = handle;
1997 } else if (strcasecmp(act, "delts") == 0) {
1998 if (tid == NULL)
1999 return -1;
2000
2001 if (atoi(tid) < 0 || atoi(tid) > 7) {
2002 sigma_dut_print(dut, DUT_MSG_ERROR,
2003 "TID %s not supported", tid);
2004 send_resp(dut, conn, SIGMA_ERROR,
2005 "errorCode,Unsupported TID");
2006 return 0;
2007 }
2008
2009 handle = dut->tid_to_handle[atoi(tid)];
2010
2011 if (handle < 7000 || handle > 7255) {
2012 /* Invalid handle ie no mapping for that TID */
2013 sigma_dut_print(dut, DUT_MSG_ERROR,
2014 "handle-> %d not found", handle);
2015 }
2016
2017 snprintf(buf, sizeof(buf), "iwpriv %s delTspec %d",
2018 intf, handle);
2019
2020 if (system(buf) != 0) {
2021 sigma_dut_print(dut, DUT_MSG_ERROR,
2022 "iwpriv deltspec request failed");
2023 send_resp(dut, conn, SIGMA_ERROR,
2024 "errorCode,Failed to execute delTspec command");
2025 return 0;
2026 }
2027
2028 sigma_dut_print(dut, DUT_MSG_INFO,
2029 "iwpriv deltspec request send");
2030
2031 dut->tid_to_handle[atoi(tid)] = 0;
2032 } else {
2033 sigma_dut_print(dut, DUT_MSG_ERROR,
2034 "Action type %s not supported", act);
2035 send_resp(dut, conn, SIGMA_ERROR,
2036 "errorCode,Unsupported Action");
2037 return 0;
2038 }
2039
2040 return 1;
2041}
2042
2043
2044static int cmd_sta_associate(struct sigma_dut *dut, struct sigma_conn *conn,
2045 struct sigma_cmd *cmd)
2046{
2047 /* const char *intf = get_param(cmd, "Interface"); */
2048 const char *ssid = get_param(cmd, "ssid");
2049 const char *wps_param = get_param(cmd, "WPS");
2050 const char *bssid = get_param(cmd, "bssid");
2051 int wps = 0;
2052 char buf[100];
2053
2054 if (ssid == NULL)
2055 return -1;
2056
2057 if (wps_param &&
2058 (strcmp(wps_param, "1") == 0 || strcasecmp(wps_param, "On") == 0))
2059 wps = 1;
2060
2061 if (wps) {
2062 if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
2063 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS "
2064 "parameters not yet set");
2065 return 0;
2066 }
2067 if (dut->wps_method == WFA_CS_WPS_PBC) {
2068 if (wpa_command(get_station_ifname(), "WPS_PBC") < 0)
2069 return -2;
2070 } else {
2071 snprintf(buf, sizeof(buf), "WPS_PIN any %s",
2072 dut->wps_pin);
2073 if (wpa_command(get_station_ifname(), buf) < 0)
2074 return -2;
2075 }
2076 } else {
2077 if (strcmp(ssid, dut->infra_ssid) != 0) {
2078 printf("No network parameters known for network "
2079 "(ssid='%s')", ssid);
2080 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2081 "No network parameters known for network");
2082 return 0;
2083 }
2084
2085 if (bssid &&
2086 set_network(get_station_ifname(), dut->infra_network_id,
2087 "bssid", bssid) < 0) {
2088 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2089 "Invalid bssid argument");
2090 return 0;
2091 }
2092
2093 snprintf(buf, sizeof(buf), "SELECT_NETWORK %d",
2094 dut->infra_network_id);
2095 if (wpa_command(get_station_ifname(), buf) < 0) {
2096 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to select "
2097 "network id %d on %s",
2098 dut->infra_network_id,
2099 get_station_ifname());
2100 return -2;
2101 }
2102 }
2103
2104 return 1;
2105}
2106
2107
2108static int run_hs20_osu(struct sigma_dut *dut, const char *params)
2109{
2110 char buf[500], cmd[200];
2111 int res;
2112
2113 /* Use hs20-osu-client file at the current dir, if found; otherwise use
2114 * default path */
2115 res = snprintf(cmd, sizeof(cmd),
2116 "%s -w \"%s\" -r hs20-osu-client.res %s%s -dddKt -f Logs/hs20-osu-client.txt",
2117 file_exists("./hs20-osu-client") ?
2118 "./hs20-osu-client" : "hs20-osu-client",
2119 sigma_wpas_ctrl,
2120 dut->summary_log ? "-s " : "",
2121 dut->summary_log ? dut->summary_log : "");
2122 if (res < 0 || res >= (int) sizeof(cmd))
2123 return -1;
2124
2125 res = snprintf(buf, sizeof(buf), "%s %s", cmd, params);
2126 if (res < 0 || res >= (int) sizeof(buf))
2127 return -1;
2128 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
2129
2130 if (system(buf) != 0) {
2131 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to run: %s", buf);
2132 return -1;
2133 }
2134 sigma_dut_print(dut, DUT_MSG_DEBUG,
2135 "Completed hs20-osu-client operation");
2136
2137 return 0;
2138}
2139
2140
2141static int download_ppsmo(struct sigma_dut *dut,
2142 struct sigma_conn *conn,
2143 const char *intf,
2144 struct sigma_cmd *cmd)
2145{
2146 const char *name, *path, *val;
2147 char url[500], buf[600], fbuf[100];
2148 char *fqdn = NULL;
2149
2150 name = get_param(cmd, "FileName");
2151 path = get_param(cmd, "FilePath");
2152 if (name == NULL || path == NULL)
2153 return -1;
2154
2155 if (strcasecmp(path, "VendorSpecific") == 0) {
2156 snprintf(url, sizeof(url), "PPS/%s", name);
2157 sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured PPS MO "
2158 "from the device (%s)", url);
2159 if (!file_exists(url)) {
2160 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
2161 "PPS MO file does not exist");
2162 return 0;
2163 }
2164 snprintf(buf, sizeof(buf), "cp %s pps-tnds.xml", url);
2165 if (system(buf) != 0) {
2166 send_resp(dut, conn, SIGMA_ERROR,
2167 "errorCode,Failed to copy PPS MO");
2168 return 0;
2169 }
2170 } else if (strncasecmp(path, "http:", 5) != 0 &&
2171 strncasecmp(path, "https:", 6) != 0) {
2172 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2173 "Unsupported FilePath value");
2174 return 0;
2175 } else {
2176 snprintf(url, sizeof(url), "%s/%s", path, name);
2177 sigma_dut_print(dut, DUT_MSG_INFO, "Downloading PPS MO from %s",
2178 url);
2179 snprintf(buf, sizeof(buf), "wget -T 10 -t 3 -O pps-tnds.xml '%s'", url);
2180 remove("pps-tnds.xml");
2181 if (system(buf) != 0) {
2182 send_resp(dut, conn, SIGMA_ERROR,
2183 "errorCode,Failed to download PPS MO");
2184 return 0;
2185 }
2186 }
2187
2188 if (run_hs20_osu(dut, "from_tnds pps-tnds.xml pps.xml") < 0) {
2189 send_resp(dut, conn, SIGMA_ERROR,
2190 "errorCode,Failed to parse downloaded PPSMO");
2191 return 0;
2192 }
2193 unlink("pps-tnds.xml");
2194
2195 val = get_param(cmd, "managementTreeURI");
2196 if (val) {
2197 const char *pos, *end;
2198 sigma_dut_print(dut, DUT_MSG_DEBUG, "managementTreeURI: %s",
2199 val);
2200 if (strncmp(val, "./Wi-Fi/", 8) != 0) {
2201 send_resp(dut, conn, SIGMA_ERROR,
2202 "errorCode,Invalid managementTreeURI prefix");
2203 return 0;
2204 }
2205 pos = val + 8;
2206 end = strchr(pos, '/');
2207 if (end == NULL ||
2208 strcmp(end, "/PerProviderSubscription") != 0) {
2209 send_resp(dut, conn, SIGMA_ERROR,
2210 "errorCode,Invalid managementTreeURI postfix");
2211 return 0;
2212 }
2213 if (end - pos >= (int) sizeof(fbuf)) {
2214 send_resp(dut, conn, SIGMA_ERROR,
2215 "errorCode,Too long FQDN in managementTreeURI");
2216 return 0;
2217 }
2218 memcpy(fbuf, pos, end - pos);
2219 fbuf[end - pos] = '\0';
2220 fqdn = fbuf;
2221 sigma_dut_print(dut, DUT_MSG_INFO,
2222 "FQDN from managementTreeURI: %s", fqdn);
2223 } else if (run_hs20_osu(dut, "get_fqdn pps.xml") == 0) {
2224 FILE *f = fopen("pps-fqdn", "r");
2225 if (f) {
2226 if (fgets(fbuf, sizeof(fbuf), f)) {
2227 fbuf[sizeof(fbuf) - 1] = '\0';
2228 fqdn = fbuf;
2229 sigma_dut_print(dut, DUT_MSG_DEBUG,
2230 "Use FQDN %s", fqdn);
2231 }
2232 fclose(f);
2233 }
2234 }
2235
2236 if (fqdn == NULL) {
2237 send_resp(dut, conn, SIGMA_ERROR,
2238 "errorCode,No FQDN specified");
2239 return 0;
2240 }
2241
2242 mkdir("SP", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
2243 snprintf(buf, sizeof(buf), "SP/%s", fqdn);
2244 mkdir(buf, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
2245
2246 snprintf(buf, sizeof(buf), "SP/%s/pps.xml", fqdn);
2247 if (rename("pps.xml", buf) < 0) {
2248 send_resp(dut, conn, SIGMA_ERROR,
2249 "errorCode,Could not move PPS MO");
2250 return 0;
2251 }
2252
2253 if (strcasecmp(path, "VendorSpecific") == 0) {
2254 snprintf(buf, sizeof(buf), "cp Certs/ca.pem SP/%s/ca.pem",
2255 fqdn);
2256 if (system(buf)) {
2257 send_resp(dut, conn, SIGMA_ERROR,
2258 "errorCode,Failed to copy OSU CA cert");
2259 return 0;
2260 }
2261
2262 snprintf(buf, sizeof(buf),
2263 "cp Certs/aaa-ca.pem SP/%s/aaa-ca.pem",
2264 fqdn);
2265 if (system(buf)) {
2266 send_resp(dut, conn, SIGMA_ERROR,
2267 "errorCode,Failed to copy AAA CA cert");
2268 return 0;
2269 }
2270 } else {
2271 snprintf(buf, sizeof(buf),
2272 "dl_osu_ca SP/%s/pps.xml SP/%s/ca.pem",
2273 fqdn, fqdn);
2274 if (run_hs20_osu(dut, buf) < 0) {
2275 send_resp(dut, conn, SIGMA_ERROR,
2276 "errorCode,Failed to download OSU CA cert");
2277 return 0;
2278 }
2279
2280 snprintf(buf, sizeof(buf),
2281 "dl_aaa_ca SP/%s/pps.xml SP/%s/aaa-ca.pem",
2282 fqdn, fqdn);
2283 if (run_hs20_osu(dut, buf) < 0) {
2284 sigma_dut_print(dut, DUT_MSG_INFO,
2285 "Failed to download AAA CA cert");
2286 }
2287 }
2288
2289 if (file_exists("next-client-cert.pem")) {
2290 snprintf(buf, sizeof(buf), "SP/%s/client-cert.pem", fqdn);
2291 if (rename("next-client-cert.pem", buf) < 0) {
2292 send_resp(dut, conn, SIGMA_ERROR,
2293 "errorCode,Could not move client certificate");
2294 return 0;
2295 }
2296 }
2297
2298 if (file_exists("next-client-key.pem")) {
2299 snprintf(buf, sizeof(buf), "SP/%s/client-key.pem", fqdn);
2300 if (rename("next-client-key.pem", buf) < 0) {
2301 send_resp(dut, conn, SIGMA_ERROR,
2302 "errorCode,Could not move client key");
2303 return 0;
2304 }
2305 }
2306
2307 snprintf(buf, sizeof(buf), "set_pps SP/%s/pps.xml", fqdn);
2308 if (run_hs20_osu(dut, buf) < 0) {
2309 send_resp(dut, conn, SIGMA_ERROR,
2310 "errorCode,Failed to configure credential from "
2311 "PPSMO");
2312 return 0;
2313 }
2314
2315 return 1;
2316}
2317
2318
2319static int download_cert(struct sigma_dut *dut,
2320 struct sigma_conn *conn,
2321 const char *intf,
2322 struct sigma_cmd *cmd)
2323{
2324 const char *name, *path;
2325 char url[500], buf[600];
2326
2327 name = get_param(cmd, "FileName");
2328 path = get_param(cmd, "FilePath");
2329 if (name == NULL || path == NULL)
2330 return -1;
2331
2332 if (strcasecmp(path, "VendorSpecific") == 0) {
2333 snprintf(url, sizeof(url), "Certs/%s-cert.pem", name);
2334 sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
2335 "certificate from the device (%s)", url);
2336 if (!file_exists(url)) {
2337 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
2338 "certificate file does not exist");
2339 return 0;
2340 }
2341 snprintf(buf, sizeof(buf), "cp %s next-client-cert.pem", url);
2342 if (system(buf) != 0) {
2343 send_resp(dut, conn, SIGMA_ERROR,
2344 "errorCode,Failed to copy client "
2345 "certificate");
2346 return 0;
2347 }
2348
2349 snprintf(url, sizeof(url), "Certs/%s-key.pem", name);
2350 sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
2351 "private key from the device (%s)", url);
2352 if (!file_exists(url)) {
2353 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
2354 "private key file does not exist");
2355 return 0;
2356 }
2357 snprintf(buf, sizeof(buf), "cp %s next-client-key.pem", url);
2358 if (system(buf) != 0) {
2359 send_resp(dut, conn, SIGMA_ERROR,
2360 "errorCode,Failed to copy client key");
2361 return 0;
2362 }
2363 } else if (strncasecmp(path, "http:", 5) != 0 &&
2364 strncasecmp(path, "https:", 6) != 0) {
2365 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2366 "Unsupported FilePath value");
2367 return 0;
2368 } else {
2369 snprintf(url, sizeof(url), "%s/%s.pem", path, name);
2370 sigma_dut_print(dut, DUT_MSG_INFO, "Downloading client "
2371 "certificate/key from %s", url);
2372 snprintf(buf, sizeof(buf),
2373 "wget -T 10 -t 3 -O next-client-cert.pem '%s'", url);
2374 if (system(buf) != 0) {
2375 send_resp(dut, conn, SIGMA_ERROR,
2376 "errorCode,Failed to download client "
2377 "certificate");
2378 return 0;
2379 }
2380
2381 if (system("cp next-client-cert.pem next-client-key.pem") != 0)
2382 {
2383 send_resp(dut, conn, SIGMA_ERROR,
2384 "errorCode,Failed to copy client key");
2385 return 0;
2386 }
2387 }
2388
2389 return 1;
2390}
2391
2392
2393static int cmd_sta_preset_testparameters_hs2_r2(struct sigma_dut *dut,
2394 struct sigma_conn *conn,
2395 const char *intf,
2396 struct sigma_cmd *cmd)
2397{
2398 const char *val;
2399
2400 val = get_param(cmd, "FileType");
2401 if (val && strcasecmp(val, "PPSMO") == 0)
2402 return download_ppsmo(dut, conn, intf, cmd);
2403 if (val && strcasecmp(val, "CERT") == 0)
2404 return download_cert(dut, conn, intf, cmd);
2405 if (val) {
2406 send_resp(dut, conn, SIGMA_ERROR,
2407 "ErrorCode,Unsupported FileType");
2408 return 0;
2409 }
2410
2411 return 1;
2412}
2413
2414
2415static void ath_sta_set_noack(struct sigma_dut *dut, const char *intf,
2416 const char *val)
2417{
2418 int counter = 0;
2419 char token[50];
2420 char *result;
2421 char buf[100];
2422
2423 strncpy(token, val, sizeof(token));
2424 token[sizeof(token) - 1] = '\0';
2425 result = strtok(token, ":");
2426 while (result) {
2427 if (strcmp(result, "disable") == 0) {
2428 snprintf(buf, sizeof(buf),
2429 "iwpriv %s noackpolicy %d 1 0",
2430 intf, counter);
2431 } else {
2432 snprintf(buf, sizeof(buf),
2433 "iwpriv %s noackpolicy %d 1 1",
2434 intf, counter);
2435 }
2436 if (system(buf) != 0) {
2437 sigma_dut_print(dut, DUT_MSG_ERROR,
2438 "iwpriv noackpolicy failed");
2439 }
2440 result = strtok(NULL, ":");
2441 counter++;
2442 }
2443}
2444
2445
2446static void ath_sta_set_rts(struct sigma_dut *dut, const char *intf,
2447 const char *val)
2448{
2449 char buf[100];
2450
2451 snprintf(buf, sizeof(buf), "iwconfig %s rts %s", intf, val);
2452 if (system(buf) != 0) {
2453 sigma_dut_print(dut, DUT_MSG_ERROR, "iwconfig RTS failed");
2454 }
2455}
2456
2457
2458static void ath_sta_set_wmm(struct sigma_dut *dut, const char *intf,
2459 const char *val)
2460{
2461 char buf[100];
2462
2463 if (strcasecmp(val, "off") == 0) {
2464 snprintf(buf, sizeof(buf), "iwpriv %s wmm 0", intf);
2465 if (system(buf) != 0) {
2466 sigma_dut_print(dut, DUT_MSG_ERROR,
2467 "Failed to turn off WMM");
2468 }
2469 }
2470}
2471
2472
2473static void ath_sta_set_sgi(struct sigma_dut *dut, const char *intf,
2474 const char *val)
2475{
2476 char buf[100];
2477 int sgi20;
2478
2479 sgi20 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
2480
2481 snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi20);
2482 if (system(buf) != 0)
2483 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv shortgi failed");
2484}
2485
2486
2487static void ath_sta_set_11nrates(struct sigma_dut *dut, const char *intf,
2488 const char *val)
2489{
2490 char buf[100];
2491 int rate_code;
2492
2493 /* Disable Tx Beam forming when using a fixed rate */
2494 ath_disable_txbf(dut, intf);
2495
2496 rate_code = 0x80 + atoi(val);
2497
2498 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0x%x",
2499 intf, rate_code);
2500 if (system(buf) != 0) {
2501 sigma_dut_print(dut, DUT_MSG_ERROR,
2502 "iwpriv set11NRates failed");
2503 }
2504
2505 /* Channel width gets messed up, fix this */
2506 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d", intf, dut->chwidth);
2507 if (system(buf) != 0)
2508 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv chwidth failed");
2509}
2510
2511
2512static void ath_sta_set_amsdu(struct sigma_dut *dut, const char *intf,
2513 const char *val)
2514{
2515 char buf[60];
2516
2517 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)
2518 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 2", intf);
2519 else
2520 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
2521
2522 if (system(buf) != 0)
2523 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv amsdu failed");
2524}
2525
2526
2527static void ath_sta_set_stbc(struct sigma_dut *dut, const char *intf,
2528 const char *val)
2529{
2530 char buf[60];
2531
2532 snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc %s", intf, val);
2533 if (system(buf) != 0) {
2534 sigma_dut_print(dut, DUT_MSG_ERROR,
2535 "iwpriv tx_stbc failed");
2536 }
2537
2538 snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc %s", intf, val);
2539 if (system(buf) != 0) {
2540 sigma_dut_print(dut, DUT_MSG_ERROR,
2541 "iwpriv rx_stbc failed");
2542 }
2543}
2544
2545
2546static int wcn_sta_set_cts_width(struct sigma_dut *dut, const char *intf,
2547 const char *val)
2548{
2549 char buf[60];
2550
2551 if (strcmp(val, "80") == 0) {
2552 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
2553 } else if (strcmp(val, "40") == 0) {
2554 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 2", intf);
2555 } else if (strcmp(val, "20") == 0) {
2556 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 1", intf);
2557 } else if (strcasecmp(val, "Auto") == 0) {
2558 buf[0] = '\0';
2559 } else {
2560 sigma_dut_print(dut, DUT_MSG_ERROR,
2561 "WIDTH/CTS_WIDTH value not supported");
2562 return -1;
2563 }
2564
2565 if (buf[0] != '\0' && system(buf) != 0) {
2566 sigma_dut_print(dut, DUT_MSG_ERROR,
2567 "Failed to set WIDTH/CTS_WIDTH");
2568 return -1;
2569 }
2570
2571 return 0;
2572}
2573
2574
2575int ath_set_width(struct sigma_dut *dut, struct sigma_conn *conn,
2576 const char *intf, const char *val)
2577{
2578 char buf[60];
2579
2580 if (strcasecmp(val, "Auto") == 0) {
2581 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
2582 dut->chwidth = 0;
2583 } else if (strcasecmp(val, "20") == 0) {
2584 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
2585 dut->chwidth = 0;
2586 } else if (strcasecmp(val, "40") == 0) {
2587 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 1", intf);
2588 dut->chwidth = 1;
2589 } else if (strcasecmp(val, "80") == 0) {
2590 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
2591 dut->chwidth = 2;
2592 } else if (strcasecmp(val, "160") == 0) {
2593 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 3", intf);
2594 dut->chwidth = 3;
2595 } else {
2596 send_resp(dut, conn, SIGMA_ERROR,
2597 "ErrorCode,WIDTH not supported");
2598 return -1;
2599 }
2600
2601 if (system(buf) != 0) {
2602 sigma_dut_print(dut, DUT_MSG_ERROR,
2603 "iwpriv chwidth failed");
2604 }
2605
2606 return 0;
2607}
2608
2609
2610static int wcn_sta_set_sp_stream(struct sigma_dut *dut, const char *intf,
2611 const char *val)
2612{
2613 char buf[60];
2614
2615 if (strcmp(val, "1SS") == 0) {
2616 snprintf(buf, sizeof(buf), "iwpriv %s nss 1", intf);
2617 } else if (strcmp(val, "2SS") == 0) {
2618 snprintf(buf, sizeof(buf), "iwpriv %s nss 2", intf);
2619 } else {
2620 sigma_dut_print(dut, DUT_MSG_ERROR,
2621 "SP_STREAM value not supported");
2622 return -1;
2623 }
2624
2625 if (system(buf) != 0) {
2626 sigma_dut_print(dut, DUT_MSG_ERROR,
2627 "Failed to set SP_STREAM");
2628 return -1;
2629 }
2630
2631 return 0;
2632}
2633
2634
2635static int cmd_sta_preset_testparameters(struct sigma_dut *dut,
2636 struct sigma_conn *conn,
2637 struct sigma_cmd *cmd)
2638{
2639 const char *intf = get_param(cmd, "Interface");
2640 const char *val;
2641
2642 val = get_param(cmd, "Program");
2643 if (val && strcasecmp(val, "HS2-R2") == 0) {
2644 if (intf == NULL)
2645 return -1;
2646 return cmd_sta_preset_testparameters_hs2_r2(dut, conn, intf,
2647 cmd);
2648 }
2649
2650#ifdef ANDROID_NAN
2651 if (val && strcasecmp(val, "NAN") == 0)
2652 return nan_cmd_sta_preset_testparameters(dut, conn, cmd);
2653#endif /* ANDROID_NAN */
2654
2655#if 0
2656 val = get_param(cmd, "Supplicant");
2657 if (val && strcasecmp(val, "Default") != 0) {
2658 send_resp(dut, conn, SIGMA_ERROR,
2659 "ErrorCode,Only default(Vendor) supplicant "
2660 "supported");
2661 return 0;
2662 }
2663#endif
2664
2665 val = get_param(cmd, "RTS");
2666 if (val) {
2667 switch (get_driver_type()) {
2668 case DRIVER_ATHEROS:
2669 ath_sta_set_rts(dut, intf, val);
2670 break;
2671 default:
2672#if 0
2673 send_resp(dut, conn, SIGMA_ERROR,
2674 "ErrorCode,Setting RTS not supported");
2675 return 0;
2676#else
2677 sigma_dut_print(dut, DUT_MSG_DEBUG,
2678 "Setting RTS not supported");
2679 break;
2680#endif
2681 }
2682 }
2683
2684#if 0
2685 val = get_param(cmd, "FRGMNT");
2686 if (val) {
2687 /* TODO */
2688 send_resp(dut, conn, SIGMA_ERROR,
2689 "ErrorCode,Setting FRGMNT not supported");
2690 return 0;
2691 }
2692#endif
2693
2694#if 0
2695 val = get_param(cmd, "Preamble");
2696 if (val) {
2697 /* TODO: Long/Short */
2698 send_resp(dut, conn, SIGMA_ERROR,
2699 "ErrorCode,Setting Preamble not supported");
2700 return 0;
2701 }
2702#endif
2703
2704 val = get_param(cmd, "Mode");
2705 if (val) {
2706 if (strcmp(val, "11b") == 0 ||
2707 strcmp(val, "11g") == 0 ||
2708 strcmp(val, "11a") == 0 ||
2709 strcmp(val, "11n") == 0 ||
2710 strcmp(val, "11ng") == 0 ||
2711 strcmp(val, "11nl") == 0 ||
2712 strcmp(val, "11nl(nabg)") == 0 ||
2713 strcmp(val, "AC") == 0 ||
2714 strcmp(val, "11AC") == 0 ||
2715 strcmp(val, "11ac") == 0 ||
2716 strcmp(val, "11na") == 0 ||
2717 strcmp(val, "11an") == 0) {
2718 /* STA supports all modes by default */
2719 } else {
2720 send_resp(dut, conn, SIGMA_ERROR,
2721 "ErrorCode,Setting Mode not supported");
2722 return 0;
2723 }
2724 }
2725
2726 val = get_param(cmd, "wmm");
2727 if (val) {
2728 switch (get_driver_type()) {
2729 case DRIVER_ATHEROS:
2730 ath_sta_set_wmm(dut, intf, val);
2731 break;
2732 default:
2733 sigma_dut_print(dut, DUT_MSG_DEBUG,
2734 "Setting wmm not supported");
2735 break;
2736 }
2737 }
2738
2739 val = get_param(cmd, "Powersave");
2740 if (val) {
2741 if (strcmp(val, "0") == 0 || strcasecmp(val, "off") == 0) {
2742 if (wpa_command(get_station_ifname(),
2743 "P2P_SET ps 0") < 0)
2744 return -2;
2745 /* Make sure test modes are disabled */
2746 wpa_command(get_station_ifname(), "P2P_SET ps 98");
2747 wpa_command(get_station_ifname(), "P2P_SET ps 96");
2748 } else if (strcmp(val, "1") == 0 ||
2749 strcasecmp(val, "PSPoll") == 0 ||
2750 strcasecmp(val, "on") == 0) {
2751 /* Disable default power save mode */
2752 wpa_command(get_station_ifname(), "P2P_SET ps 0");
2753 /* Enable PS-Poll test mode */
2754 if (wpa_command(get_station_ifname(),
2755 "P2P_SET ps 97") < 0 ||
2756 wpa_command(get_station_ifname(),
2757 "P2P_SET ps 99") < 0)
2758 return -2;
2759 } else if (strcmp(val, "2") == 0 ||
2760 strcasecmp(val, "Fast") == 0) {
2761 /* TODO */
2762 send_resp(dut, conn, SIGMA_ERROR,
2763 "ErrorCode,Powersave=Fast not supported");
2764 return 0;
2765 } else if (strcmp(val, "3") == 0 ||
2766 strcasecmp(val, "PSNonPoll") == 0) {
2767 /* Make sure test modes are disabled */
2768 wpa_command(get_station_ifname(), "P2P_SET ps 98");
2769 wpa_command(get_station_ifname(), "P2P_SET ps 96");
2770
2771 /* Enable default power save mode */
2772 if (wpa_command(get_station_ifname(),
2773 "P2P_SET ps 1") < 0)
2774 return -2;
2775 } else
2776 return -1;
2777 }
2778
2779 val = get_param(cmd, "NoAck");
2780 if (val) {
2781 switch (get_driver_type()) {
2782 case DRIVER_ATHEROS:
2783 ath_sta_set_noack(dut, intf, val);
2784 break;
2785 default:
2786 send_resp(dut, conn, SIGMA_ERROR,
2787 "ErrorCode,Setting NoAck not supported");
2788 return 0;
2789 }
2790 }
2791
2792 val = get_param(cmd, "IgnoreChswitchProhibit");
2793 if (val) {
2794 /* TODO: Enabled/disabled */
2795 if (strcasecmp(val, "Enabled") == 0) {
2796 send_resp(dut, conn, SIGMA_ERROR,
2797 "ErrorCode,Enabling IgnoreChswitchProhibit "
2798 "not supported");
2799 return 0;
2800 }
2801 }
2802
2803 val = get_param(cmd, "TDLS");
2804 if (val) {
2805 if (strcasecmp(val, "Disabled") == 0) {
2806 if (wpa_command(intf, "SET tdls_disabled 1")) {
2807 send_resp(dut, conn, SIGMA_ERROR,
2808 "ErrorCode,Failed to disable TDLS");
2809 return 0;
2810 }
2811 } else if (strcasecmp(val, "Enabled") == 0) {
2812 if (wpa_command(intf, "SET tdls_disabled 0")) {
2813 send_resp(dut, conn, SIGMA_ERROR,
2814 "ErrorCode,Failed to enable TDLS");
2815 return 0;
2816 }
2817 } else {
2818 send_resp(dut, conn, SIGMA_ERROR,
2819 "ErrorCode,Unsupported TDLS value");
2820 return 0;
2821 }
2822 }
2823
2824 val = get_param(cmd, "TDLSmode");
2825 if (val) {
2826 if (strcasecmp(val, "Default") == 0) {
2827 wpa_command(intf, "SET tdls_testing 0");
2828 } else if (strcasecmp(val, "APProhibit") == 0) {
2829 if (wpa_command(intf, "SET tdls_testing 0x400")) {
2830 send_resp(dut, conn, SIGMA_ERROR,
2831 "ErrorCode,Failed to enable ignore "
2832 "APProhibit TDLS mode");
2833 return 0;
2834 }
2835 } else if (strcasecmp(val, "HiLoMac") == 0) {
2836 /* STA should respond with TDLS setup req for a TDLS
2837 * setup req */
2838 if (wpa_command(intf, "SET tdls_testing 0x80")) {
2839 send_resp(dut, conn, SIGMA_ERROR,
2840 "ErrorCode,Failed to enable HiLoMac "
2841 "TDLS mode");
2842 return 0;
2843 }
2844 } else if (strcasecmp(val, "WeakSecurity") == 0) {
2845 /*
2846 * Since all security modes are enabled by default when
2847 * Sigma control is used, there is no need to do
2848 * anything here.
2849 */
2850 } else if (strcasecmp(val, "ExistLink") == 0) {
2851 /*
2852 * Since we allow new TDLS Setup Request even if there
2853 * is an existing link, nothing needs to be done for
2854 * this.
2855 */
2856 } else {
2857 /* TODO:
2858 * ExistLink: STA should send TDLS setup req even if
2859 * direct link already exists
2860 */
2861 send_resp(dut, conn, SIGMA_ERROR,
2862 "ErrorCode,Unsupported TDLSmode value");
2863 return 0;
2864 }
2865 }
2866
2867 val = get_param(cmd, "FakePubKey");
2868 if (val && atoi(val) && wpa_command(intf, "SET wps_corrupt_pkhash 1")) {
2869 send_resp(dut, conn, SIGMA_ERROR,
2870 "ErrorCode,Failed to enable FakePubKey");
2871 return 0;
2872 }
2873
2874 return 1;
2875}
2876
2877
2878static const char * ath_get_radio_name(const char *radio_name)
2879{
2880 if (radio_name == NULL)
2881 return "wifi0";
2882 if (strcmp(radio_name, "wifi1") == 0)
2883 return "wifi1";
2884 if (strcmp(radio_name, "wifi2") == 0)
2885 return "wifi2";
2886 return "wifi0";
2887}
2888
2889
2890static void ath_sta_set_txsp_stream(struct sigma_dut *dut, const char *intf,
2891 const char *val)
2892{
2893 char buf[60];
2894 unsigned int vht_mcsmap = 0;
2895 int txchainmask = 0;
2896 const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
2897
2898 if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
2899 if (dut->testbed_flag_txsp == 1) {
2900 vht_mcsmap = 0xfffc;
2901 dut->testbed_flag_txsp = 0;
2902 } else {
2903 vht_mcsmap = 0xfffe;
2904 }
2905 txchainmask = 1;
2906 } else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
2907 if (dut->testbed_flag_txsp == 1) {
2908 vht_mcsmap = 0xfff0;
2909 dut->testbed_flag_txsp = 0;
2910 } else {
2911 vht_mcsmap = 0xfffa;
2912 }
2913 txchainmask = 3;
2914 } else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
2915 if (dut->testbed_flag_txsp == 1) {
2916 vht_mcsmap = 0xffc0;
2917 dut->testbed_flag_txsp = 0;
2918 } else {
2919 vht_mcsmap = 0xffea;
2920 }
2921 txchainmask = 7;
2922 } else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
2923 if (dut->testbed_flag_txsp == 1) {
2924 vht_mcsmap = 0xff00;
2925 dut->testbed_flag_txsp = 0;
2926 } else {
2927 vht_mcsmap = 0xffaa;
2928 }
2929 txchainmask = 15;
2930 } else {
2931 if (dut->testbed_flag_txsp == 1) {
2932 vht_mcsmap = 0xffc0;
2933 dut->testbed_flag_txsp = 0;
2934 } else {
2935 vht_mcsmap = 0xffea;
2936 }
2937 }
2938
2939 if (txchainmask) {
2940 snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
2941 basedev, txchainmask);
2942 if (system(buf) != 0) {
2943 sigma_dut_print(dut, DUT_MSG_ERROR,
2944 "iwpriv txchainmask failed");
2945 }
2946 }
2947
2948 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
2949 intf, vht_mcsmap);
2950 if (system(buf) != 0) {
2951 sigma_dut_print(dut, DUT_MSG_ERROR,
2952 "iwpriv %s vht_mcsmap 0x%04x failed",
2953 intf, vht_mcsmap);
2954 }
2955}
2956
2957
2958static void ath_sta_set_rxsp_stream(struct sigma_dut *dut, const char *intf,
2959 const char *val)
2960{
2961 char buf[60];
2962 unsigned int vht_mcsmap = 0;
2963 int rxchainmask = 0;
2964 const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
2965
2966 if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
2967 if (dut->testbed_flag_rxsp == 1) {
2968 vht_mcsmap = 0xfffc;
2969 dut->testbed_flag_rxsp = 0;
2970 } else {
2971 vht_mcsmap = 0xfffe;
2972 }
2973 rxchainmask = 1;
2974 } else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
2975 if (dut->testbed_flag_rxsp == 1) {
2976 vht_mcsmap = 0xfff0;
2977 dut->testbed_flag_rxsp = 0;
2978 } else {
2979 vht_mcsmap = 0xfffa;
2980 }
2981 rxchainmask = 3;
2982 } else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
2983 if (dut->testbed_flag_rxsp == 1) {
2984 vht_mcsmap = 0xffc0;
2985 dut->testbed_flag_rxsp = 0;
2986 } else {
2987 vht_mcsmap = 0xffea;
2988 }
2989 rxchainmask = 7;
2990 } else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
2991 if (dut->testbed_flag_rxsp == 1) {
2992 vht_mcsmap = 0xff00;
2993 dut->testbed_flag_rxsp = 0;
2994 } else {
2995 vht_mcsmap = 0xffaa;
2996 }
2997 rxchainmask = 15;
2998 } else {
2999 if (dut->testbed_flag_rxsp == 1) {
3000 vht_mcsmap = 0xffc0;
3001 dut->testbed_flag_rxsp = 0;
3002 } else {
3003 vht_mcsmap = 0xffea;
3004 }
3005 }
3006
3007 if (rxchainmask) {
3008 snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
3009 basedev, rxchainmask);
3010 if (system(buf) != 0) {
3011 sigma_dut_print(dut, DUT_MSG_ERROR,
3012 "iwpriv rxchainmask failed");
3013 }
3014 }
3015
3016 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
3017 intf, vht_mcsmap);
3018 if (system(buf) != 0) {
3019 sigma_dut_print(dut, DUT_MSG_ERROR,
3020 "iwpriv %s vht_mcsmap 0x%04x",
3021 intf, vht_mcsmap);
3022 }
3023}
3024
3025
3026void ath_set_zero_crc(struct sigma_dut *dut, const char *val)
3027{
3028 if (strcasecmp(val, "enable") == 0) {
3029 if (system("athdiag --set --address=0x2a204 --and=0xbfffffff")
3030 != 0) {
3031 sigma_dut_print(dut, DUT_MSG_ERROR,
3032 "Disable BB_VHTSIGB_CRC_CALC failed");
3033 }
3034
3035 if (system("athdiag --set --address=0x2a204 --or=0x80000000")
3036 != 0) {
3037 sigma_dut_print(dut, DUT_MSG_ERROR,
3038 "Enable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
3039 }
3040 } else {
3041 if (system("athdiag --set --address=0x2a204 --and=0x7fffffff")
3042 != 0) {
3043 sigma_dut_print(dut, DUT_MSG_ERROR,
3044 "Disable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
3045 }
3046
3047 if (system("athdiag --set --address=0x2a204 --or=0x40000000")
3048 != 0) {
3049 sigma_dut_print(dut, DUT_MSG_ERROR,
3050 "Enable BB_VHTSIGB_CRC_CALC failed");
3051 }
3052 }
3053}
3054
3055
3056static int cmd_sta_set_wireless_common(const char *intf, struct sigma_dut *dut,
3057 struct sigma_conn *conn,
3058 struct sigma_cmd *cmd)
3059{
3060 const char *val;
3061 int ampdu = -1;
3062 char buf[30];
3063
3064 val = get_param(cmd, "40_INTOLERANT");
3065 if (val) {
3066 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3067 /* TODO: iwpriv ht40intol through wpa_supplicant */
3068 send_resp(dut, conn, SIGMA_ERROR,
3069 "ErrorCode,40_INTOLERANT not supported");
3070 return 0;
3071 }
3072 }
3073
3074 val = get_param(cmd, "ADDBA_REJECT");
3075 if (val) {
3076 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3077 /* reject any ADDBA with status "decline" */
3078 ampdu = 0;
3079 } else {
3080 /* accept ADDBA */
3081 ampdu = 1;
3082 }
3083 }
3084
3085 val = get_param(cmd, "AMPDU");
3086 if (val) {
3087 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3088 /* enable AMPDU Aggregation */
3089 if (ampdu == 0) {
3090 send_resp(dut, conn, SIGMA_ERROR,
3091 "ErrorCode,Mismatch in "
3092 "addba_reject/ampdu - "
3093 "not supported");
3094 return 0;
3095 }
3096 ampdu = 1;
3097 } else {
3098 /* disable AMPDU Aggregation */
3099 if (ampdu == 1) {
3100 send_resp(dut, conn, SIGMA_ERROR,
3101 "ErrorCode,Mismatch in "
3102 "addba_reject/ampdu - "
3103 "not supported");
3104 return 0;
3105 }
3106 ampdu = 0;
3107 }
3108 }
3109
3110 if (ampdu >= 0) {
3111 sigma_dut_print(dut, DUT_MSG_DEBUG, "%s A-MPDU aggregation",
3112 ampdu ? "Enabling" : "Disabling");
3113 snprintf(buf, sizeof(buf), "SET ampdu %d", ampdu);
3114 if (wpa_command(intf, buf) < 0) {
3115 send_resp(dut, conn, SIGMA_ERROR,
3116 "ErrorCode,set aggr failed");
3117 return 0;
3118 }
3119 }
3120
3121 val = get_param(cmd, "AMSDU");
3122 if (val) {
3123 switch (get_driver_type()) {
3124 case DRIVER_ATHEROS:
3125 ath_sta_set_amsdu(dut, intf, val);
3126 break;
3127 default:
3128 if (strcmp(val, "1") == 0 ||
3129 strcasecmp(val, "Enable") == 0) {
3130 /* Enable AMSDU Aggregation */
3131 send_resp(dut, conn, SIGMA_ERROR,
3132 "ErrorCode,AMSDU aggregation not supported");
3133 return 0;
3134 }
3135 break;
3136 }
3137 }
3138
3139 val = get_param(cmd, "STBC_RX");
3140 if (val) {
3141 switch (get_driver_type()) {
3142 case DRIVER_ATHEROS:
3143 ath_sta_set_stbc(dut, intf, val);
3144 break;
3145 default:
3146 send_resp(dut, conn, SIGMA_ERROR,
3147 "ErrorCode,STBC_RX not supported");
3148 return 0;
3149 }
3150 }
3151
3152 val = get_param(cmd, "WIDTH");
3153 if (val) {
3154 switch (get_driver_type()) {
3155 case DRIVER_WCN:
3156 if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
3157 send_resp(dut, conn, SIGMA_ERROR,
3158 "ErrorCode,Failed to set WIDTH");
3159 return 0;
3160 }
3161 break;
3162 case DRIVER_ATHEROS:
3163 if (ath_set_width(dut, conn, intf, val) < 0)
3164 return 0;
3165 break;
3166 default:
3167 sigma_dut_print(dut, DUT_MSG_ERROR,
3168 "Setting WIDTH not supported");
3169 break;
3170 }
3171 }
3172
3173 val = get_param(cmd, "SMPS");
3174 if (val) {
3175 /* TODO: Dynamic/0, Static/1, No Limit/2 */
3176 send_resp(dut, conn, SIGMA_ERROR,
3177 "ErrorCode,SMPS not supported");
3178 return 0;
3179 }
3180
3181 val = get_param(cmd, "TXSP_STREAM");
3182 if (val) {
3183 switch (get_driver_type()) {
3184 case DRIVER_WCN:
3185 if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
3186 send_resp(dut, conn, SIGMA_ERROR,
3187 "ErrorCode,Failed to set TXSP_STREAM");
3188 return 0;
3189 }
3190 break;
3191 case DRIVER_ATHEROS:
3192 ath_sta_set_txsp_stream(dut, intf, val);
3193 break;
3194 default:
3195 sigma_dut_print(dut, DUT_MSG_ERROR,
3196 "Setting TXSP_STREAM not supported");
3197 break;
3198 }
3199 }
3200
3201 val = get_param(cmd, "RXSP_STREAM");
3202 if (val) {
3203 switch (get_driver_type()) {
3204 case DRIVER_WCN:
3205 if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
3206 send_resp(dut, conn, SIGMA_ERROR,
3207 "ErrorCode,Failed to set RXSP_STREAM");
3208 return 0;
3209 }
3210 break;
3211 case DRIVER_ATHEROS:
3212 ath_sta_set_rxsp_stream(dut, intf, val);
3213 break;
3214 default:
3215 sigma_dut_print(dut, DUT_MSG_ERROR,
3216 "Setting RXSP_STREAM not supported");
3217 break;
3218 }
3219 }
3220
3221 val = get_param(cmd, "DYN_BW_SGNL");
3222 if (val) {
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003223 switch (get_driver_type()) {
3224 case DRIVER_WCN:
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003225 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
3226 if (system(buf) != 0) {
3227 sigma_dut_print(dut, DUT_MSG_ERROR,
3228 "Failed to set cts_cbw in DYN_BW_SGNL");
3229 return 0;
3230 }
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003231 break;
3232 case DRIVER_ATHEROS:
3233 ath_config_dyn_bw_sig(dut, intf, val);
3234 break;
3235 default:
3236 sigma_dut_print(dut, DUT_MSG_ERROR,
3237 "Failed to set DYN_BW_SGNL");
3238 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003239 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003240 }
3241
3242 val = get_param(cmd, "RTS_FORCE");
3243 if (val) {
3244 if (strcasecmp(val, "Enable") == 0) {
3245 snprintf(buf, sizeof(buf), "iwconfig %s rts 64", intf);
Priyadharshini Gowthamanabdb2122015-11-17 11:52:19 +02003246 if (system(buf) != 0) {
3247 sigma_dut_print(dut, DUT_MSG_ERROR,
3248 "Failed to set RTS_FORCE 64");
3249 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003250 } else if (strcasecmp(val, "Disable") == 0) {
3251 snprintf(buf, sizeof(buf), "iwconfig %s rts 2347",
3252 intf);
Priyadharshini Gowthamanabdb2122015-11-17 11:52:19 +02003253 if (system(buf) != 0) {
3254 sigma_dut_print(dut, DUT_MSG_ERROR,
3255 "Failed to set RTS_FORCE 2347");
3256 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003257 } else {
3258 send_resp(dut, conn, SIGMA_ERROR,
3259 "ErrorCode,RTS_FORCE value not supported");
3260 return 0;
3261 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003262 }
3263
3264 val = get_param(cmd, "CTS_WIDTH");
3265 if (val) {
3266 switch (get_driver_type()) {
3267 case DRIVER_WCN:
3268 if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
3269 send_resp(dut, conn, SIGMA_ERROR,
3270 "ErrorCode,Failed to set CTS_WIDTH");
3271 return 0;
3272 }
3273 break;
3274 case DRIVER_ATHEROS:
3275 ath_set_cts_width(dut, intf, val);
3276 break;
3277 default:
3278 sigma_dut_print(dut, DUT_MSG_ERROR,
3279 "Setting CTS_WIDTH not supported");
3280 break;
3281 }
3282 }
3283
3284 val = get_param(cmd, "BW_SGNL");
3285 if (val) {
3286 if (strcasecmp(val, "Enable") == 0) {
3287 snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1",
3288 intf);
3289 } else if (strcasecmp(val, "Disable") == 0) {
3290 /* TODO: Disable */
3291 buf[0] = '\0';
3292 } else {
3293 send_resp(dut, conn, SIGMA_ERROR,
3294 "ErrorCode,BW_SGNL value not supported");
3295 return 0;
3296 }
3297
3298 if (buf[0] != '\0' && system(buf) != 0) {
3299 sigma_dut_print(dut, DUT_MSG_ERROR,
3300 "Failed to set BW_SGNL");
3301 }
3302 }
3303
3304 val = get_param(cmd, "Band");
3305 if (val) {
3306 if (strcmp(val, "2.4") == 0 || strcmp(val, "5") == 0) {
3307 /* STA supports all bands by default */
3308 } else {
3309 send_resp(dut, conn, SIGMA_ERROR,
3310 "ErrorCode,Unsupported Band");
3311 return 0;
3312 }
3313 }
3314
3315 val = get_param(cmd, "zero_crc");
3316 if (val) {
3317 switch (get_driver_type()) {
3318 case DRIVER_ATHEROS:
3319 ath_set_zero_crc(dut, val);
3320 break;
3321 default:
3322 break;
3323 }
3324 }
3325
3326 return 1;
3327}
3328
3329
3330static int sta_set_60g_common(struct sigma_dut *dut, struct sigma_conn *conn,
3331 struct sigma_cmd *cmd)
3332{
3333 const char *val;
3334 char buf[100];
3335
3336 val = get_param(cmd, "MSDUSize");
3337 if (val) {
3338 int mtu;
3339
3340 dut->amsdu_size = atoi(val);
3341 if (dut->amsdu_size > IEEE80211_MAX_DATA_LEN_DMG ||
3342 dut->amsdu_size < IEEE80211_SNAP_LEN_DMG) {
3343 sigma_dut_print(dut, DUT_MSG_ERROR,
3344 "MSDUSize %d is above max %d or below min %d",
3345 dut->amsdu_size,
3346 IEEE80211_MAX_DATA_LEN_DMG,
3347 IEEE80211_SNAP_LEN_DMG);
3348 dut->amsdu_size = 0;
3349 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3350 }
3351
3352 mtu = dut->amsdu_size - IEEE80211_SNAP_LEN_DMG;
3353 sigma_dut_print(dut, DUT_MSG_DEBUG,
3354 "Setting amsdu_size to %d", mtu);
3355 snprintf(buf, sizeof(buf), "ifconfig %s mtu %d",
3356 get_station_ifname(), mtu);
3357
3358 if (system(buf) != 0) {
3359 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set %s",
3360 buf);
3361 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3362 }
3363 }
3364
3365 val = get_param(cmd, "BAckRcvBuf");
3366 if (val) {
3367 dut->back_rcv_buf = atoi(val);
3368 if (dut->back_rcv_buf == 0) {
3369 sigma_dut_print(dut, DUT_MSG_ERROR,
3370 "Failed to convert %s or value is 0",
3371 val);
3372 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3373 }
3374
3375 sigma_dut_print(dut, DUT_MSG_DEBUG,
3376 "Setting BAckRcvBuf to %s", val);
3377 }
3378
3379 return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
3380}
3381
3382
3383static int sta_pcp_start(struct sigma_dut *dut, struct sigma_conn *conn,
3384 struct sigma_cmd *cmd)
3385{
3386 int net_id;
3387 char *ifname;
3388 const char *val;
3389 char buf[100];
3390
3391 dut->mode = SIGMA_MODE_STATION;
3392 ifname = get_main_ifname();
3393 if (wpa_command(ifname, "PING") != 0) {
3394 sigma_dut_print(dut, DUT_MSG_ERROR, "Supplicant not running");
3395 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3396 }
3397
3398 wpa_command(ifname, "FLUSH");
3399 net_id = add_network_common(dut, conn, ifname, cmd);
3400 if (net_id < 0) {
3401 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add network");
3402 return net_id;
3403 }
3404
3405 /* TODO: mode=2 for the AP; in the future, replace for mode PCP */
3406 if (set_network(ifname, net_id, "mode", "2") < 0) {
3407 sigma_dut_print(dut, DUT_MSG_ERROR,
3408 "Failed to set supplicant network mode");
3409 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3410 }
3411
3412 sigma_dut_print(dut, DUT_MSG_DEBUG,
3413 "Supplicant set network with mode 2");
3414
3415 val = get_param(cmd, "Security");
3416 if (val && strcasecmp(val, "OPEN") == 0) {
3417 dut->ap_key_mgmt = AP_OPEN;
3418 if (set_network(ifname, net_id, "key_mgmt", "NONE") < 0) {
3419 sigma_dut_print(dut, DUT_MSG_ERROR,
3420 "Failed to set supplicant to %s security",
3421 val);
3422 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3423 }
3424 } else if (val && strcasecmp(val, "WPA2-PSK") == 0) {
3425 dut->ap_key_mgmt = AP_WPA2_PSK;
3426 if (set_network(ifname, net_id, "key_mgmt", "WPA-PSK") < 0) {
3427 sigma_dut_print(dut, DUT_MSG_ERROR,
3428 "Failed to set supplicant to %s security",
3429 val);
3430 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3431 }
3432
3433 if (set_network(ifname, net_id, "proto", "RSN") < 0) {
3434 sigma_dut_print(dut, DUT_MSG_ERROR,
3435 "Failed to set supplicant to proto RSN");
3436 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3437 }
3438 } else if (val) {
3439 sigma_dut_print(dut, DUT_MSG_ERROR,
3440 "Requested Security %s is not supported on 60GHz",
3441 val);
3442 return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
3443 }
3444
3445 val = get_param(cmd, "Encrypt");
3446 if (val && strcasecmp(val, "AES-GCMP") == 0) {
3447 if (set_network(ifname, net_id, "pairwise", "GCMP") < 0) {
3448 sigma_dut_print(dut, DUT_MSG_ERROR,
3449 "Failed to set supplicant to pairwise GCMP");
3450 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3451 }
3452 if (set_network(ifname, net_id, "group", "GCMP") < 0) {
3453 sigma_dut_print(dut, DUT_MSG_ERROR,
3454 "Failed to set supplicant to group GCMP");
3455 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3456 }
3457 } else if (val) {
3458 sigma_dut_print(dut, DUT_MSG_ERROR,
3459 "Requested Encrypt %s is not supported on 60 GHz",
3460 val);
3461 return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
3462 }
3463
3464 val = get_param(cmd, "PSK");
3465 if (val && set_network_quoted(ifname, net_id, "psk", val) < 0) {
3466 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set psk %s",
3467 val);
3468 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3469 }
3470
3471 /* Convert 60G channel to freq */
3472 switch (dut->ap_channel) {
3473 case 1:
3474 val = "58320";
3475 break;
3476 case 2:
3477 val = "60480";
3478 break;
3479 case 3:
3480 val = "62640";
3481 break;
3482 default:
3483 sigma_dut_print(dut, DUT_MSG_ERROR,
3484 "Failed to configure channel %d. Not supported",
3485 dut->ap_channel);
3486 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3487 }
3488
3489 if (set_network(ifname, net_id, "frequency", val) < 0) {
3490 sigma_dut_print(dut, DUT_MSG_ERROR,
3491 "Failed to set supplicant network frequency");
3492 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3493 }
3494
3495 sigma_dut_print(dut, DUT_MSG_DEBUG,
3496 "Supplicant set network with frequency");
3497
3498 snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", net_id);
3499 if (wpa_command(ifname, buf) < 0) {
3500 sigma_dut_print(dut, DUT_MSG_INFO,
3501 "Failed to select network id %d on %s",
3502 net_id, ifname);
3503 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3504 }
3505
3506 sigma_dut_print(dut, DUT_MSG_DEBUG, "Selected network");
3507
3508 return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
3509}
3510
3511
3512static int sta_set_60g_pcp(struct sigma_dut *dut, struct sigma_conn *conn,
3513 struct sigma_cmd *cmd)
3514{
3515 const char *val;
3516
3517 if (dut->dev_role != DEVROLE_PCP) {
3518 send_resp(dut, conn, SIGMA_INVALID,
3519 "ErrorCode,Invalid DevRole");
3520 return 0;
3521 }
3522
3523 val = get_param(cmd, "SSID");
3524 if (val) {
3525 if (strlen(val) > sizeof(dut->ap_ssid) - 1) {
3526 send_resp(dut, conn, SIGMA_INVALID,
3527 "ErrorCode,Invalid SSID");
3528 return -1;
3529 }
3530
3531 strncpy(dut->ap_ssid, val, sizeof(dut->ap_ssid));
3532 }
3533
3534 val = get_param(cmd, "CHANNEL");
3535 if (val) {
3536 const char *pos;
3537
3538 dut->ap_channel = atoi(val);
3539 pos = strchr(val, ';');
3540 if (pos) {
3541 pos++;
3542 dut->ap_channel_1 = atoi(pos);
3543 }
3544 }
3545
3546 switch (dut->ap_channel) {
3547 case 1:
3548 case 2:
3549 case 3:
3550 break;
3551 default:
3552 sigma_dut_print(dut, DUT_MSG_ERROR,
3553 "Channel %d is not supported", dut->ap_channel);
3554 send_resp(dut, conn, SIGMA_ERROR,
3555 "Requested channel is not supported");
3556 return -1;
3557 }
3558
3559 val = get_param(cmd, "BCNINT");
3560 if (val)
3561 dut->ap_bcnint = atoi(val);
3562
3563
3564 val = get_param(cmd, "ExtSchIE");
3565 if (val) {
3566 send_resp(dut, conn, SIGMA_ERROR,
3567 "ErrorCode,ExtSchIE is not supported yet");
3568 return -1;
3569 }
3570
3571 val = get_param(cmd, "AllocType");
3572 if (val) {
3573 send_resp(dut, conn, SIGMA_ERROR,
3574 "ErrorCode,AllocType is not supported yet");
3575 return -1;
3576 }
3577
3578 val = get_param(cmd, "PercentBI");
3579 if (val) {
3580 send_resp(dut, conn, SIGMA_ERROR,
3581 "ErrorCode,PercentBI is not supported yet");
3582 return -1;
3583 }
3584
3585 val = get_param(cmd, "CBAPOnly");
3586 if (val) {
3587 send_resp(dut, conn, SIGMA_ERROR,
3588 "ErrorCode,CBAPOnly is not supported yet");
3589 return -1;
3590 }
3591
3592 val = get_param(cmd, "AMPDU");
3593 if (val) {
3594 if (strcasecmp(val, "Enable") == 0)
3595 dut->ap_ampdu = 1;
3596 else if (strcasecmp(val, "Disable") == 0)
3597 dut->ap_ampdu = 2;
3598 else {
3599 send_resp(dut, conn, SIGMA_ERROR,
3600 "ErrorCode,AMPDU value is not Enable nor Disabled");
3601 return -1;
3602 }
3603 }
3604
3605 val = get_param(cmd, "AMSDU");
3606 if (val) {
3607 if (strcasecmp(val, "Enable") == 0)
3608 dut->ap_amsdu = 1;
3609 else if (strcasecmp(val, "Disable") == 0)
3610 dut->ap_amsdu = 2;
3611 }
3612
3613 val = get_param(cmd, "NumMSDU");
3614 if (val) {
3615 send_resp(dut, conn, SIGMA_ERROR,
3616 "ErrorCode, NumMSDU is not supported yet");
3617 return -1;
3618 }
3619
3620 val = get_param(cmd, "ABFTLRang");
3621 if (val) {
3622 sigma_dut_print(dut, DUT_MSG_DEBUG,
3623 "Ignoring ABFTLRang parameter since FW default is greater than 1");
3624 }
3625
3626 if (sta_pcp_start(dut, conn, cmd) < 0) {
3627 send_resp(dut, conn, SIGMA_ERROR,
3628 "ErrorCode, Can't start PCP role");
3629 return -1;
3630 }
3631
3632 return sta_set_60g_common(dut, conn, cmd);
3633}
3634
3635
3636static int sta_set_60g_sta(struct sigma_dut *dut, struct sigma_conn *conn,
3637 struct sigma_cmd *cmd)
3638{
3639 const char *val = get_param(cmd, "DiscoveryMode");
3640
3641 if (dut->dev_role != DEVROLE_STA) {
3642 send_resp(dut, conn, SIGMA_INVALID,
3643 "ErrorCode,Invalid DevRole");
3644 return 0;
3645 }
3646
3647 if (val) {
3648 sigma_dut_print(dut, DUT_MSG_DEBUG, "Discovery: %s", val);
3649 /* Ignore Discovery mode till Driver expose API. */
3650#if 0
3651 if (strcasecmp(val, "1") == 0) {
3652 send_resp(dut, conn, SIGMA_INVALID,
3653 "ErrorCode,DiscoveryMode 1 not supported");
3654 return 0;
3655 }
3656
3657 if (strcasecmp(val, "0") == 0) {
3658 /* OK */
3659 } else {
3660 send_resp(dut, conn, SIGMA_INVALID,
3661 "ErrorCode,DiscoveryMode not supported");
3662 return 0;
3663 }
3664#endif
3665 }
3666
3667 if (start_sta_mode(dut) != 0)
3668 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3669 return sta_set_60g_common(dut, conn, cmd);
3670}
3671
3672
3673static int cmd_sta_disconnect(struct sigma_dut *dut, struct sigma_conn *conn,
3674 struct sigma_cmd *cmd)
3675{
3676 const char *intf = get_param(cmd, "Interface");
3677 disconnect_station(dut);
3678 /* Try to ignore old scan results to avoid HS 2.0R2 test case failures
3679 * due to cached results. */
3680 wpa_command(intf, "SET ignore_old_scan_res 1");
3681 wpa_command(intf, "BSS_FLUSH");
3682 return 1;
3683}
3684
3685
3686static int cmd_sta_reassoc(struct sigma_dut *dut, struct sigma_conn *conn,
3687 struct sigma_cmd *cmd)
3688{
3689 const char *intf = get_param(cmd, "Interface");
3690 const char *bssid = get_param(cmd, "bssid");
3691 const char *val = get_param(cmd, "CHANNEL");
3692 struct wpa_ctrl *ctrl;
3693 char buf[100];
3694 int res;
3695 int chan = 0;
3696
3697 if (bssid == NULL) {
3698 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing bssid "
3699 "argument");
3700 return 0;
3701 }
3702
3703 if (val)
3704 chan = atoi(val);
3705
3706 if (wifi_chip_type != DRIVER_WCN && wifi_chip_type != DRIVER_AR6003) {
3707 /* The current network may be from sta_associate or
3708 * sta_hs2_associate
3709 */
3710 if (set_network(intf, dut->infra_network_id, "bssid", bssid) <
3711 0 ||
3712 set_network(intf, 0, "bssid", bssid) < 0)
3713 return -2;
3714 }
3715
3716 ctrl = open_wpa_mon(intf);
3717 if (ctrl == NULL) {
3718 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
3719 "wpa_supplicant monitor connection");
3720 return -1;
3721 }
3722
3723 if (wifi_chip_type == DRIVER_WCN) {
3724#ifdef ANDROID
3725 if (set_network(intf, dut->infra_network_id, "bssid", "any")
3726 < 0) {
3727 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
3728 "bssid to any during FASTREASSOC");
3729 return -2;
3730 }
3731 res = snprintf(buf, sizeof(buf), "DRIVER FASTREASSOC %s %d",
3732 bssid, chan);
3733 if (res > 0 && res < (int) sizeof(buf))
3734 res = wpa_command(intf, buf);
3735
3736 if (res < 0 || res >= (int) sizeof(buf)) {
3737 send_resp(dut, conn, SIGMA_ERROR,
3738 "errorCode,Failed to run DRIVER FASTREASSOC");
3739 wpa_ctrl_detach(ctrl);
3740 wpa_ctrl_close(ctrl);
3741 return 0;
3742 }
3743#else /* ANDROID */
3744 sigma_dut_print(dut, DUT_MSG_DEBUG,
3745 "Reassoc using iwpriv - skip chan=%d info",
3746 chan);
3747 snprintf(buf, sizeof(buf), "iwpriv %s reassoc", intf);
3748 if (system(buf) != 0) {
3749 sigma_dut_print(dut, DUT_MSG_ERROR, "%s failed", buf);
3750 wpa_ctrl_detach(ctrl);
3751 wpa_ctrl_close(ctrl);
3752 return 0;
3753 }
3754#endif /* ANDROID */
3755 sigma_dut_print(dut, DUT_MSG_INFO,
3756 "sta_reassoc: Run %s successful", buf);
3757 } else if (wpa_command(intf, "REASSOCIATE")) {
3758 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
3759 "request reassociation");
3760 wpa_ctrl_detach(ctrl);
3761 wpa_ctrl_close(ctrl);
3762 return 0;
3763 }
3764
3765 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
3766 buf, sizeof(buf));
3767
3768 wpa_ctrl_detach(ctrl);
3769 wpa_ctrl_close(ctrl);
3770
3771 if (res < 0) {
3772 sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
3773 return -1;
3774 }
3775
3776 return 1;
3777}
3778
3779
3780static void hs2_clear_credentials(const char *intf)
3781{
3782 wpa_command(intf, "REMOVE_CRED all");
3783}
3784
3785
3786static int sta_get_parameter_60g(struct sigma_dut *dut, struct sigma_conn *conn,
3787 struct sigma_cmd *cmd)
3788{
3789 char buf[MAX_CMD_LEN];
3790 char bss_list[MAX_CMD_LEN];
3791 const char *parameter = get_param(cmd, "Parameter");
3792
3793 if (parameter == NULL)
3794 return -1;
3795
3796 if (strcasecmp(parameter, "DiscoveredDevList") == 0) {
3797 char *bss_line;
3798 char *bss_id = NULL;
3799 const char *ifname = get_param(cmd, "Interface");
3800
3801 if (ifname == NULL) {
3802 sigma_dut_print(dut, DUT_MSG_INFO,
3803 "For get DiscoveredDevList need Interface name.");
3804 return -1;
3805 }
3806
3807 /*
3808 * Use "BSS RANGE=ALL MASK=0x2" which provides a list
3809 * of BSSIDs in "bssid=<BSSID>\n"
3810 */
3811 if (wpa_command_resp(ifname, "BSS RANGE=ALL MASK=0x2",
3812 bss_list,
3813 sizeof(bss_list)) < 0) {
3814 sigma_dut_print(dut, DUT_MSG_ERROR,
3815 "Failed to get bss list");
3816 return -1;
3817 }
3818
3819 sigma_dut_print(dut, DUT_MSG_DEBUG,
3820 "bss list for ifname:%s is:%s",
3821 ifname, bss_list);
3822
3823 snprintf(buf, sizeof(buf), "DeviceList");
3824 bss_line = strtok(bss_list, "\n");
3825 while (bss_line) {
3826 if (sscanf(bss_line, "bssid=%ms", &bss_id) > 0 &&
3827 bss_id) {
3828 int len;
3829
3830 len = snprintf(buf + strlen(buf),
3831 sizeof(buf) - strlen(buf),
3832 ",%s", bss_id);
3833 free(bss_id);
3834 bss_id = NULL;
3835 if (len < 0) {
3836 sigma_dut_print(dut,
3837 DUT_MSG_ERROR,
3838 "Failed to read BSSID");
3839 send_resp(dut, conn, SIGMA_ERROR,
3840 "ErrorCode,Failed to read BSS ID");
3841 return 0;
3842 }
3843
3844 if ((size_t) len >= sizeof(buf) - strlen(buf)) {
3845 sigma_dut_print(dut,
3846 DUT_MSG_ERROR,
3847 "Response buf too small for list");
3848 send_resp(dut, conn,
3849 SIGMA_ERROR,
3850 "ErrorCode,Response buf too small for list");
3851 return 0;
3852 }
3853 }
3854
3855 bss_line = strtok(NULL, "\n");
3856 }
3857
3858 sigma_dut_print(dut, DUT_MSG_INFO, "DiscoveredDevList is %s",
3859 buf);
3860 send_resp(dut, conn, SIGMA_COMPLETE, buf);
3861 return 0;
3862 }
3863
3864 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
3865 return 0;
3866}
3867
3868
3869static int cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
3870 struct sigma_cmd *cmd)
3871{
3872 const char *program = get_param(cmd, "Program");
3873
3874 if (program == NULL)
3875 return -1;
3876
3877 if (strcasecmp(program, "P2PNFC") == 0)
3878 return p2p_cmd_sta_get_parameter(dut, conn, cmd);
3879
3880 if (strcasecmp(program, "60ghz") == 0)
3881 return sta_get_parameter_60g(dut, conn, cmd);
3882
3883#ifdef ANDROID_NAN
3884 if (strcasecmp(program, "NAN") == 0)
3885 return nan_cmd_sta_exec_action(dut, conn, cmd);
3886#endif /* ANDROID_NAN */
3887
3888 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
3889 return 0;
3890}
3891
3892
3893static void sta_reset_default_ath(struct sigma_dut *dut, const char *intf,
3894 const char *type)
3895{
3896 char buf[100];
3897
3898 if (dut->program == PROGRAM_VHT) {
3899 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
3900 if (system(buf) != 0) {
3901 sigma_dut_print(dut, DUT_MSG_ERROR,
3902 "iwpriv %s chwidth failed", intf);
3903 }
3904
3905 snprintf(buf, sizeof(buf), "iwpriv %s mode 11ACVHT80", intf);
3906 if (system(buf) != 0) {
3907 sigma_dut_print(dut, DUT_MSG_ERROR,
3908 "iwpriv %s mode 11ACVHT80 failed",
3909 intf);
3910 }
3911
3912 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs -1", intf);
3913 if (system(buf) != 0) {
3914 sigma_dut_print(dut, DUT_MSG_ERROR,
3915 "iwpriv %s vhtmcs -1 failed", intf);
3916 }
3917 }
3918
3919 if (dut->program == PROGRAM_HT) {
3920 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
3921 if (system(buf) != 0) {
3922 sigma_dut_print(dut, DUT_MSG_ERROR,
3923 "iwpriv %s chwidth failed", intf);
3924 }
3925
3926 snprintf(buf, sizeof(buf), "iwpriv %s mode 11naht40", intf);
3927 if (system(buf) != 0) {
3928 sigma_dut_print(dut, DUT_MSG_ERROR,
3929 "iwpriv %s mode 11naht40 failed",
3930 intf);
3931 }
3932
3933 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0", intf);
3934 if (system(buf) != 0) {
3935 sigma_dut_print(dut, DUT_MSG_ERROR,
3936 "iwpriv set11NRates failed");
3937 }
3938 }
3939
3940 if (dut->program == PROGRAM_VHT || dut->program == PROGRAM_HT) {
3941 snprintf(buf, sizeof(buf), "iwpriv %s powersave 0", intf);
3942 if (system(buf) != 0) {
3943 sigma_dut_print(dut, DUT_MSG_ERROR,
3944 "disabling powersave failed");
3945 }
3946
3947 /* Reset CTS width */
3948 snprintf(buf, sizeof(buf), "wifitool %s beeliner_fw_test 54 0",
3949 intf);
3950 if (system(buf) != 0) {
3951 sigma_dut_print(dut, DUT_MSG_ERROR,
3952 "wifitool %s beeliner_fw_test 54 0 failed",
3953 intf);
3954 }
3955
3956 /* Enable Dynamic Bandwidth signalling by default */
3957 snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1", intf);
3958 if (system(buf) != 0) {
3959 sigma_dut_print(dut, DUT_MSG_ERROR,
3960 "iwpriv %s cwmenable 1 failed", intf);
3961 }
3962
3963 snprintf(buf, sizeof(buf), "iwconfig %s rts 2347", intf);
3964 if (system(buf) != 0) {
3965 sigma_dut_print(dut, DUT_MSG_ERROR,
3966 "iwpriv rts failed");
3967 }
3968 }
3969
3970 if (type && strcasecmp(type, "Testbed") == 0) {
3971 dut->testbed_flag_txsp = 1;
3972 dut->testbed_flag_rxsp = 1;
3973 /* STA has to set spatial stream to 2 per Appendix H */
3974 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0xfff0", intf);
3975 if (system(buf) != 0) {
3976 sigma_dut_print(dut, DUT_MSG_ERROR,
3977 "iwpriv vht_mcsmap failed");
3978 }
3979
3980 /* Disable LDPC per Appendix H */
3981 snprintf(buf, sizeof(buf), "iwpriv %s ldpc 0", intf);
3982 if (system(buf) != 0) {
3983 sigma_dut_print(dut, DUT_MSG_ERROR,
3984 "iwpriv %s ldpc 0 failed", intf);
3985 }
3986
3987 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
3988 if (system(buf) != 0) {
3989 sigma_dut_print(dut, DUT_MSG_ERROR,
3990 "iwpriv amsdu failed");
3991 }
3992
3993 /* TODO: Disable STBC 2x1 transmit and receive */
3994 snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc 0", intf);
3995 if (system(buf) != 0) {
3996 sigma_dut_print(dut, DUT_MSG_ERROR,
3997 "Disable tx_stbc 0 failed");
3998 }
3999
4000 snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc 0", intf);
4001 if (system(buf) != 0) {
4002 sigma_dut_print(dut, DUT_MSG_ERROR,
4003 "Disable rx_stbc 0 failed");
4004 }
4005
4006 /* STA has to disable Short GI per Appendix H */
4007 snprintf(buf, sizeof(buf), "iwpriv %s shortgi 0", intf);
4008 if (system(buf) != 0) {
4009 sigma_dut_print(dut, DUT_MSG_ERROR,
4010 "iwpriv %s shortgi 0 failed", intf);
4011 }
4012 }
4013
4014 if (type && strcasecmp(type, "DUT") == 0) {
4015 snprintf(buf, sizeof(buf), "iwpriv %s nss 3", intf);
4016 if (system(buf) != 0) {
4017 sigma_dut_print(dut, DUT_MSG_ERROR,
4018 "iwpriv %s nss 3 failed", intf);
4019 }
4020
4021 snprintf(buf, sizeof(buf), "iwpriv %s shortgi 1", intf);
4022 if (system(buf) != 0) {
4023 sigma_dut_print(dut, DUT_MSG_ERROR,
4024 "iwpriv %s shortgi 1 failed", intf);
4025 }
4026 }
4027}
4028
4029
4030static int cmd_sta_reset_default(struct sigma_dut *dut,
4031 struct sigma_conn *conn,
4032 struct sigma_cmd *cmd)
4033{
4034 int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn,
4035 struct sigma_cmd *cmd);
4036 const char *intf = get_param(cmd, "Interface");
4037 const char *type;
4038
4039 dut->program = sigma_program_to_enum(get_param(cmd, "prog"));
4040 dut->device_type = STA_unknown;
4041 type = get_param(cmd, "type");
4042 if (type && strcasecmp(type, "Testbed") == 0)
4043 dut->device_type = STA_testbed;
4044 if (type && strcasecmp(type, "DUT") == 0)
4045 dut->device_type = STA_dut;
4046
4047 if (dut->program == PROGRAM_TDLS) {
4048 /* Clear TDLS testing mode */
4049 wpa_command(intf, "SET tdls_disabled 0");
4050 wpa_command(intf, "SET tdls_testing 0");
4051 dut->no_tpk_expiration = 0;
4052 }
4053
4054 switch (get_driver_type()) {
4055 case DRIVER_ATHEROS:
4056 sta_reset_default_ath(dut, intf, type);
4057 break;
4058 default:
4059 break;
4060 }
4061
4062#ifdef ANDROID_NAN
4063 if (dut->program == PROGRAM_NAN)
4064 nan_cmd_sta_reset_default(dut, conn, cmd);
4065#endif /* ANDROID_NAN */
4066
4067 if (dut->program == PROGRAM_HS2_R2) {
4068 unlink("SP/wi-fi.org/pps.xml");
4069 if (system("rm -r SP/*") != 0) {
4070 }
4071 unlink("next-client-cert.pem");
4072 unlink("next-client-key.pem");
4073 }
4074
4075 if (dut->program == PROGRAM_60GHZ) {
4076 const char *dev_role = get_param(cmd, "DevRole");
4077
4078 if (!dev_role) {
4079 send_resp(dut, conn, SIGMA_ERROR,
4080 "errorCode,Missing DevRole argument");
4081 return 0;
4082 }
4083
4084 if (strcasecmp(dev_role, "STA") == 0)
4085 dut->dev_role = DEVROLE_STA;
4086 else if (strcasecmp(dev_role, "PCP") == 0)
4087 dut->dev_role = DEVROLE_PCP;
4088 else {
4089 send_resp(dut, conn, SIGMA_ERROR,
4090 "errorCode,Unknown DevRole");
4091 return 0;
4092 }
4093
4094 if (dut->device_type == STA_unknown) {
4095 sigma_dut_print(dut, DUT_MSG_ERROR,
4096 "Device type is not STA testbed or DUT");
4097 send_resp(dut, conn, SIGMA_ERROR,
4098 "errorCode,Unknown device type");
4099 return 0;
4100 }
4101 }
4102
4103 wpa_command(intf, "WPS_ER_STOP");
4104 wpa_command(intf, "FLUSH");
4105 wpa_command(intf, "SET radio_disabled 0");
4106
4107 if (dut->tmp_mac_addr && dut->set_macaddr) {
4108 dut->tmp_mac_addr = 0;
4109 if (system(dut->set_macaddr) != 0) {
4110 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to clear "
4111 "temporary MAC address");
4112 }
4113 }
4114
4115 set_ps(intf, dut, 0);
4116
4117 if (dut->program == PROGRAM_HS2 || dut->program == PROGRAM_HS2_R2) {
4118 wpa_command(intf, "SET interworking 1");
4119 wpa_command(intf, "SET hs20 1");
4120 }
4121
4122 if (dut->program == PROGRAM_HS2_R2) {
4123 wpa_command(intf, "SET pmf 1");
4124 } else {
4125 wpa_command(intf, "SET pmf 0");
4126 }
4127
4128 hs2_clear_credentials(intf);
4129 wpa_command(intf, "SET hessid 00:00:00:00:00:00");
4130 wpa_command(intf, "SET access_network_type 15");
4131
4132 static_ip_file(0, NULL, NULL, NULL);
4133 kill_dhcp_client(dut, intf);
4134 clear_ip_addr(dut, intf);
4135
4136 dut->er_oper_performed = 0;
4137 dut->er_oper_bssid[0] = '\0';
4138
Priyadharshini Gowthamana7dfd492015-11-09 14:34:08 -08004139 if (dut->program != PROGRAM_VHT)
4140 return cmd_sta_p2p_reset(dut, conn, cmd);
4141 return 1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004142}
4143
4144
4145static int cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
4146 struct sigma_cmd *cmd)
4147{
4148 const char *program = get_param(cmd, "Program");
4149
4150 if (program == NULL)
4151 return -1;
4152#ifdef ANDROID_NAN
4153 if (strcasecmp(program, "NAN") == 0)
4154 return nan_cmd_sta_get_events(dut, conn, cmd);
4155#endif /* ANDROID_NAN */
4156 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4157 return 0;
4158}
4159
4160
4161static int cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
4162 struct sigma_cmd *cmd)
4163{
4164 const char *program = get_param(cmd, "Prog");
4165
4166 if (program == NULL)
4167 return -1;
4168#ifdef ANDROID_NAN
4169 if (strcasecmp(program, "NAN") == 0)
4170 return nan_cmd_sta_exec_action(dut, conn, cmd);
4171#endif /* ANDROID_NAN */
4172 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4173 return 0;
4174}
4175
4176
4177static int cmd_sta_set_11n(struct sigma_dut *dut, struct sigma_conn *conn,
4178 struct sigma_cmd *cmd)
4179{
4180 const char *intf = get_param(cmd, "Interface");
4181 const char *val, *mcs32, *rate;
4182
4183 val = get_param(cmd, "GREENFIELD");
4184 if (val) {
4185 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
4186 /* Enable GD */
4187 send_resp(dut, conn, SIGMA_ERROR,
4188 "ErrorCode,GF not supported");
4189 return 0;
4190 }
4191 }
4192
4193 val = get_param(cmd, "SGI20");
4194 if (val) {
4195 switch (get_driver_type()) {
4196 case DRIVER_ATHEROS:
4197 ath_sta_set_sgi(dut, intf, val);
4198 break;
4199 default:
4200 send_resp(dut, conn, SIGMA_ERROR,
4201 "ErrorCode,SGI20 not supported");
4202 return 0;
4203 }
4204 }
4205
4206 mcs32 = get_param(cmd, "MCS32"); /* HT Duplicate Mode Enable/Disable */
4207 rate = get_param(cmd, "MCS_FIXEDRATE"); /* Fixed MCS rate (0..31) */
4208 if (mcs32 && rate) {
4209 /* TODO */
4210 send_resp(dut, conn, SIGMA_ERROR,
4211 "ErrorCode,MCS32,MCS_FIXEDRATE not supported");
4212 return 0;
4213 } else if (mcs32 && !rate) {
4214 /* TODO */
4215 send_resp(dut, conn, SIGMA_ERROR,
4216 "ErrorCode,MCS32 not supported");
4217 return 0;
4218 } else if (!mcs32 && rate) {
4219 switch (get_driver_type()) {
4220 case DRIVER_ATHEROS:
4221 ath_sta_set_11nrates(dut, intf, rate);
4222 break;
4223 default:
4224 send_resp(dut, conn, SIGMA_ERROR,
4225 "ErrorCode,MCS32_FIXEDRATE not supported");
4226 return 0;
4227 }
4228 }
4229
4230 return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
4231}
4232
4233
4234static int cmd_sta_set_wireless_vht(struct sigma_dut *dut,
4235 struct sigma_conn *conn,
4236 struct sigma_cmd *cmd)
4237{
4238 const char *intf = get_param(cmd, "Interface");
4239 const char *val;
4240 char buf[30];
4241 int tkip = -1;
4242 int wep = -1;
4243
4244 val = get_param(cmd, "SGI80");
4245 if (val) {
4246 int sgi80;
4247
4248 sgi80 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4249 snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi80);
4250 if (system(buf) != 0) {
4251 sigma_dut_print(dut, DUT_MSG_ERROR,
4252 "iwpriv shortgi failed");
4253 }
4254 }
4255
4256 val = get_param(cmd, "TxBF");
4257 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
4258 snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfee 1", intf);
4259 if (system(buf) != 0) {
4260 sigma_dut_print(dut, DUT_MSG_ERROR,
4261 "iwpriv vhtsubfee failed");
4262 }
4263 snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfer 1", intf);
4264 if (system(buf) != 0) {
4265 sigma_dut_print(dut, DUT_MSG_ERROR,
4266 "iwpriv vhtsubfer failed");
4267 }
4268 }
4269
4270 val = get_param(cmd, "MU_TxBF");
4271 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
4272 switch (get_driver_type()) {
4273 case DRIVER_ATHEROS:
4274 ath_sta_set_txsp_stream(dut, intf, "1SS");
4275 ath_sta_set_rxsp_stream(dut, intf, "1SS");
4276 case DRIVER_WCN:
4277 if (wcn_sta_set_sp_stream(dut, intf, "1SS") < 0) {
4278 send_resp(dut, conn, SIGMA_ERROR,
4279 "ErrorCode,Failed to set RX/TXSP_STREAM");
4280 return 0;
4281 }
4282 default:
4283 sigma_dut_print(dut, DUT_MSG_ERROR,
4284 "Setting SP_STREAM not supported");
4285 break;
4286 }
4287 snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfee 1", intf);
4288 if (system(buf) != 0) {
4289 sigma_dut_print(dut, DUT_MSG_ERROR,
4290 "iwpriv vhtmubfee failed");
4291 }
4292 snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfer 1", intf);
4293 if (system(buf) != 0) {
4294 sigma_dut_print(dut, DUT_MSG_ERROR,
4295 "iwpriv vhtmubfer failed");
4296 }
4297 }
4298
4299 val = get_param(cmd, "LDPC");
4300 if (val) {
4301 int ldpc;
4302
4303 ldpc = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4304 snprintf(buf, sizeof(buf), "iwpriv %s ldpc %d", intf, ldpc);
4305 if (system(buf) != 0) {
4306 sigma_dut_print(dut, DUT_MSG_ERROR,
4307 "iwpriv ldpc failed");
4308 }
4309 }
4310
4311 val = get_param(cmd, "opt_md_notif_ie");
4312 if (val) {
4313 char *result = NULL;
4314 char delim[] = ";";
4315 char token[30];
4316 int value, config_val = 0;
4317
4318 strncpy(token, val, sizeof(token));
4319 token[sizeof(token) - 1] = '\0';
4320 result = strtok(token, delim);
4321
4322 /* Extract the NSS information */
4323 if (result) {
4324 value = atoi(result);
4325 switch (value) {
4326 case 1:
4327 config_val = 1;
4328 break;
4329 case 2:
4330 config_val = 3;
4331 break;
4332 case 3:
4333 config_val = 7;
4334 break;
4335 case 4:
4336 config_val = 15;
4337 break;
4338 default:
4339 config_val = 3;
4340 break;
4341 }
4342
4343 snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
4344 intf, config_val);
4345 if (system(buf) != 0) {
4346 sigma_dut_print(dut, DUT_MSG_ERROR,
4347 "iwpriv rxchainmask failed");
4348 }
4349
4350 snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
4351 intf, config_val);
4352 if (system(buf) != 0) {
4353 sigma_dut_print(dut, DUT_MSG_ERROR,
4354 "iwpriv txchainmask failed");
4355 }
4356 }
4357
4358 /* Extract the channel width information */
4359 result = strtok(NULL, delim);
4360 if (result) {
4361 value = atoi(result);
4362 switch (value) {
4363 case 20:
4364 config_val = 0;
4365 break;
4366 case 40:
4367 config_val = 1;
4368 break;
4369 case 80:
4370 config_val = 2;
4371 break;
4372 case 160:
4373 config_val = 3;
4374 break;
4375 default:
4376 config_val = 2;
4377 break;
4378 }
4379
4380 dut->chwidth = config_val;
4381
4382 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
4383 intf, config_val);
4384 if (system(buf) != 0) {
4385 sigma_dut_print(dut, DUT_MSG_ERROR,
4386 "iwpriv chwidth failed");
4387 }
4388 }
4389
4390 snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", intf);
4391 if (system(buf) != 0) {
4392 sigma_dut_print(dut, DUT_MSG_ERROR,
4393 "iwpriv opmode_notify failed");
4394 }
4395 }
4396
4397 val = get_param(cmd, "nss_mcs_cap");
4398 if (val) {
4399 int nss, mcs;
4400 char token[20];
4401 char *result = NULL;
4402 unsigned int vht_mcsmap = 0;
4403
4404 strncpy(token, val, sizeof(token));
4405 token[sizeof(token) - 1] = '\0';
4406 result = strtok(token, ";");
4407 nss = atoi(result);
4408
4409 snprintf(buf, sizeof(buf), "iwpriv %s nss %d", intf, nss);
4410 if (system(buf) != 0) {
4411 sigma_dut_print(dut, DUT_MSG_ERROR,
4412 "iwpriv nss failed");
4413 }
4414
4415 result = strtok(NULL, ";");
4416 if (result == NULL) {
4417 sigma_dut_print(dut, DUT_MSG_ERROR,
4418 "VHTMCS NOT SPECIFIED!");
4419 return 0;
4420 }
4421 result = strtok(result, "-");
4422 result = strtok(NULL, "-");
4423 mcs = atoi(result);
4424
4425 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d", intf, mcs);
4426 if (system(buf) != 0) {
4427 sigma_dut_print(dut, DUT_MSG_ERROR,
4428 "iwpriv mcs failed");
4429 }
4430
4431 switch (nss) {
4432 case 1:
4433 switch (mcs) {
4434 case 7:
4435 vht_mcsmap = 0xfffc;
4436 break;
4437 case 8:
4438 vht_mcsmap = 0xfffd;
4439 break;
4440 case 9:
4441 vht_mcsmap = 0xfffe;
4442 break;
4443 default:
4444 vht_mcsmap = 0xfffe;
4445 break;
4446 }
4447 break;
4448 case 2:
4449 switch (mcs) {
4450 case 7:
4451 vht_mcsmap = 0xfff0;
4452 break;
4453 case 8:
4454 vht_mcsmap = 0xfff5;
4455 break;
4456 case 9:
4457 vht_mcsmap = 0xfffa;
4458 break;
4459 default:
4460 vht_mcsmap = 0xfffa;
4461 break;
4462 }
4463 break;
4464 case 3:
4465 switch (mcs) {
4466 case 7:
4467 vht_mcsmap = 0xffc0;
4468 break;
4469 case 8:
4470 vht_mcsmap = 0xffd5;
4471 break;
4472 case 9:
4473 vht_mcsmap = 0xffea;
4474 break;
4475 default:
4476 vht_mcsmap = 0xffea;
4477 break;
4478 }
4479 break;
4480 default:
4481 vht_mcsmap = 0xffea;
4482 break;
4483 }
4484 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
4485 intf, vht_mcsmap);
4486 if (system(buf) != 0) {
4487 sigma_dut_print(dut, DUT_MSG_ERROR,
4488 "iwpriv vht_mcsmap failed");
4489 }
4490 }
4491
4492 /* UNSUPPORTED: val = get_param(cmd, "Tx_lgi_rate"); */
4493
4494 val = get_param(cmd, "Vht_tkip");
4495 if (val)
4496 tkip = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4497
4498 val = get_param(cmd, "Vht_wep");
4499 if (val)
4500 wep = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4501
4502 if (tkip != -1 || wep != -1) {
4503 if ((tkip == 1 && wep != 0) || (wep == 1 && tkip != 0)) {
4504 snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 1",
4505 intf);
4506 } else if ((tkip == 0 && wep != 1) || (wep == 0 && tkip != 1)) {
4507 snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 0",
4508 intf);
4509 } else {
4510 sigma_dut_print(dut, DUT_MSG_ERROR,
4511 "ErrorCode,mixed mode of VHT TKIP/WEP not supported");
4512 return 0;
4513 }
4514
4515 if (system(buf) != 0) {
4516 sigma_dut_print(dut, DUT_MSG_ERROR,
4517 "iwpriv htweptkip failed");
4518 }
4519 }
4520
4521 val = get_param(cmd, "txBandwidth");
4522 if (val) {
4523 switch (get_driver_type()) {
4524 case DRIVER_ATHEROS:
4525 if (ath_set_width(dut, conn, intf, val) < 0) {
4526 send_resp(dut, conn, SIGMA_ERROR,
4527 "ErrorCode,Failed to set txBandwidth");
4528 return 0;
4529 }
4530 break;
4531 default:
4532 sigma_dut_print(dut, DUT_MSG_ERROR,
4533 "Setting txBandwidth not supported");
4534 break;
4535 }
4536 }
4537
4538 return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
4539}
4540
4541
4542static int sta_set_wireless_60g(struct sigma_dut *dut,
4543 struct sigma_conn *conn,
4544 struct sigma_cmd *cmd)
4545{
4546 const char *dev_role = get_param(cmd, "DevRole");
4547
4548 if (!dev_role) {
4549 send_resp(dut, conn, SIGMA_INVALID,
4550 "ErrorCode,DevRole not specified");
4551 return 0;
4552 }
4553
4554 if (strcasecmp(dev_role, "PCP") == 0)
4555 return sta_set_60g_pcp(dut, conn, cmd);
4556 if (strcasecmp(dev_role, "STA") == 0)
4557 return sta_set_60g_sta(dut, conn, cmd);
4558 send_resp(dut, conn, SIGMA_INVALID,
4559 "ErrorCode,DevRole not supported");
4560 return 0;
4561}
4562
4563
4564static int cmd_sta_set_wireless(struct sigma_dut *dut, struct sigma_conn *conn,
4565 struct sigma_cmd *cmd)
4566{
4567 const char *val;
4568
4569 val = get_param(cmd, "Program");
4570 if (val) {
4571 if (strcasecmp(val, "11n") == 0)
4572 return cmd_sta_set_11n(dut, conn, cmd);
4573 if (strcasecmp(val, "VHT") == 0)
4574 return cmd_sta_set_wireless_vht(dut, conn, cmd);
4575 if (strcasecmp(val, "60ghz") == 0)
4576 return sta_set_wireless_60g(dut, conn, cmd);
4577 send_resp(dut, conn, SIGMA_ERROR,
4578 "ErrorCode,Program value not supported");
4579 } else {
4580 send_resp(dut, conn, SIGMA_ERROR,
4581 "ErrorCode,Program argument not available");
4582 }
4583
4584 return 0;
4585}
4586
4587
4588static void ath_sta_inject_frame(struct sigma_dut *dut, const char *intf,
4589 int tid)
4590{
4591 char buf[100];
4592 int tid_to_dscp [] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 };
4593
4594 /*
4595 * Two ways to ensure that addba request with a
4596 * non zero TID could be sent out. EV 117296
4597 */
4598 snprintf(buf, sizeof(buf),
4599 "ping -c 8 -Q %d `arp -a | grep wlan0 | awk '{print $2}' | tr -d '()'`",
4600 tid);
4601 if (system(buf) != 0) {
4602 sigma_dut_print(dut, DUT_MSG_ERROR,
4603 "Ping did not send out");
4604 }
4605
4606 snprintf(buf, sizeof(buf),
4607 "iwconfig %s | grep Access | awk '{print $6}' > %s",
4608 intf, VI_QOS_TMP_FILE);
4609 if (system(buf) != 0)
4610 return;
4611
4612 snprintf(buf, sizeof(buf),
4613 "ifconfig %s | grep HWaddr | cut -b 39-56 >> %s",
4614 intf, VI_QOS_TMP_FILE);
4615 if (system(buf) != 0)
4616 sigma_dut_print(dut, DUT_MSG_ERROR, "HWaddr matching failed");
4617
4618 snprintf(buf,sizeof(buf), "sed -n '3,$p' %s >> %s",
4619 VI_QOS_REFFILE, VI_QOS_TMP_FILE);
4620 if (system(buf) != 0) {
4621 sigma_dut_print(dut, DUT_MSG_ERROR,
4622 "VI_QOS_TEMP_FILE generation error failed");
4623 }
4624 snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
4625 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
4626 if (system(buf) != 0) {
4627 sigma_dut_print(dut, DUT_MSG_ERROR,
4628 "VI_QOS_FILE generation failed");
4629 }
4630
4631 snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
4632 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
4633 if (system(buf) != 0) {
4634 sigma_dut_print(dut, DUT_MSG_ERROR,
4635 "VI_QOS_FILE generation failed");
4636 }
4637
4638 snprintf(buf, sizeof(buf), "ethinject %s %s", intf, VI_QOS_FILE);
4639 if (system(buf) != 0) {
4640 }
4641}
4642
4643
4644static int ath_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
4645 struct sigma_cmd *cmd)
4646{
4647 const char *intf = get_param(cmd, "Interface");
4648 const char *val;
4649 int tid = 0;
4650 char buf[100];
4651
4652 val = get_param(cmd, "TID");
4653 if (val) {
4654 tid = atoi(val);
4655 if (tid)
4656 ath_sta_inject_frame(dut, intf, tid);
4657 }
4658
4659 /* Command sequence for ADDBA request on Peregrine based devices */
4660 snprintf(buf, sizeof(buf), "iwpriv %s setaddbaoper 1", intf);
4661 if (system(buf) != 0) {
4662 sigma_dut_print(dut, DUT_MSG_ERROR,
4663 "iwpriv setaddbaoper failed");
4664 }
4665
4666 snprintf(buf, sizeof(buf), "wifitool %s senddelba 1 %d 1 4", intf, tid);
4667 if (system(buf) != 0) {
4668 sigma_dut_print(dut, DUT_MSG_ERROR,
4669 "wifitool senddelba failed");
4670 }
4671
4672 snprintf(buf, sizeof(buf), "wifitool %s sendaddba 1 %d 64", intf, tid);
4673 if (system(buf) != 0) {
4674 sigma_dut_print(dut, DUT_MSG_ERROR,
4675 "wifitool sendaddba failed");
4676 }
4677
4678 /* UNSUPPORTED: val = get_param(cmd, "Dest_mac"); */
4679
4680 return 1;
4681}
4682
4683
4684static int send_addba_60g(struct sigma_dut *dut, struct sigma_conn *conn,
4685 struct sigma_cmd *cmd)
4686{
4687 const char *val;
4688 int tid = 0;
4689 char buf[100];
4690
4691 val = get_param(cmd, "TID");
4692 if (val) {
4693 tid = atoi(val);
4694 if (tid != 0) {
4695 sigma_dut_print(dut, DUT_MSG_ERROR,
4696 "Ignore TID %d for send_addba use TID 0 for 60g since only 0 required on TX",
4697 tid);
4698 }
4699 }
4700
4701 val = get_param(cmd, "Dest_mac");
4702 if (!val) {
4703 sigma_dut_print(dut, DUT_MSG_ERROR,
4704 "Currently not supporting addba for 60G without Dest_mac");
4705 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
4706 }
4707
4708 snprintf(buf, sizeof(buf), "wil6210_addba_req.py %s %d",
4709 val, dut->back_rcv_buf);
4710 sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
4711
4712 if (system(buf) != 0) {
4713 sigma_dut_print(dut, DUT_MSG_ERROR,
4714 "Failed to send addba");
4715 return -1;
4716 }
4717
4718 return 1;
4719}
4720
4721
4722static int cmd_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
4723 struct sigma_cmd *cmd)
4724{
4725 switch (get_driver_type()) {
4726 case DRIVER_ATHEROS:
4727 return ath_sta_send_addba(dut, conn, cmd);
4728 case DRIVER_WIL6210:
4729 return send_addba_60g(dut, conn, cmd);
4730 default:
4731 /*
4732 * There is no driver specific implementation for other drivers.
4733 * Ignore the command and report COMPLETE since the following
4734 * throughput test operation will end up sending ADDBA anyway.
4735 */
4736 return 1;
4737 }
4738}
4739
4740
4741int inject_eth_frame(int s, const void *data, size_t len,
4742 unsigned short ethtype, char *dst, char *src)
4743{
4744 struct iovec iov[4] = {
4745 {
4746 .iov_base = dst,
4747 .iov_len = ETH_ALEN,
4748 },
4749 {
4750 .iov_base = src,
4751 .iov_len = ETH_ALEN,
4752 },
4753 {
4754 .iov_base = &ethtype,
4755 .iov_len = sizeof(unsigned short),
4756 },
4757 {
4758 .iov_base = (void *) data,
4759 .iov_len = len,
4760 }
4761 };
4762 struct msghdr msg = {
4763 .msg_name = NULL,
4764 .msg_namelen = 0,
4765 .msg_iov = iov,
4766 .msg_iovlen = 4,
4767 .msg_control = NULL,
4768 .msg_controllen = 0,
4769 .msg_flags = 0,
4770 };
4771
4772 return sendmsg(s, &msg, 0);
4773}
4774
4775#if defined(__linux__) || defined(__QNXNTO__)
4776
4777int inject_frame(int s, const void *data, size_t len, int encrypt)
4778{
4779#define IEEE80211_RADIOTAP_F_WEP 0x04
4780#define IEEE80211_RADIOTAP_F_FRAG 0x08
4781 unsigned char rtap_hdr[] = {
4782 0x00, 0x00, /* radiotap version */
4783 0x0e, 0x00, /* radiotap length */
4784 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
4785 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
4786 0x00, /* padding */
4787 0x00, 0x00, /* RX and TX flags to indicate that */
4788 0x00, 0x00, /* this is the injected frame directly */
4789 };
4790 struct iovec iov[2] = {
4791 {
4792 .iov_base = &rtap_hdr,
4793 .iov_len = sizeof(rtap_hdr),
4794 },
4795 {
4796 .iov_base = (void *) data,
4797 .iov_len = len,
4798 }
4799 };
4800 struct msghdr msg = {
4801 .msg_name = NULL,
4802 .msg_namelen = 0,
4803 .msg_iov = iov,
4804 .msg_iovlen = 2,
4805 .msg_control = NULL,
4806 .msg_controllen = 0,
4807 .msg_flags = 0,
4808 };
4809
4810 if (encrypt)
4811 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
4812
4813 return sendmsg(s, &msg, 0);
4814}
4815
4816
4817int open_monitor(const char *ifname)
4818{
4819#ifdef __QNXNTO__
4820 struct sockaddr_dl ll;
4821 int s;
4822
4823 memset(&ll, 0, sizeof(ll));
4824 ll.sdl_family = AF_LINK;
4825 ll.sdl_index = if_nametoindex(ifname);
4826 if (ll.sdl_index == 0) {
4827 perror("if_nametoindex");
4828 return -1;
4829 }
4830 s = socket(PF_INET, SOCK_RAW, 0);
4831#else /* __QNXNTO__ */
4832 struct sockaddr_ll ll;
4833 int s;
4834
4835 memset(&ll, 0, sizeof(ll));
4836 ll.sll_family = AF_PACKET;
4837 ll.sll_ifindex = if_nametoindex(ifname);
4838 if (ll.sll_ifindex == 0) {
4839 perror("if_nametoindex");
4840 return -1;
4841 }
4842 s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
4843#endif /* __QNXNTO__ */
4844 if (s < 0) {
4845 perror("socket[PF_PACKET,SOCK_RAW]");
4846 return -1;
4847 }
4848
4849 if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
4850 perror("monitor socket bind");
4851 close(s);
4852 return -1;
4853 }
4854
4855 return s;
4856}
4857
4858
4859static int hex2num(char c)
4860{
4861 if (c >= '0' && c <= '9')
4862 return c - '0';
4863 if (c >= 'a' && c <= 'f')
4864 return c - 'a' + 10;
4865 if (c >= 'A' && c <= 'F')
4866 return c - 'A' + 10;
4867 return -1;
4868}
4869
4870
4871int hwaddr_aton(const char *txt, unsigned char *addr)
4872{
4873 int i;
4874
4875 for (i = 0; i < 6; i++) {
4876 int a, b;
4877
4878 a = hex2num(*txt++);
4879 if (a < 0)
4880 return -1;
4881 b = hex2num(*txt++);
4882 if (b < 0)
4883 return -1;
4884 *addr++ = (a << 4) | b;
4885 if (i < 5 && *txt++ != ':')
4886 return -1;
4887 }
4888
4889 return 0;
4890}
4891
4892#endif /* defined(__linux__) || defined(__QNXNTO__) */
4893
4894enum send_frame_type {
4895 DISASSOC, DEAUTH, SAQUERY, AUTH, ASSOCREQ, REASSOCREQ, DLS_REQ
4896};
4897enum send_frame_protection {
4898 CORRECT_KEY, INCORRECT_KEY, UNPROTECTED
4899};
4900
4901
4902static int sta_inject_frame(struct sigma_dut *dut, struct sigma_conn *conn,
4903 enum send_frame_type frame,
4904 enum send_frame_protection protected,
4905 const char *dest)
4906{
4907#ifdef __linux__
4908 unsigned char buf[1000], *pos;
4909 int s, res;
4910 char bssid[20], addr[20];
4911 char result[32], ssid[100];
4912 size_t ssid_len;
4913
4914 if (get_wpa_status(get_station_ifname(), "wpa_state", result,
4915 sizeof(result)) < 0 ||
4916 strncmp(result, "COMPLETED", 9) != 0) {
4917 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Not connected");
4918 return 0;
4919 }
4920
4921 if (get_wpa_status(get_station_ifname(), "bssid", bssid, sizeof(bssid))
4922 < 0) {
4923 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
4924 "current BSSID");
4925 return 0;
4926 }
4927
4928 if (get_wpa_status(get_station_ifname(), "address", addr, sizeof(addr))
4929 < 0) {
4930 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
4931 "own MAC address");
4932 return 0;
4933 }
4934
4935 if (get_wpa_status(get_station_ifname(), "ssid", ssid, sizeof(ssid))
4936 < 0) {
4937 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
4938 "current SSID");
4939 return 0;
4940 }
4941 ssid_len = strlen(ssid);
4942
4943 pos = buf;
4944
4945 /* Frame Control */
4946 switch (frame) {
4947 case DISASSOC:
4948 *pos++ = 0xa0;
4949 break;
4950 case DEAUTH:
4951 *pos++ = 0xc0;
4952 break;
4953 case SAQUERY:
4954 *pos++ = 0xd0;
4955 break;
4956 case AUTH:
4957 *pos++ = 0xb0;
4958 break;
4959 case ASSOCREQ:
4960 *pos++ = 0x00;
4961 break;
4962 case REASSOCREQ:
4963 *pos++ = 0x20;
4964 break;
4965 case DLS_REQ:
4966 *pos++ = 0xd0;
4967 break;
4968 }
4969
4970 if (protected == INCORRECT_KEY)
4971 *pos++ = 0x40; /* Set Protected field to 1 */
4972 else
4973 *pos++ = 0x00;
4974
4975 /* Duration */
4976 *pos++ = 0x00;
4977 *pos++ = 0x00;
4978
4979 /* addr1 = DA (current AP) */
4980 hwaddr_aton(bssid, pos);
4981 pos += 6;
4982 /* addr2 = SA (own address) */
4983 hwaddr_aton(addr, pos);
4984 pos += 6;
4985 /* addr3 = BSSID (current AP) */
4986 hwaddr_aton(bssid, pos);
4987 pos += 6;
4988
4989 /* Seq# (to be filled by driver/mac80211) */
4990 *pos++ = 0x00;
4991 *pos++ = 0x00;
4992
4993 if (protected == INCORRECT_KEY) {
4994 /* CCMP parameters */
4995 memcpy(pos, "\x61\x01\x00\x20\x00\x10\x00\x00", 8);
4996 pos += 8;
4997 }
4998
4999 if (protected == INCORRECT_KEY) {
5000 switch (frame) {
5001 case DEAUTH:
5002 /* Reason code (encrypted) */
5003 memcpy(pos, "\xa7\x39", 2);
5004 pos += 2;
5005 break;
5006 case DISASSOC:
5007 /* Reason code (encrypted) */
5008 memcpy(pos, "\xa7\x39", 2);
5009 pos += 2;
5010 break;
5011 case SAQUERY:
5012 /* Category|Action|TransID (encrypted) */
5013 memcpy(pos, "\x6f\xbd\xe9\x4d", 4);
5014 pos += 4;
5015 break;
5016 default:
5017 return -1;
5018 }
5019
5020 /* CCMP MIC */
5021 memcpy(pos, "\xc8\xd8\x3b\x06\x5d\xb7\x25\x68", 8);
5022 pos += 8;
5023 } else {
5024 switch (frame) {
5025 case DEAUTH:
5026 /* reason code = 8 */
5027 *pos++ = 0x08;
5028 *pos++ = 0x00;
5029 break;
5030 case DISASSOC:
5031 /* reason code = 8 */
5032 *pos++ = 0x08;
5033 *pos++ = 0x00;
5034 break;
5035 case SAQUERY:
5036 /* Category - SA Query */
5037 *pos++ = 0x08;
5038 /* SA query Action - Request */
5039 *pos++ = 0x00;
5040 /* Transaction ID */
5041 *pos++ = 0x12;
5042 *pos++ = 0x34;
5043 break;
5044 case AUTH:
5045 /* Auth Alg (Open) */
5046 *pos++ = 0x00;
5047 *pos++ = 0x00;
5048 /* Seq# */
5049 *pos++ = 0x01;
5050 *pos++ = 0x00;
5051 /* Status code */
5052 *pos++ = 0x00;
5053 *pos++ = 0x00;
5054 break;
5055 case ASSOCREQ:
5056 /* Capability Information */
5057 *pos++ = 0x31;
5058 *pos++ = 0x04;
5059 /* Listen Interval */
5060 *pos++ = 0x0a;
5061 *pos++ = 0x00;
5062 /* SSID */
5063 *pos++ = 0x00;
5064 *pos++ = ssid_len;
5065 memcpy(pos, ssid, ssid_len);
5066 pos += ssid_len;
5067 /* Supported Rates */
5068 memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
5069 10);
5070 pos += 10;
5071 /* Extended Supported Rates */
5072 memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
5073 pos += 6;
5074 /* RSN */
5075 memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
5076 "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
5077 "\x00\x00\x00\x00\x0f\xac\x06", 28);
5078 pos += 28;
5079 break;
5080 case REASSOCREQ:
5081 /* Capability Information */
5082 *pos++ = 0x31;
5083 *pos++ = 0x04;
5084 /* Listen Interval */
5085 *pos++ = 0x0a;
5086 *pos++ = 0x00;
5087 /* Current AP */
5088 hwaddr_aton(bssid, pos);
5089 pos += 6;
5090 /* SSID */
5091 *pos++ = 0x00;
5092 *pos++ = ssid_len;
5093 memcpy(pos, ssid, ssid_len);
5094 pos += ssid_len;
5095 /* Supported Rates */
5096 memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
5097 10);
5098 pos += 10;
5099 /* Extended Supported Rates */
5100 memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
5101 pos += 6;
5102 /* RSN */
5103 memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
5104 "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
5105 "\x00\x00\x00\x00\x0f\xac\x06", 28);
5106 pos += 28;
5107 break;
5108 case DLS_REQ:
5109 /* Category - DLS */
5110 *pos++ = 0x02;
5111 /* DLS Action - Request */
5112 *pos++ = 0x00;
5113 /* Destination MACAddress */
5114 if (dest)
5115 hwaddr_aton(dest, pos);
5116 else
5117 memset(pos, 0, 6);
5118 pos += 6;
5119 /* Source MACAddress */
5120 hwaddr_aton(addr, pos);
5121 pos += 6;
5122 /* Capability Information */
5123 *pos++ = 0x10; /* Privacy */
5124 *pos++ = 0x06; /* QoS */
5125 /* DLS Timeout Value */
5126 *pos++ = 0x00;
5127 *pos++ = 0x01;
5128 /* Supported rates */
5129 *pos++ = 0x01;
5130 *pos++ = 0x08;
5131 *pos++ = 0x0c; /* 6 Mbps */
5132 *pos++ = 0x12; /* 9 Mbps */
5133 *pos++ = 0x18; /* 12 Mbps */
5134 *pos++ = 0x24; /* 18 Mbps */
5135 *pos++ = 0x30; /* 24 Mbps */
5136 *pos++ = 0x48; /* 36 Mbps */
5137 *pos++ = 0x60; /* 48 Mbps */
5138 *pos++ = 0x6c; /* 54 Mbps */
5139 /* TODO: Extended Supported Rates */
5140 /* TODO: HT Capabilities */
5141 break;
5142 }
5143 }
5144
5145 s = open_monitor("sigmadut");
5146 if (s < 0) {
5147 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
5148 "monitor socket");
5149 return 0;
5150 }
5151
5152 res = inject_frame(s, buf, pos - buf, protected == CORRECT_KEY);
5153 if (res < 0) {
5154 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
5155 "inject frame");
5156 return 0;
5157 }
5158 if (res < pos - buf) {
5159 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Only partial "
5160 "frame sent");
5161 return 0;
5162 }
5163
5164 close(s);
5165
5166 return 1;
5167#else /* __linux__ */
5168 send_resp(dut, conn, SIGMA_ERROR, "errorCode,sta_send_frame not "
5169 "yet supported");
5170 return 0;
5171#endif /* __linux__ */
5172}
5173
5174
5175static int cmd_sta_send_frame_tdls(struct sigma_dut *dut,
5176 struct sigma_conn *conn,
5177 struct sigma_cmd *cmd)
5178{
5179 const char *intf = get_param(cmd, "Interface");
5180 const char *sta, *val;
5181 unsigned char addr[ETH_ALEN];
5182 char buf[100];
5183
5184 sta = get_param(cmd, "peer");
5185 if (sta == NULL)
5186 sta = get_param(cmd, "station");
5187 if (sta == NULL) {
5188 send_resp(dut, conn, SIGMA_ERROR,
5189 "ErrorCode,Missing peer address");
5190 return 0;
5191 }
5192 if (hwaddr_aton(sta, addr) < 0) {
5193 send_resp(dut, conn, SIGMA_ERROR,
5194 "ErrorCode,Invalid peer address");
5195 return 0;
5196 }
5197
5198 val = get_param(cmd, "type");
5199 if (val == NULL)
5200 return -1;
5201
5202 if (strcasecmp(val, "DISCOVERY") == 0) {
5203 snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", sta);
5204 if (wpa_command(intf, buf) < 0) {
5205 send_resp(dut, conn, SIGMA_ERROR,
5206 "ErrorCode,Failed to send TDLS discovery");
5207 return 0;
5208 }
5209 return 1;
5210 }
5211
5212 if (strcasecmp(val, "SETUP") == 0) {
5213 int status = 0, timeout = 0;
5214
5215 val = get_param(cmd, "Status");
5216 if (val)
5217 status = atoi(val);
5218
5219 val = get_param(cmd, "Timeout");
5220 if (val)
5221 timeout = atoi(val);
5222
5223 if (status != 0 && status != 37) {
5224 send_resp(dut, conn, SIGMA_ERROR,
5225 "ErrorCode,Unsupported status value");
5226 return 0;
5227 }
5228
5229 if (timeout != 0 && timeout != 301) {
5230 send_resp(dut, conn, SIGMA_ERROR,
5231 "ErrorCode,Unsupported timeout value");
5232 return 0;
5233 }
5234
5235 if (status && timeout) {
5236 send_resp(dut, conn, SIGMA_ERROR,
5237 "ErrorCode,Unsupported timeout+status "
5238 "combination");
5239 return 0;
5240 }
5241
5242 if (status == 37 &&
5243 wpa_command(intf, "SET tdls_testing 0x200")) {
5244 send_resp(dut, conn, SIGMA_ERROR,
5245 "ErrorCode,Failed to enable "
5246 "decline setup response test mode");
5247 return 0;
5248 }
5249
5250 if (timeout == 301) {
5251 int res;
5252 if (dut->no_tpk_expiration)
5253 res = wpa_command(intf,
5254 "SET tdls_testing 0x108");
5255 else
5256 res = wpa_command(intf,
5257 "SET tdls_testing 0x8");
5258 if (res) {
5259 send_resp(dut, conn, SIGMA_ERROR,
5260 "ErrorCode,Failed to set short TPK "
5261 "lifetime");
5262 return 0;
5263 }
5264 }
5265
5266 snprintf(buf, sizeof(buf), "TDLS_SETUP %s", sta);
5267 if (wpa_command(intf, buf) < 0) {
5268 send_resp(dut, conn, SIGMA_ERROR,
5269 "ErrorCode,Failed to send TDLS setup");
5270 return 0;
5271 }
5272 return 1;
5273 }
5274
5275 if (strcasecmp(val, "TEARDOWN") == 0) {
5276 snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", sta);
5277 if (wpa_command(intf, buf) < 0) {
5278 send_resp(dut, conn, SIGMA_ERROR,
5279 "ErrorCode,Failed to send TDLS teardown");
5280 return 0;
5281 }
5282 return 1;
5283 }
5284
5285 send_resp(dut, conn, SIGMA_ERROR,
5286 "ErrorCode,Unsupported TDLS frame");
5287 return 0;
5288}
5289
5290
5291static int sta_ap_known(const char *ifname, const char *bssid)
5292{
5293 char buf[4096];
5294
5295 snprintf(buf, sizeof(buf), "BSS %s", bssid);
5296 if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
5297 return 0;
5298 if (strncmp(buf, "id=", 3) != 0)
5299 return 0;
5300 return 1;
5301}
5302
5303
5304static int sta_scan_ap(struct sigma_dut *dut, const char *ifname,
5305 const char *bssid)
5306{
5307 int res;
5308 struct wpa_ctrl *ctrl;
5309 char buf[256];
5310
5311 if (sta_ap_known(ifname, bssid))
5312 return 0;
5313 sigma_dut_print(dut, DUT_MSG_DEBUG,
5314 "AP not in BSS table - start scan");
5315
5316 ctrl = open_wpa_mon(ifname);
5317 if (ctrl == NULL) {
5318 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
5319 "wpa_supplicant monitor connection");
5320 return -1;
5321 }
5322
5323 if (wpa_command(ifname, "SCAN") < 0) {
5324 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to start scan");
5325 wpa_ctrl_detach(ctrl);
5326 wpa_ctrl_close(ctrl);
5327 return -1;
5328 }
5329
5330 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
5331 buf, sizeof(buf));
5332
5333 wpa_ctrl_detach(ctrl);
5334 wpa_ctrl_close(ctrl);
5335
5336 if (res < 0) {
5337 sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
5338 return -1;
5339 }
5340
5341 if (sta_ap_known(ifname, bssid))
5342 return 0;
5343 sigma_dut_print(dut, DUT_MSG_INFO, "AP not in BSS table");
5344 return -1;
5345}
5346
5347
5348static int cmd_sta_send_frame_hs2_neighadv(struct sigma_dut *dut,
5349 struct sigma_conn *conn,
5350 struct sigma_cmd *cmd,
5351 const char *intf)
5352{
5353 char buf[200];
5354
5355 snprintf(buf, sizeof(buf), "ndsend 2001:DB8::1 %s", intf);
5356 if (system(buf) != 0) {
5357 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to run "
5358 "ndsend");
5359 return 0;
5360 }
5361
5362 return 1;
5363}
5364
5365
5366static int cmd_sta_send_frame_hs2_neighsolreq(struct sigma_dut *dut,
5367 struct sigma_conn *conn,
5368 struct sigma_cmd *cmd,
5369 const char *intf)
5370{
5371 char buf[200];
5372 const char *ip = get_param(cmd, "SenderIP");
5373
5374 snprintf(buf, sizeof(buf), "ndisc6 -nm %s %s -r 4", ip, intf);
5375 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
5376 if (system(buf) == 0) {
5377 sigma_dut_print(dut, DUT_MSG_INFO,
5378 "Neighbor Solicitation got a response "
5379 "for %s@%s", ip, intf);
5380 }
5381
5382 return 1;
5383}
5384
5385
5386static int cmd_sta_send_frame_hs2_arpprobe(struct sigma_dut *dut,
5387 struct sigma_conn *conn,
5388 struct sigma_cmd *cmd,
5389 const char *ifname)
5390{
5391 char buf[200];
5392 const char *ip = get_param(cmd, "SenderIP");
5393
5394 if (ip == NULL) {
5395 send_resp(dut, conn, SIGMA_ERROR,
5396 "ErrorCode,Missing SenderIP parameter");
5397 return 0;
5398 }
5399 snprintf(buf, sizeof(buf), "arping -I %s -D %s -c 4", ifname, ip);
5400 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
5401 if (system(buf) != 0) {
5402 sigma_dut_print(dut, DUT_MSG_INFO, "arping DAD got a response "
5403 "for %s@%s", ip, ifname);
5404 }
5405
5406 return 1;
5407}
5408
5409
5410static int cmd_sta_send_frame_hs2_arpannounce(struct sigma_dut *dut,
5411 struct sigma_conn *conn,
5412 struct sigma_cmd *cmd,
5413 const char *ifname)
5414{
5415 char buf[200];
5416 char ip[16];
5417 int s;
5418
5419 s = socket(PF_INET, SOCK_DGRAM, 0);
5420 if (s >= 0) {
5421 struct ifreq ifr;
5422 struct sockaddr_in saddr;
5423
5424 memset(&ifr, 0, sizeof(ifr));
5425 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
5426 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
5427 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
5428 "%s IP address: %s",
5429 ifname, strerror(errno));
5430 return -1;
5431 } else {
5432 memcpy(&saddr, &ifr.ifr_addr,
5433 sizeof(struct sockaddr_in));
5434 strncpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
5435 }
5436 close(s);
5437
5438 }
5439
5440 snprintf(buf, sizeof(buf), "arping -I %s -s %s %s -c 4", ifname, ip,
5441 ip);
5442 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
5443 if (system(buf) != 0) {
5444 }
5445
5446 return 1;
5447}
5448
5449
5450static int cmd_sta_send_frame_hs2_arpreply(struct sigma_dut *dut,
5451 struct sigma_conn *conn,
5452 struct sigma_cmd *cmd,
5453 const char *ifname)
5454{
5455 char buf[200], addr[20];
5456 char dst[ETH_ALEN], src[ETH_ALEN];
5457 short ethtype = htons(ETH_P_ARP);
5458 char *pos;
5459 int s, res;
5460 const char *val;
5461 struct sockaddr_in taddr;
5462
5463 val = get_param(cmd, "dest");
5464 if (val)
5465 hwaddr_aton(val, (unsigned char *) dst);
5466
5467 val = get_param(cmd, "DestIP");
5468 if (val)
5469 inet_aton(val, &taddr.sin_addr);
5470
5471 if (get_wpa_status(get_station_ifname(), "address", addr,
5472 sizeof(addr)) < 0)
5473 return -2;
5474 hwaddr_aton(addr, (unsigned char *) src);
5475
5476 pos = buf;
5477 *pos++ = 0x00;
5478 *pos++ = 0x01;
5479 *pos++ = 0x08;
5480 *pos++ = 0x00;
5481 *pos++ = 0x06;
5482 *pos++ = 0x04;
5483 *pos++ = 0x00;
5484 *pos++ = 0x02;
5485 memcpy(pos, src, ETH_ALEN);
5486 pos += ETH_ALEN;
5487 memcpy(pos, &taddr.sin_addr, 4);
5488 pos += 4;
5489 memcpy(pos, dst, ETH_ALEN);
5490 pos += ETH_ALEN;
5491 memcpy(pos, &taddr.sin_addr, 4);
5492 pos += 4;
5493
5494 s = open_monitor(get_station_ifname());
5495 if (s < 0) {
5496 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
5497 "monitor socket");
5498 return 0;
5499 }
5500
5501 res = inject_eth_frame(s, buf, pos - buf, ethtype, dst, src);
5502 if (res < 0) {
5503 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
5504 "inject frame");
5505 return 0;
5506 }
5507
5508 close(s);
5509
5510 return 1;
5511}
5512
5513
5514static int cmd_sta_send_frame_hs2_dls_req(struct sigma_dut *dut,
5515 struct sigma_conn *conn,
5516 struct sigma_cmd *cmd,
5517 const char *intf, const char *dest)
5518{
5519 char buf[100];
5520
5521 if (if_nametoindex("sigmadut") == 0) {
5522 snprintf(buf, sizeof(buf),
5523 "iw dev %s interface add sigmadut type monitor",
5524 get_station_ifname());
5525 if (system(buf) != 0 ||
5526 if_nametoindex("sigmadut") == 0) {
5527 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
5528 "monitor interface with '%s'", buf);
5529 return -2;
5530 }
5531 }
5532
5533 if (system("ifconfig sigmadut up") != 0) {
5534 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
5535 "monitor interface up");
5536 return -2;
5537 }
5538
5539 return sta_inject_frame(dut, conn, DLS_REQ, UNPROTECTED, dest);
5540}
5541
5542
5543static int cmd_sta_send_frame_hs2(struct sigma_dut *dut,
5544 struct sigma_conn *conn,
5545 struct sigma_cmd *cmd)
5546{
5547 const char *intf = get_param(cmd, "Interface");
5548 const char *dest = get_param(cmd, "Dest");
5549 const char *type = get_param(cmd, "FrameName");
5550 const char *val;
5551 char buf[200], *pos, *end;
5552 int count, count2;
5553
5554 if (type == NULL)
5555 type = get_param(cmd, "Type");
5556
5557 if (intf == NULL || dest == NULL || type == NULL)
5558 return -1;
5559
5560 if (strcasecmp(type, "NeighAdv") == 0)
5561 return cmd_sta_send_frame_hs2_neighadv(dut, conn, cmd, intf);
5562
5563 if (strcasecmp(type, "NeighSolicitReq") == 0)
5564 return cmd_sta_send_frame_hs2_neighsolreq(dut, conn, cmd, intf);
5565
5566 if (strcasecmp(type, "ARPProbe") == 0)
5567 return cmd_sta_send_frame_hs2_arpprobe(dut, conn, cmd, intf);
5568
5569 if (strcasecmp(type, "ARPAnnounce") == 0)
5570 return cmd_sta_send_frame_hs2_arpannounce(dut, conn, cmd, intf);
5571
5572 if (strcasecmp(type, "ARPReply") == 0)
5573 return cmd_sta_send_frame_hs2_arpreply(dut, conn, cmd, intf);
5574
5575 if (strcasecmp(type, "DLS-request") == 0 ||
5576 strcasecmp(type, "DLSrequest") == 0)
5577 return cmd_sta_send_frame_hs2_dls_req(dut, conn, cmd, intf,
5578 dest);
5579
5580 if (strcasecmp(type, "ANQPQuery") != 0 &&
5581 strcasecmp(type, "Query") != 0) {
5582 send_resp(dut, conn, SIGMA_ERROR,
5583 "ErrorCode,Unsupported HS 2.0 send frame type");
5584 return 0;
5585 }
5586
5587 if (sta_scan_ap(dut, intf, dest) < 0) {
5588 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find "
5589 "the requested AP");
5590 return 0;
5591 }
5592
5593 pos = buf;
5594 end = buf + sizeof(buf);
5595 count = 0;
5596 pos += snprintf(pos, end - pos, "ANQP_GET %s ", dest);
5597
5598 val = get_param(cmd, "ANQP_CAP_LIST");
5599 if (val && atoi(val)) {
5600 pos += snprintf(pos, end - pos, "%s257", count > 0 ? "," : "");
5601 count++;
5602 }
5603
5604 val = get_param(cmd, "VENUE_NAME");
5605 if (val && atoi(val)) {
5606 pos += snprintf(pos, end - pos, "%s258", count > 0 ? "," : "");
5607 count++;
5608 }
5609
5610 val = get_param(cmd, "NETWORK_AUTH_TYPE");
5611 if (val && atoi(val)) {
5612 pos += snprintf(pos, end - pos, "%s260", count > 0 ? "," : "");
5613 count++;
5614 }
5615
5616 val = get_param(cmd, "ROAMING_CONS");
5617 if (val && atoi(val)) {
5618 pos += snprintf(pos, end - pos, "%s261", count > 0 ? "," : "");
5619 count++;
5620 }
5621
5622 val = get_param(cmd, "IP_ADDR_TYPE_AVAILABILITY");
5623 if (val && atoi(val)) {
5624 pos += snprintf(pos, end - pos, "%s262", count > 0 ? "," : "");
5625 count++;
5626 }
5627
5628 val = get_param(cmd, "NAI_REALM_LIST");
5629 if (val && atoi(val)) {
5630 pos += snprintf(pos, end - pos, "%s263", count > 0 ? "," : "");
5631 count++;
5632 }
5633
5634 val = get_param(cmd, "3GPP_INFO");
5635 if (val && atoi(val)) {
5636 pos += snprintf(pos, end - pos, "%s264", count > 0 ? "," : "");
5637 count++;
5638 }
5639
5640 val = get_param(cmd, "DOMAIN_LIST");
5641 if (val && atoi(val)) {
5642 pos += snprintf(pos, end - pos, "%s268", count > 0 ? "," : "");
5643 count++;
5644 }
5645
5646 if (count && wpa_command(intf, buf)) {
5647 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,ANQP_GET failed");
5648 return 0;
5649 }
5650
5651 pos = buf;
5652 end = buf + sizeof(buf);
5653 count2 = 0;
5654 pos += snprintf(pos, end - pos, "HS20_ANQP_GET %s ", dest);
5655
5656 val = get_param(cmd, "HS_CAP_LIST");
5657 if (val && atoi(val)) {
5658 pos += snprintf(pos, end - pos, "%s2", count2 > 0 ? "," : "");
5659 count2++;
5660 }
5661
5662 val = get_param(cmd, "OPER_NAME");
5663 if (val && atoi(val)) {
5664 pos += snprintf(pos, end - pos, "%s3", count2 > 0 ? "," : "");
5665 count2++;
5666 }
5667
5668 val = get_param(cmd, "WAN_METRICS");
5669 if (!val)
5670 val = get_param(cmd, "WAN_MAT");
5671 if (!val)
5672 val = get_param(cmd, "WAN_MET");
5673 if (val && atoi(val)) {
5674 pos += snprintf(pos, end - pos, "%s4", count2 > 0 ? "," : "");
5675 count2++;
5676 }
5677
5678 val = get_param(cmd, "CONNECTION_CAPABILITY");
5679 if (val && atoi(val)) {
5680 pos += snprintf(pos, end - pos, "%s5", count2 > 0 ? "," : "");
5681 count2++;
5682 }
5683
5684 val = get_param(cmd, "OP_CLASS");
5685 if (val && atoi(val)) {
5686 pos += snprintf(pos, end - pos, "%s7", count2 > 0 ? "," : "");
5687 count2++;
5688 }
5689
5690 val = get_param(cmd, "OSU_PROVIDER_LIST");
5691 if (val && atoi(val)) {
5692 pos += snprintf(pos, end - pos, "%s8", count2 > 0 ? "," : "");
5693 count2++;
5694 }
5695
5696 if (count && count2) {
5697 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before sending out "
5698 "second query");
5699 sleep(1);
5700 }
5701
5702 if (count2 && wpa_command(intf, buf)) {
5703 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,HS20_ANQP_GET "
5704 "failed");
5705 return 0;
5706 }
5707
5708 val = get_param(cmd, "NAI_HOME_REALM_LIST");
5709 if (val) {
5710 if (count || count2) {
5711 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
5712 "sending out second query");
5713 sleep(1);
5714 }
5715
5716 if (strcmp(val, "1") == 0)
5717 val = "mail.example.com";
5718 snprintf(buf, end - pos,
5719 "HS20_GET_NAI_HOME_REALM_LIST %s realm=%s",
5720 dest, val);
5721 if (wpa_command(intf, buf)) {
5722 send_resp(dut, conn, SIGMA_ERROR,
5723 "ErrorCode,HS20_GET_NAI_HOME_REALM_LIST "
5724 "failed");
5725 return 0;
5726 }
5727 }
5728
5729 val = get_param(cmd, "ICON_REQUEST");
5730 if (val) {
5731 if (count || count2) {
5732 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
5733 "sending out second query");
5734 sleep(1);
5735 }
5736
5737 snprintf(buf, end - pos,
5738 "HS20_ICON_REQUEST %s %s", dest, val);
5739 if (wpa_command(intf, buf)) {
5740 send_resp(dut, conn, SIGMA_ERROR,
5741 "ErrorCode,HS20_ICON_REQUEST failed");
5742 return 0;
5743 }
5744 }
5745
5746 return 1;
5747}
5748
5749
5750static int ath_sta_send_frame_vht(struct sigma_dut *dut,
5751 struct sigma_conn *conn,
5752 struct sigma_cmd *cmd)
5753{
5754 const char *val;
5755 char *ifname;
5756 char buf[100];
5757 int chwidth, nss;
5758
5759 val = get_param(cmd, "framename");
5760 if (!val)
5761 return -1;
5762 sigma_dut_print(dut, DUT_MSG_DEBUG, "framename is %s", val);
5763
5764 /* Command sequence to generate Op mode notification */
5765 if (val && strcasecmp(val, "Op_md_notif_frm") == 0) {
5766 ifname = get_station_ifname();
5767
5768 /* Disable STBC */
5769 snprintf(buf, sizeof(buf),
5770 "iwpriv %s tx_stbc 0", ifname);
5771 if (system(buf) != 0) {
5772 sigma_dut_print(dut, DUT_MSG_ERROR,
5773 "iwpriv tx_stbc 0 failed!");
5774 }
5775
5776 /* Extract Channel width */
5777 val = get_param(cmd, "Channel_width");
5778 if (val) {
5779 switch (atoi(val)) {
5780 case 20:
5781 chwidth = 0;
5782 break;
5783 case 40:
5784 chwidth = 1;
5785 break;
5786 case 80:
5787 chwidth = 2;
5788 break;
5789 case 160:
5790 chwidth = 3;
5791 break;
5792 default:
5793 chwidth = 2;
5794 break;
5795 }
5796
5797 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
5798 ifname, chwidth);
5799 if (system(buf) != 0) {
5800 sigma_dut_print(dut, DUT_MSG_ERROR,
5801 "iwpriv chwidth failed!");
5802 }
5803 }
5804
5805 /* Extract NSS */
5806 val = get_param(cmd, "NSS");
5807 if (val) {
5808 switch (atoi(val)) {
5809 case 1:
5810 nss = 1;
5811 break;
5812 case 2:
5813 nss = 3;
5814 break;
5815 case 3:
5816 nss = 7;
5817 break;
5818 default:
5819 /* We do not support NSS > 3 */
5820 nss = 3;
5821 break;
5822 }
5823 snprintf(buf, sizeof(buf),
5824 "iwpriv %s rxchainmask %d", ifname, nss);
5825 if (system(buf) != 0) {
5826 sigma_dut_print(dut, DUT_MSG_ERROR,
5827 "iwpriv rxchainmask failed!");
5828 }
5829 }
5830
5831 /* Opmode notify */
5832 snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", ifname);
5833 if (system(buf) != 0) {
5834 sigma_dut_print(dut, DUT_MSG_ERROR,
5835 "iwpriv opmode_notify failed!");
5836 } else {
5837 sigma_dut_print(dut, DUT_MSG_INFO,
5838 "Sent out the notify frame!");
5839 }
5840 }
5841
5842 return 1;
5843}
5844
5845
5846static int cmd_sta_send_frame_vht(struct sigma_dut *dut,
5847 struct sigma_conn *conn,
5848 struct sigma_cmd *cmd)
5849{
5850 switch (get_driver_type()) {
5851 case DRIVER_ATHEROS:
5852 return ath_sta_send_frame_vht(dut, conn, cmd);
5853 default:
5854 send_resp(dut, conn, SIGMA_ERROR,
5855 "errorCode,Unsupported sta_set_frame(VHT) with the current driver");
5856 return 0;
5857 }
5858}
5859
5860
5861int cmd_sta_send_frame(struct sigma_dut *dut, struct sigma_conn *conn,
5862 struct sigma_cmd *cmd)
5863{
5864 const char *intf = get_param(cmd, "Interface");
5865 const char *val;
5866 enum send_frame_type frame;
5867 enum send_frame_protection protected;
5868 char buf[100];
5869 unsigned char addr[ETH_ALEN];
5870 int res;
5871
5872 val = get_param(cmd, "program");
5873 if (val == NULL)
5874 val = get_param(cmd, "frame");
5875 if (val && strcasecmp(val, "TDLS") == 0)
5876 return cmd_sta_send_frame_tdls(dut, conn, cmd);
5877 if (val && (strcasecmp(val, "HS2") == 0 ||
5878 strcasecmp(val, "HS2-R2") == 0))
5879 return cmd_sta_send_frame_hs2(dut, conn, cmd);
5880 if (val && strcasecmp(val, "VHT") == 0)
5881 return cmd_sta_send_frame_vht(dut, conn, cmd);
5882
5883 val = get_param(cmd, "TD_DISC");
5884 if (val) {
5885 if (hwaddr_aton(val, addr) < 0)
5886 return -1;
5887 snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", val);
5888 if (wpa_command(intf, buf) < 0) {
5889 send_resp(dut, conn, SIGMA_ERROR,
5890 "ErrorCode,Failed to send TDLS discovery");
5891 return 0;
5892 }
5893 return 1;
5894 }
5895
5896 val = get_param(cmd, "TD_Setup");
5897 if (val) {
5898 if (hwaddr_aton(val, addr) < 0)
5899 return -1;
5900 snprintf(buf, sizeof(buf), "TDLS_SETUP %s", val);
5901 if (wpa_command(intf, buf) < 0) {
5902 send_resp(dut, conn, SIGMA_ERROR,
5903 "ErrorCode,Failed to start TDLS setup");
5904 return 0;
5905 }
5906 return 1;
5907 }
5908
5909 val = get_param(cmd, "TD_TearDown");
5910 if (val) {
5911 if (hwaddr_aton(val, addr) < 0)
5912 return -1;
5913 snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", val);
5914 if (wpa_command(intf, buf) < 0) {
5915 send_resp(dut, conn, SIGMA_ERROR,
5916 "ErrorCode,Failed to tear down TDLS link");
5917 return 0;
5918 }
5919 return 1;
5920 }
5921
5922 val = get_param(cmd, "TD_ChannelSwitch");
5923 if (val) {
5924 /* TODO */
5925 send_resp(dut, conn, SIGMA_ERROR,
5926 "ErrorCode,TD_ChannelSwitch not yet supported");
5927 return 0;
5928 }
5929
5930 val = get_param(cmd, "TD_NF");
5931 if (val) {
5932 /* TODO */
5933 send_resp(dut, conn, SIGMA_ERROR,
5934 "ErrorCode,TD_NF not yet supported");
5935 return 0;
5936 }
5937
5938 val = get_param(cmd, "PMFFrameType");
5939 if (val == NULL)
5940 val = get_param(cmd, "FrameName");
5941 if (val == NULL)
5942 val = get_param(cmd, "Type");
5943 if (val == NULL)
5944 return -1;
5945 if (strcasecmp(val, "disassoc") == 0)
5946 frame = DISASSOC;
5947 else if (strcasecmp(val, "deauth") == 0)
5948 frame = DEAUTH;
5949 else if (strcasecmp(val, "saquery") == 0)
5950 frame = SAQUERY;
5951 else if (strcasecmp(val, "auth") == 0)
5952 frame = AUTH;
5953 else if (strcasecmp(val, "assocreq") == 0)
5954 frame = ASSOCREQ;
5955 else if (strcasecmp(val, "reassocreq") == 0)
5956 frame = REASSOCREQ;
5957 else if (strcasecmp(val, "neigreq") == 0) {
5958 sigma_dut_print(dut, DUT_MSG_INFO, "Got neighbor request");
5959
5960 val = get_param(cmd, "ssid");
5961 if (val == NULL)
5962 return -1;
5963
5964 res = send_neighbor_request(dut, intf, val);
5965 if (res) {
5966 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
5967 "Failed to send neighbor report request");
5968 return 0;
5969 }
5970
5971 return 1;
5972 } else if (strcasecmp(val, "transmgmtquery") == 0) {
5973 sigma_dut_print(dut, DUT_MSG_DEBUG,
5974 "Got Transition Management Query");
5975
5976 val = get_param(cmd, "ssid");
5977 res = send_trans_mgmt_query(dut, intf, val);
5978 if (res) {
5979 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
5980 "Failed to send Transition Management Query");
5981 return 0;
5982 }
5983
5984 return 1;
5985 } else {
5986 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
5987 "PMFFrameType");
5988 return 0;
5989 }
5990
5991 val = get_param(cmd, "PMFProtected");
5992 if (val == NULL)
5993 val = get_param(cmd, "Protected");
5994 if (val == NULL)
5995 return -1;
5996 if (strcasecmp(val, "Correct-key") == 0 ||
5997 strcasecmp(val, "CorrectKey") == 0)
5998 protected = CORRECT_KEY;
5999 else if (strcasecmp(val, "IncorrectKey") == 0)
6000 protected = INCORRECT_KEY;
6001 else if (strcasecmp(val, "Unprotected") == 0)
6002 protected = UNPROTECTED;
6003 else {
6004 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6005 "PMFProtected");
6006 return 0;
6007 }
6008
6009 if (protected != UNPROTECTED &&
6010 (frame == AUTH || frame == ASSOCREQ || frame == REASSOCREQ)) {
6011 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Impossible "
6012 "PMFProtected for auth/assocreq/reassocreq");
6013 return 0;
6014 }
6015
6016 if (if_nametoindex("sigmadut") == 0) {
6017 snprintf(buf, sizeof(buf),
6018 "iw dev %s interface add sigmadut type monitor",
6019 get_station_ifname());
6020 if (system(buf) != 0 ||
6021 if_nametoindex("sigmadut") == 0) {
6022 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
6023 "monitor interface with '%s'", buf);
6024 return -2;
6025 }
6026 }
6027
6028 if (system("ifconfig sigmadut up") != 0) {
6029 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
6030 "monitor interface up");
6031 return -2;
6032 }
6033
6034 return sta_inject_frame(dut, conn, frame, protected, NULL);
6035}
6036
6037
6038static int cmd_sta_set_parameter_hs2(struct sigma_dut *dut,
6039 struct sigma_conn *conn,
6040 struct sigma_cmd *cmd,
6041 const char *ifname)
6042{
6043 char buf[200];
6044 const char *val;
6045
6046 val = get_param(cmd, "ClearARP");
6047 if (val && atoi(val) == 1) {
6048 snprintf(buf, sizeof(buf), "ip neigh flush dev %s", ifname);
6049 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6050 if (system(buf) != 0) {
6051 send_resp(dut, conn, SIGMA_ERROR,
6052 "errorCode,Failed to clear ARP cache");
6053 return 0;
6054 }
6055 }
6056
6057 return 1;
6058}
6059
6060
6061int cmd_sta_set_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
6062 struct sigma_cmd *cmd)
6063{
6064 const char *intf = get_param(cmd, "Interface");
6065 const char *val;
6066
6067 if (intf == NULL)
6068 return -1;
6069
6070 val = get_param(cmd, "program");
6071 if (val && (strcasecmp(val, "HS2") == 0 ||
6072 strcasecmp(val, "HS2-R2") == 0))
6073 return cmd_sta_set_parameter_hs2(dut, conn, cmd, intf);
6074
6075 return -1;
6076}
6077
6078
6079static int cmd_sta_set_macaddr(struct sigma_dut *dut, struct sigma_conn *conn,
6080 struct sigma_cmd *cmd)
6081{
6082 const char *intf = get_param(cmd, "Interface");
6083 const char *mac = get_param(cmd, "MAC");
6084
6085 if (intf == NULL || mac == NULL)
6086 return -1;
6087
6088 sigma_dut_print(dut, DUT_MSG_INFO, "Change local MAC address for "
6089 "interface %s to %s", intf, mac);
6090
6091 if (dut->set_macaddr) {
6092 char buf[128];
6093 int res;
6094 if (strcasecmp(mac, "default") == 0) {
6095 res = snprintf(buf, sizeof(buf), "%s",
6096 dut->set_macaddr);
6097 dut->tmp_mac_addr = 0;
6098 } else {
6099 res = snprintf(buf, sizeof(buf), "%s %s",
6100 dut->set_macaddr, mac);
6101 dut->tmp_mac_addr = 1;
6102 }
6103 if (res < 0 || res >= (int) sizeof(buf))
6104 return -1;
6105 if (system(buf) != 0) {
6106 send_resp(dut, conn, SIGMA_ERROR,
6107 "errorCode,Failed to set MAC "
6108 "address");
6109 return 0;
6110 }
6111 return 1;
6112 }
6113
6114 if (strcasecmp(mac, "default") == 0)
6115 return 1;
6116
6117 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6118 "command");
6119 return 0;
6120}
6121
6122
6123static int iwpriv_tdlsoffchnmode(struct sigma_dut *dut,
6124 struct sigma_conn *conn, const char *intf,
6125 int val)
6126{
6127 char buf[200];
6128 int res;
6129
6130 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchnmode %d",
6131 intf, val);
6132 if (res < 0 || res >= (int) sizeof(buf))
6133 return -1;
6134 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6135 if (system(buf) != 0) {
6136 send_resp(dut, conn, SIGMA_ERROR,
6137 "errorCode,Failed to configure offchannel mode");
6138 return 0;
6139 }
6140
6141 return 1;
6142}
6143
6144
6145enum sec_ch_offset {
6146 SEC_CH_NO,
6147 SEC_CH_40ABOVE,
6148 SEC_CH_40BELOW
6149};
6150
6151
6152static int off_chan_val(enum sec_ch_offset off)
6153{
6154 switch (off) {
6155 case SEC_CH_NO:
6156 return 0;
6157 case SEC_CH_40ABOVE:
6158 return 40;
6159 case SEC_CH_40BELOW:
6160 return -40;
6161 }
6162
6163 return 0;
6164}
6165
6166
6167static int iwpriv_set_offchan(struct sigma_dut *dut, struct sigma_conn *conn,
6168 const char *intf, int off_ch_num,
6169 enum sec_ch_offset sec)
6170{
6171 char buf[200];
6172 int res;
6173
6174 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchan %d",
6175 intf, off_ch_num);
6176 if (res < 0 || res >= (int) sizeof(buf))
6177 return -1;
6178 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6179 if (system(buf) != 0) {
6180 send_resp(dut, conn, SIGMA_ERROR,
6181 "errorCode,Failed to set offchan");
6182 return 0;
6183 }
6184
6185 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsecchnoffst %d",
6186 intf, off_chan_val(sec));
6187 if (res < 0 || res >= (int) sizeof(buf))
6188 return -1;
6189 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6190 if (system(buf) != 0) {
6191 send_resp(dut, conn, SIGMA_ERROR,
6192 "errorCode,Failed to set sec chan offset");
6193 return 0;
6194 }
6195
6196 return 1;
6197}
6198
6199
6200static int tdls_set_offchannel_offset(struct sigma_dut *dut,
6201 struct sigma_conn *conn,
6202 const char *intf, int off_ch_num,
6203 enum sec_ch_offset sec)
6204{
6205 char buf[200];
6206 int res;
6207
6208 res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNEL %d",
6209 off_ch_num);
6210 if (res < 0 || res >= (int) sizeof(buf))
6211 return -1;
6212 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6213
6214 if (wpa_command(intf, buf) < 0) {
6215 send_resp(dut, conn, SIGMA_ERROR,
6216 "ErrorCode,Failed to set offchan");
6217 return 0;
6218 }
6219 res = snprintf(buf, sizeof(buf), "DRIVER TDLSSECONDARYCHANNELOFFSET %d",
6220 off_chan_val(sec));
6221 if (res < 0 || res >= (int) sizeof(buf))
6222 return -1;
6223
6224 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6225
6226 if (wpa_command(intf, buf) < 0) {
6227 send_resp(dut, conn, SIGMA_ERROR,
6228 "ErrorCode,Failed to set sec chan offset");
6229 return 0;
6230 }
6231
6232 return 1;
6233}
6234
6235
6236static int tdls_set_offchannel_mode(struct sigma_dut *dut,
6237 struct sigma_conn *conn,
6238 const char *intf, int val)
6239{
6240 char buf[200];
6241 int res;
6242
6243 res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNELMODE %d",
6244 val);
6245 if (res < 0 || res >= (int) sizeof(buf))
6246 return -1;
6247 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6248
6249 if (wpa_command(intf, buf) < 0) {
6250 send_resp(dut, conn, SIGMA_ERROR,
6251 "ErrorCode,Failed to configure offchannel mode");
6252 return 0;
6253 }
6254
6255 return 1;
6256}
6257
6258
6259static int cmd_sta_set_rfeature_tdls(const char *intf, struct sigma_dut *dut,
6260 struct sigma_conn *conn,
6261 struct sigma_cmd *cmd)
6262{
6263 const char *val;
6264 enum {
6265 CHSM_NOT_SET,
6266 CHSM_ENABLE,
6267 CHSM_DISABLE,
6268 CHSM_REJREQ,
6269 CHSM_UNSOLRESP
6270 } chsm = CHSM_NOT_SET;
6271 int off_ch_num = -1;
6272 enum sec_ch_offset sec_ch = SEC_CH_NO;
6273 int res;
6274
6275 val = get_param(cmd, "Uapsd");
6276 if (val) {
6277 char buf[100];
6278 if (strcasecmp(val, "Enable") == 0)
6279 snprintf(buf, sizeof(buf), "SET ps 99");
6280 else if (strcasecmp(val, "Disable") == 0)
6281 snprintf(buf, sizeof(buf), "SET ps 98");
6282 else {
6283 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
6284 "Unsupported uapsd parameter value");
6285 return 0;
6286 }
6287 if (wpa_command(intf, buf)) {
6288 send_resp(dut, conn, SIGMA_ERROR,
6289 "ErrorCode,Failed to change U-APSD "
6290 "powersave mode");
6291 return 0;
6292 }
6293 }
6294
6295 val = get_param(cmd, "TPKTIMER");
6296 if (val && strcasecmp(val, "DISABLE") == 0) {
6297 if (wpa_command(intf, "SET tdls_testing 0x100")) {
6298 send_resp(dut, conn, SIGMA_ERROR,
6299 "ErrorCode,Failed to enable no TPK "
6300 "expiration test mode");
6301 return 0;
6302 }
6303 dut->no_tpk_expiration = 1;
6304 }
6305
6306 val = get_param(cmd, "ChSwitchMode");
6307 if (val) {
6308 if (strcasecmp(val, "Enable") == 0 ||
6309 strcasecmp(val, "Initiate") == 0)
6310 chsm = CHSM_ENABLE;
6311 else if (strcasecmp(val, "Disable") == 0 ||
6312 strcasecmp(val, "passive") == 0)
6313 chsm = CHSM_DISABLE;
6314 else if (strcasecmp(val, "RejReq") == 0)
6315 chsm = CHSM_REJREQ;
6316 else if (strcasecmp(val, "UnSolResp") == 0)
6317 chsm = CHSM_UNSOLRESP;
6318 else {
6319 send_resp(dut, conn, SIGMA_ERROR,
6320 "ErrorCode,Unknown ChSwitchMode value");
6321 return 0;
6322 }
6323 }
6324
6325 val = get_param(cmd, "OffChNum");
6326 if (val) {
6327 off_ch_num = atoi(val);
6328 if (off_ch_num == 0) {
6329 send_resp(dut, conn, SIGMA_ERROR,
6330 "ErrorCode,Invalid OffChNum");
6331 return 0;
6332 }
6333 }
6334
6335 val = get_param(cmd, "SecChOffset");
6336 if (val) {
6337 if (strcmp(val, "20") == 0)
6338 sec_ch = SEC_CH_NO;
6339 else if (strcasecmp(val, "40above") == 0)
6340 sec_ch = SEC_CH_40ABOVE;
6341 else if (strcasecmp(val, "40below") == 0)
6342 sec_ch = SEC_CH_40BELOW;
6343 else {
6344 send_resp(dut, conn, SIGMA_ERROR,
6345 "ErrorCode,Unknown SecChOffset value");
6346 return 0;
6347 }
6348 }
6349
6350 if (chsm == CHSM_NOT_SET) {
6351 /* no offchannel changes requested */
6352 return 1;
6353 }
6354
6355 if (strcmp(intf, get_main_ifname()) != 0 &&
6356 strcmp(intf, get_station_ifname()) != 0) {
6357 send_resp(dut, conn, SIGMA_ERROR,
6358 "ErrorCode,Unknown interface");
6359 return 0;
6360 }
6361
6362 switch (chsm) {
6363 case CHSM_NOT_SET:
6364 break;
6365 case CHSM_ENABLE:
6366 if (off_ch_num < 0) {
6367 send_resp(dut, conn, SIGMA_ERROR,
6368 "ErrorCode,Missing OffChNum argument");
6369 return 0;
6370 }
6371 if (wifi_chip_type == DRIVER_WCN) {
6372 res = tdls_set_offchannel_offset(dut, conn, intf,
6373 off_ch_num, sec_ch);
6374 } else {
6375 res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
6376 sec_ch);
6377 }
6378 if (res != 1)
6379 return res;
6380 if (wifi_chip_type == DRIVER_WCN)
6381 res = tdls_set_offchannel_mode(dut, conn, intf, 1);
6382 else
6383 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 1);
6384 break;
6385 case CHSM_DISABLE:
6386 if (wifi_chip_type == DRIVER_WCN)
6387 res = tdls_set_offchannel_mode(dut, conn, intf, 2);
6388 else
6389 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 2);
6390 break;
6391 case CHSM_REJREQ:
6392 if (wifi_chip_type == DRIVER_WCN)
6393 res = tdls_set_offchannel_mode(dut, conn, intf, 3);
6394 else
6395 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 3);
6396 break;
6397 case CHSM_UNSOLRESP:
6398 if (off_ch_num < 0) {
6399 send_resp(dut, conn, SIGMA_ERROR,
6400 "ErrorCode,Missing OffChNum argument");
6401 return 0;
6402 }
6403 if (wifi_chip_type == DRIVER_WCN) {
6404 res = tdls_set_offchannel_offset(dut, conn, intf,
6405 off_ch_num, sec_ch);
6406 } else {
6407 res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
6408 sec_ch);
6409 }
6410 if (res != 1)
6411 return res;
6412 if (wifi_chip_type == DRIVER_WCN)
6413 res = tdls_set_offchannel_mode(dut, conn, intf, 4);
6414 else
6415 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 4);
6416 break;
6417 }
6418
6419 return res;
6420}
6421
6422
6423static int ath_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
6424 struct sigma_conn *conn,
6425 struct sigma_cmd *cmd)
6426{
6427 const char *val;
6428 char *token, *result;
6429
6430 val = get_param(cmd, "nss_mcs_opt");
6431 if (val) {
6432 /* String (nss_operating_mode; mcs_operating_mode) */
6433 int nss, mcs;
6434 char buf[50];
6435
6436 token = strdup(val);
6437 if (!token)
6438 return 0;
6439 result = strtok(token, ";");
6440 if (strcasecmp(result, "def") != 0) {
6441 nss = atoi(result);
6442 if (nss == 4)
6443 ath_disable_txbf(dut, intf);
6444 snprintf(buf, sizeof(buf), "iwpriv %s nss %d",
6445 intf, nss);
6446 if (system(buf) != 0) {
6447 sigma_dut_print(dut, DUT_MSG_ERROR,
6448 "iwpriv nss failed");
6449 goto failed;
6450 }
6451 }
6452
6453 result = strtok(NULL, ";");
6454 if (strcasecmp(result, "def") == 0) {
6455 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0",
6456 intf);
6457 if (system(buf) != 0) {
6458 sigma_dut_print(dut, DUT_MSG_ERROR,
6459 "iwpriv set11NRates failed");
6460 goto failed;
6461 }
6462
6463 } else {
6464 mcs = atoi(result);
6465 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d",
6466 intf, mcs);
6467 if (system(buf) != 0) {
6468 sigma_dut_print(dut, DUT_MSG_ERROR,
6469 "iwpriv vhtmcs failed");
6470 goto failed;
6471 }
6472 }
6473 /* Channel width gets messed up, fix this */
6474 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
6475 intf, dut->chwidth);
6476 if (system(buf) != 0) {
6477 sigma_dut_print(dut, DUT_MSG_ERROR,
6478 "iwpriv chwidth failed");
6479 }
6480 }
6481
6482 return 1;
6483failed:
6484 free(token);
6485 return 0;
6486}
6487
6488
6489static int cmd_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
6490 struct sigma_conn *conn,
6491 struct sigma_cmd *cmd)
6492{
6493 switch (get_driver_type()) {
6494 case DRIVER_ATHEROS:
6495 return ath_sta_set_rfeature_vht(intf, dut, conn, cmd);
6496 default:
6497 send_resp(dut, conn, SIGMA_ERROR,
6498 "errorCode,Unsupported sta_set_rfeature(VHT) with the current driver");
6499 return 0;
6500 }
6501}
6502
6503
6504static int cmd_sta_set_rfeature(struct sigma_dut *dut, struct sigma_conn *conn,
6505 struct sigma_cmd *cmd)
6506{
6507 const char *intf = get_param(cmd, "Interface");
6508 const char *prog = get_param(cmd, "Prog");
6509
6510 if (intf == NULL || prog == NULL)
6511 return -1;
6512
6513 if (strcasecmp(prog, "TDLS") == 0)
6514 return cmd_sta_set_rfeature_tdls(intf, dut, conn, cmd);
6515
6516 if (strcasecmp(prog, "VHT") == 0)
6517 return cmd_sta_set_rfeature_vht(intf, dut, conn, cmd);
6518
6519 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported Prog");
6520 return 0;
6521}
6522
6523
6524static int cmd_sta_set_radio(struct sigma_dut *dut, struct sigma_conn *conn,
6525 struct sigma_cmd *cmd)
6526{
6527 const char *intf = get_param(cmd, "Interface");
6528 const char *mode = get_param(cmd, "Mode");
6529 int res;
6530
6531 if (intf == NULL || mode == NULL)
6532 return -1;
6533
6534 if (strcasecmp(mode, "On") == 0)
6535 res = wpa_command(intf, "SET radio_disabled 0");
6536 else if (strcasecmp(mode, "Off") == 0)
6537 res = wpa_command(intf, "SET radio_disabled 1");
6538 else
6539 return -1;
6540
6541 if (res) {
6542 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
6543 "radio mode");
6544 return 0;
6545 }
6546
6547 return 1;
6548}
6549
6550
6551static int cmd_sta_set_pwrsave(struct sigma_dut *dut, struct sigma_conn *conn,
6552 struct sigma_cmd *cmd)
6553{
6554 const char *intf = get_param(cmd, "Interface");
6555 const char *mode = get_param(cmd, "Mode");
6556 int res;
6557
6558 if (intf == NULL || mode == NULL)
6559 return -1;
6560
6561 if (strcasecmp(mode, "On") == 0)
6562 res = set_ps(intf, dut, 1);
6563 else if (strcasecmp(mode, "Off") == 0)
6564 res = set_ps(intf, dut, 0);
6565 else
6566 return -1;
6567
6568 if (res) {
6569 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
6570 "power save mode");
6571 return 0;
6572 }
6573
6574 return 1;
6575}
6576
6577
6578static int cmd_sta_bssid_pool(struct sigma_dut *dut, struct sigma_conn *conn,
6579 struct sigma_cmd *cmd)
6580{
6581 const char *intf = get_param(cmd, "Interface");
6582 const char *val, *bssid;
6583 int res;
6584 char *buf;
6585 size_t buf_len;
6586
6587 val = get_param(cmd, "BSSID_FILTER");
6588 if (val == NULL)
6589 return -1;
6590
6591 bssid = get_param(cmd, "BSSID_List");
6592 if (atoi(val) == 0 || bssid == NULL) {
6593 /* Disable BSSID filter */
6594 if (wpa_command(intf, "SET bssid_filter ")) {
6595 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed "
6596 "to disable BSSID filter");
6597 return 0;
6598 }
6599
6600 return 1;
6601 }
6602
6603 buf_len = 100 + strlen(bssid);
6604 buf = malloc(buf_len);
6605 if (buf == NULL)
6606 return -1;
6607
6608 snprintf(buf, buf_len, "SET bssid_filter %s", bssid);
6609 res = wpa_command(intf, buf);
6610 free(buf);
6611 if (res) {
6612 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to enable "
6613 "BSSID filter");
6614 return 0;
6615 }
6616
6617 return 1;
6618}
6619
6620
6621static int cmd_sta_reset_parm(struct sigma_dut *dut, struct sigma_conn *conn,
6622 struct sigma_cmd *cmd)
6623{
6624 const char *intf = get_param(cmd, "Interface");
6625 const char *val;
6626
6627 /* TODO: ARP */
6628
6629 val = get_param(cmd, "HS2_CACHE_PROFILE");
6630 if (val && strcasecmp(val, "All") == 0)
6631 hs2_clear_credentials(intf);
6632
6633 return 1;
6634}
6635
6636
6637static int cmd_sta_get_key(struct sigma_dut *dut, struct sigma_conn *conn,
6638 struct sigma_cmd *cmd)
6639{
6640 const char *intf = get_param(cmd, "Interface");
6641 const char *key_type = get_param(cmd, "KeyType");
6642 char buf[100], resp[200];
6643
6644 if (key_type == NULL)
6645 return -1;
6646
6647 if (strcasecmp(key_type, "GTK") == 0) {
6648 if (wpa_command_resp(intf, "GET gtk", buf, sizeof(buf)) < 0 ||
6649 strncmp(buf, "FAIL", 4) == 0) {
6650 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
6651 "not fetch current GTK");
6652 return 0;
6653 }
6654 snprintf(resp, sizeof(resp), "KeyValue,%s", buf);
6655 send_resp(dut, conn, SIGMA_COMPLETE, resp);
6656 return 0;
6657 } else {
6658 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6659 "KeyType");
6660 return 0;
6661 }
6662
6663 return 1;
6664}
6665
6666
6667static int hs2_set_policy(struct sigma_dut *dut)
6668{
6669#ifdef ANDROID
6670 system("ip rule del prio 23000");
6671 if (system("ip rule add from all lookup main prio 23000") != 0) {
6672 sigma_dut_print(dut, DUT_MSG_ERROR,
6673 "Failed to run:ip rule add from all lookup main prio");
6674 return -1;
6675 }
6676 if (system("ip route flush cache") != 0) {
6677 sigma_dut_print(dut, DUT_MSG_ERROR,
6678 "Failed to run ip route flush cache");
6679 return -1;
6680 }
6681 return 1;
6682#else /* ANDROID */
6683 return 0;
6684#endif /* ANDROID */
6685}
6686
6687
6688static int cmd_sta_hs2_associate(struct sigma_dut *dut,
6689 struct sigma_conn *conn,
6690 struct sigma_cmd *cmd)
6691{
6692 const char *intf = get_param(cmd, "Interface");
6693 const char *val = get_param(cmd, "Ignore_blacklist");
6694 struct wpa_ctrl *ctrl;
6695 int res;
6696 char bssid[20], ssid[40], resp[100], buf[100], blacklisted[100];
6697 int tries = 0;
6698 int ignore_blacklist = 0;
6699 const char *events[] = {
6700 "CTRL-EVENT-CONNECTED",
6701 "INTERWORKING-BLACKLISTED",
6702 "INTERWORKING-NO-MATCH",
6703 NULL
6704 };
6705
6706 start_sta_mode(dut);
6707
6708 blacklisted[0] = '\0';
6709 if (val && atoi(val))
6710 ignore_blacklist = 1;
6711
6712try_again:
6713 ctrl = open_wpa_mon(intf);
6714 if (ctrl == NULL) {
6715 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
6716 "wpa_supplicant monitor connection");
6717 return -2;
6718 }
6719
6720 tries++;
6721 if (wpa_command(intf, "INTERWORKING_SELECT auto")) {
6722 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start "
6723 "Interworking connection");
6724 wpa_ctrl_detach(ctrl);
6725 wpa_ctrl_close(ctrl);
6726 return 0;
6727 }
6728
6729 buf[0] = '\0';
6730 while (1) {
6731 char *pos;
6732 res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
6733 pos = strstr(buf, "INTERWORKING-BLACKLISTED");
6734 if (!pos)
6735 break;
6736 pos += 25;
6737 sigma_dut_print(dut, DUT_MSG_DEBUG, "Found blacklisted AP: %s",
6738 pos);
6739 if (!blacklisted[0])
6740 memcpy(blacklisted, pos, strlen(pos) + 1);
6741 }
6742
6743 if (ignore_blacklist && blacklisted[0]) {
6744 char *end;
6745 end = strchr(blacklisted, ' ');
6746 if (end)
6747 *end = '\0';
6748 sigma_dut_print(dut, DUT_MSG_DEBUG, "Try to connect to a blacklisted network: %s",
6749 blacklisted);
6750 snprintf(buf, sizeof(buf), "INTERWORKING_CONNECT %s",
6751 blacklisted);
6752 if (wpa_command(intf, buf)) {
6753 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start Interworking connection to blacklisted network");
6754 wpa_ctrl_detach(ctrl);
6755 wpa_ctrl_close(ctrl);
6756 return 0;
6757 }
6758 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
6759 buf, sizeof(buf));
6760 }
6761
6762 wpa_ctrl_detach(ctrl);
6763 wpa_ctrl_close(ctrl);
6764
6765 if (res < 0) {
6766 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
6767 "connect");
6768 return 0;
6769 }
6770
6771 if (strstr(buf, "INTERWORKING-NO-MATCH") ||
6772 strstr(buf, "INTERWORKING-BLACKLISTED")) {
6773 if (tries < 2) {
6774 sigma_dut_print(dut, DUT_MSG_INFO, "No match found - try again to verify no APs were missed in the scan");
6775 goto try_again;
6776 }
6777 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,No network with "
6778 "matching credentials found");
6779 return 0;
6780 }
6781
6782 if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
6783 get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
6784 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
6785 "get current BSSID/SSID");
6786 return 0;
6787 }
6788
6789 snprintf(resp, sizeof(resp), "SSID,%s,BSSID,%s", ssid, bssid);
6790 send_resp(dut, conn, SIGMA_COMPLETE, resp);
6791 hs2_set_policy(dut);
6792 return 0;
6793}
6794
6795
6796static int sta_add_credential_uname_pwd(struct sigma_dut *dut,
6797 struct sigma_conn *conn,
6798 const char *ifname,
6799 struct sigma_cmd *cmd)
6800{
6801 const char *val;
6802 int id;
6803
6804 id = add_cred(ifname);
6805 if (id < 0)
6806 return -2;
6807 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
6808
6809 val = get_param(cmd, "prefer");
6810 if (val && atoi(val) > 0)
6811 set_cred(ifname, id, "priority", "1");
6812
6813 val = get_param(cmd, "REALM");
6814 if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
6815 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
6816 "realm");
6817 return 0;
6818 }
6819
6820 val = get_param(cmd, "HOME_FQDN");
6821 if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
6822 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
6823 "home_fqdn");
6824 return 0;
6825 }
6826
6827 val = get_param(cmd, "Username");
6828 if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
6829 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
6830 "username");
6831 return 0;
6832 }
6833
6834 val = get_param(cmd, "Password");
6835 if (val && set_cred_quoted(ifname, id, "password", val) < 0) {
6836 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
6837 "password");
6838 return 0;
6839 }
6840
6841 val = get_param(cmd, "ROOT_CA");
6842 if (val) {
6843 char fname[200];
6844 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
6845#ifdef __linux__
6846 if (!file_exists(fname)) {
6847 char msg[300];
6848 snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
6849 "file (%s) not found", fname);
6850 send_resp(dut, conn, SIGMA_ERROR, msg);
6851 return 0;
6852 }
6853#endif /* __linux__ */
6854 if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
6855 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
6856 "not set root CA");
6857 return 0;
6858 }
6859 }
6860
6861 return 1;
6862}
6863
6864
6865static int update_devdetail_imsi(struct sigma_dut *dut, const char *imsi)
6866{
6867 FILE *in, *out;
6868 char buf[500];
6869 int found = 0;
6870
6871 in = fopen("devdetail.xml", "r");
6872 if (in == NULL)
6873 return -1;
6874 out = fopen("devdetail.xml.tmp", "w");
6875 if (out == NULL) {
6876 fclose(in);
6877 return -1;
6878 }
6879
6880 while (fgets(buf, sizeof(buf), in)) {
6881 char *pos = strstr(buf, "<IMSI>");
6882 if (pos) {
6883 sigma_dut_print(dut, DUT_MSG_INFO, "Updated DevDetail IMSI to %s",
6884 imsi);
6885 pos += 6;
6886 *pos = '\0';
6887 fprintf(out, "%s%s</IMSI>\n", buf, imsi);
6888 found++;
6889 } else {
6890 fprintf(out, "%s", buf);
6891 }
6892 }
6893
6894 fclose(out);
6895 fclose(in);
6896 if (found)
6897 rename("devdetail.xml.tmp", "devdetail.xml");
6898 else
6899 unlink("devdetail.xml.tmp");
6900
6901 return 0;
6902}
6903
6904
6905static int sta_add_credential_sim(struct sigma_dut *dut,
6906 struct sigma_conn *conn,
6907 const char *ifname, struct sigma_cmd *cmd)
6908{
6909 const char *val, *imsi = NULL;
6910 int id;
6911 char buf[200];
6912 int res;
6913 const char *pos;
6914 size_t mnc_len;
6915 char plmn_mcc[4];
6916 char plmn_mnc[4];
6917
6918 id = add_cred(ifname);
6919 if (id < 0)
6920 return -2;
6921 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
6922
6923 val = get_param(cmd, "prefer");
6924 if (val && atoi(val) > 0)
6925 set_cred(ifname, id, "priority", "1");
6926
6927 val = get_param(cmd, "PLMN_MCC");
6928 if (val == NULL) {
6929 send_resp(dut, conn, SIGMA_ERROR,
6930 "errorCode,Missing PLMN_MCC");
6931 return 0;
6932 }
6933 if (strlen(val) != 3) {
6934 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MCC");
6935 return 0;
6936 }
6937 snprintf(plmn_mcc, sizeof(plmn_mcc), "%s", val);
6938
6939 val = get_param(cmd, "PLMN_MNC");
6940 if (val == NULL) {
6941 send_resp(dut, conn, SIGMA_ERROR,
6942 "errorCode,Missing PLMN_MNC");
6943 return 0;
6944 }
6945 if (strlen(val) != 2 && strlen(val) != 3) {
6946 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MNC");
6947 return 0;
6948 }
6949 snprintf(plmn_mnc, sizeof(plmn_mnc), "%s", val);
6950
6951 val = get_param(cmd, "IMSI");
6952 if (val == NULL) {
6953 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing SIM "
6954 "IMSI");
6955 return 0;
6956 }
6957
6958 imsi = pos = val;
6959
6960 if (strncmp(plmn_mcc, pos, 3) != 0) {
6961 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MCC mismatch");
6962 return 0;
6963 }
6964 pos += 3;
6965
6966 mnc_len = strlen(plmn_mnc);
6967 if (mnc_len < 2) {
6968 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC not set");
6969 return 0;
6970 }
6971
6972 if (strncmp(plmn_mnc, pos, mnc_len) != 0) {
6973 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC mismatch");
6974 return 0;
6975 }
6976 pos += mnc_len;
6977
6978 res = snprintf(buf, sizeof(buf), "%s%s-%s",plmn_mcc, plmn_mnc, pos);
6979 if (res < 0 || res >= (int) sizeof(buf))
6980 return -1;
6981 if (set_cred_quoted(ifname, id, "imsi", buf) < 0) {
6982 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
6983 "not set IMSI");
6984 return 0;
6985 }
6986
6987 val = get_param(cmd, "Password");
6988 if (val && set_cred_quoted(ifname, id, "milenage", val) < 0) {
6989 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
6990 "not set password");
6991 return 0;
6992 }
6993
6994 if (dut->program == PROGRAM_HS2_R2) {
6995 /*
6996 * Set provisioning_sp for the test cases where SIM/USIM
6997 * provisioning is used.
6998 */
6999 if (val && set_cred_quoted(ifname, id, "provisioning_sp",
7000 "wi-fi.org") < 0) {
7001 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7002 "not set provisioning_sp");
7003 return 0;
7004 }
7005
7006 update_devdetail_imsi(dut, imsi);
7007 }
7008
7009 return 1;
7010}
7011
7012
7013static int sta_add_credential_cert(struct sigma_dut *dut,
7014 struct sigma_conn *conn,
7015 const char *ifname,
7016 struct sigma_cmd *cmd)
7017{
7018 const char *val;
7019 int id;
7020
7021 id = add_cred(ifname);
7022 if (id < 0)
7023 return -2;
7024 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
7025
7026 val = get_param(cmd, "prefer");
7027 if (val && atoi(val) > 0)
7028 set_cred(ifname, id, "priority", "1");
7029
7030 val = get_param(cmd, "REALM");
7031 if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
7032 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7033 "realm");
7034 return 0;
7035 }
7036
7037 val = get_param(cmd, "HOME_FQDN");
7038 if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
7039 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7040 "home_fqdn");
7041 return 0;
7042 }
7043
7044 val = get_param(cmd, "Username");
7045 if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
7046 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7047 "username");
7048 return 0;
7049 }
7050
7051 val = get_param(cmd, "clientCertificate");
7052 if (val) {
7053 char fname[200];
7054 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
7055#ifdef __linux__
7056 if (!file_exists(fname)) {
7057 char msg[300];
7058 snprintf(msg, sizeof(msg),
7059 "ErrorCode,clientCertificate "
7060 "file (%s) not found", fname);
7061 send_resp(dut, conn, SIGMA_ERROR, msg);
7062 return 0;
7063 }
7064#endif /* __linux__ */
7065 if (set_cred_quoted(ifname, id, "client_cert", fname) < 0) {
7066 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7067 "not set client_cert");
7068 return 0;
7069 }
7070 if (set_cred_quoted(ifname, id, "private_key", fname) < 0) {
7071 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7072 "not set private_key");
7073 return 0;
7074 }
7075 }
7076
7077 val = get_param(cmd, "ROOT_CA");
7078 if (val) {
7079 char fname[200];
7080 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
7081#ifdef __linux__
7082 if (!file_exists(fname)) {
7083 char msg[300];
7084 snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
7085 "file (%s) not found", fname);
7086 send_resp(dut, conn, SIGMA_ERROR, msg);
7087 return 0;
7088 }
7089#endif /* __linux__ */
7090 if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
7091 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7092 "not set root CA");
7093 return 0;
7094 }
7095 }
7096
7097 return 1;
7098}
7099
7100
7101static int cmd_sta_add_credential(struct sigma_dut *dut,
7102 struct sigma_conn *conn,
7103 struct sigma_cmd *cmd)
7104{
7105 const char *intf = get_param(cmd, "Interface");
7106 const char *type;
7107
7108 start_sta_mode(dut);
7109
7110 type = get_param(cmd, "Type");
7111 if (!type)
7112 return -1;
7113
7114 if (strcasecmp(type, "uname_pwd") == 0)
7115 return sta_add_credential_uname_pwd(dut, conn, intf, cmd);
7116
7117 if (strcasecmp(type, "sim") == 0)
7118 return sta_add_credential_sim(dut, conn, intf, cmd);
7119
7120 if (strcasecmp(type, "cert") == 0)
7121 return sta_add_credential_cert(dut, conn, intf, cmd);
7122
7123 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported credential "
7124 "type");
7125 return 0;
7126}
7127
7128
7129static int cmd_sta_scan(struct sigma_dut *dut, struct sigma_conn *conn,
7130 struct sigma_cmd *cmd)
7131{
7132 const char *intf = get_param(cmd, "Interface");
7133 const char *val;
7134 char buf[100];
7135 int res;
7136
7137 val = get_param(cmd, "HESSID");
7138 if (val) {
7139 res = snprintf(buf, sizeof(buf), "SET hessid %s", val);
7140 if (res < 0 || res >= (int) sizeof(buf))
7141 return -1;
7142 wpa_command(intf, buf);
7143 }
7144
7145 val = get_param(cmd, "ACCS_NET_TYPE");
7146 if (val) {
7147 res = snprintf(buf, sizeof(buf), "SET access_network_type %s",
7148 val);
7149 if (res < 0 || res >= (int) sizeof(buf))
7150 return -1;
7151 wpa_command(intf, buf);
7152 }
7153
7154 if (wpa_command(intf, "SCAN")) {
7155 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not start "
7156 "scan");
7157 return 0;
7158 }
7159
7160 return 1;
7161}
7162
7163
7164static int cmd_sta_set_systime(struct sigma_dut *dut, struct sigma_conn *conn,
7165 struct sigma_cmd *cmd)
7166{
7167#ifdef __linux__
7168 struct timeval tv;
7169 struct tm tm;
7170 time_t t;
7171 const char *val;
7172
7173 wpa_command(get_station_ifname(), "PMKSA_FLUSH");
7174
7175 memset(&tm, 0, sizeof(tm));
7176 val = get_param(cmd, "seconds");
7177 if (val)
7178 tm.tm_sec = atoi(val);
7179 val = get_param(cmd, "minutes");
7180 if (val)
7181 tm.tm_min = atoi(val);
7182 val = get_param(cmd, "hours");
7183 if (val)
7184 tm.tm_hour = atoi(val);
7185 val = get_param(cmd, "date");
7186 if (val)
7187 tm.tm_mday = atoi(val);
7188 val = get_param(cmd, "month");
7189 if (val)
7190 tm.tm_mon = atoi(val) - 1;
7191 val = get_param(cmd, "year");
7192 if (val) {
7193 int year = atoi(val);
7194#ifdef ANDROID
7195 if (year > 2035)
7196 year = 2035; /* years beyond 2035 not supported */
7197#endif /* ANDROID */
7198 tm.tm_year = year - 1900;
7199 }
7200 t = mktime(&tm);
7201 if (t == (time_t) -1) {
7202 send_resp(dut, conn, SIGMA_ERROR,
7203 "errorCode,Invalid date or time");
7204 return 0;
7205 }
7206
7207 memset(&tv, 0, sizeof(tv));
7208 tv.tv_sec = t;
7209
7210 if (settimeofday(&tv, NULL) < 0) {
7211 sigma_dut_print(dut, DUT_MSG_INFO, "settimeofday failed: %s",
7212 strerror(errno));
7213 send_resp(dut, conn, SIGMA_ERROR,
7214 "errorCode,Failed to set time");
7215 return 0;
7216 }
7217
7218 return 1;
7219#endif /* __linux__ */
7220
7221 return -1;
7222}
7223
7224
7225static int cmd_sta_osu(struct sigma_dut *dut, struct sigma_conn *conn,
7226 struct sigma_cmd *cmd)
7227{
7228 const char *intf = get_param(cmd, "Interface");
7229 const char *name, *val;
7230 int prod_ess_assoc = 1;
7231 char buf[200], bssid[100], ssid[100];
7232 int res;
7233 struct wpa_ctrl *ctrl;
7234
7235 name = get_param(cmd, "osuFriendlyName");
7236
7237 val = get_param(cmd, "ProdESSAssoc");
7238 if (val)
7239 prod_ess_assoc = atoi(val);
7240
7241 kill_dhcp_client(dut, intf);
7242 if (start_dhcp_client(dut, intf) < 0)
7243 return -2;
7244
7245 sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger OSU");
7246 mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
7247 res = snprintf(buf, sizeof(buf),
7248 "%s %s%s%s signup osu-ca.pem",
7249 prod_ess_assoc ? "" : "-N",
7250 name ? "-O'" : "", name ? name : "",
7251 name ? "'" : "");
7252
7253 if (run_hs20_osu(dut, buf) < 0) {
7254 FILE *f;
7255
7256 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to complete OSU");
7257
7258 f = fopen("hs20-osu-client.res", "r");
7259 if (f) {
7260 char resp[400], res[300], *pos;
7261 if (!fgets(res, sizeof(res), f))
7262 res[0] = '\0';
7263 pos = strchr(res, '\n');
7264 if (pos)
7265 *pos = '\0';
7266 fclose(f);
7267 sigma_dut_summary(dut, "hs20-osu-client provisioning failed: %s",
7268 res);
7269 snprintf(resp, sizeof(resp), "notify-send '%s'", res);
7270 if (system(resp) != 0) {
7271 }
7272 snprintf(resp, sizeof(resp),
7273 "SSID,,BSSID,,failureReason,%s", res);
7274 send_resp(dut, conn, SIGMA_COMPLETE, resp);
7275 return 0;
7276 }
7277
7278 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
7279 return 0;
7280 }
7281
7282 if (!prod_ess_assoc)
7283 goto report;
7284
7285 ctrl = open_wpa_mon(intf);
7286 if (ctrl == NULL) {
7287 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
7288 "wpa_supplicant monitor connection");
7289 return -1;
7290 }
7291
7292 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
7293 buf, sizeof(buf));
7294
7295 wpa_ctrl_detach(ctrl);
7296 wpa_ctrl_close(ctrl);
7297
7298 if (res < 0) {
7299 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to connect to "
7300 "network after OSU");
7301 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
7302 return 0;
7303 }
7304
7305report:
7306 if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
7307 get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
7308 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get BSSID/SSID");
7309 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
7310 return 0;
7311 }
7312
7313 snprintf(buf, sizeof(buf), "SSID,%s,BSSID,%s", ssid, bssid);
7314 send_resp(dut, conn, SIGMA_COMPLETE, buf);
7315 hs2_set_policy(dut);
7316 return 0;
7317}
7318
7319
7320static int cmd_sta_policy_update(struct sigma_dut *dut, struct sigma_conn *conn,
7321 struct sigma_cmd *cmd)
7322{
7323 const char *val;
7324 int timeout = 120;
7325
7326 val = get_param(cmd, "PolicyUpdate");
7327 if (val == NULL || atoi(val) == 0)
7328 return 1; /* No operation requested */
7329
7330 val = get_param(cmd, "Timeout");
7331 if (val)
7332 timeout = atoi(val);
7333
7334 if (timeout) {
7335 /* TODO: time out the command and return
7336 * PolicyUpdateStatus,TIMEOUT if needed. */
7337 }
7338
7339 sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger policy update");
7340 mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
7341 if (run_hs20_osu(dut, "pol_upd fqdn=wi-fi.org") < 0) {
7342 send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,FAIL");
7343 return 0;
7344 }
7345
7346 send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,SUCCESS");
7347 return 0;
7348}
7349
7350
7351static int cmd_sta_er_config(struct sigma_dut *dut, struct sigma_conn *conn,
7352 struct sigma_cmd *cmd)
7353{
7354 struct wpa_ctrl *ctrl;
7355 const char *intf = get_param(cmd, "Interface");
7356 const char *bssid = get_param(cmd, "Bssid");
7357 const char *ssid = get_param(cmd, "SSID");
7358 const char *security = get_param(cmd, "Security");
7359 const char *passphrase = get_param(cmd, "Passphrase");
7360 const char *pin = get_param(cmd, "PIN");
7361 char buf[1000];
7362 char ssid_hex[200], passphrase_hex[200];
7363 const char *keymgmt, *cipher;
7364
7365 if (intf == NULL)
7366 intf = get_main_ifname();
7367
7368 if (!bssid) {
7369 send_resp(dut, conn, SIGMA_ERROR,
7370 "ErrorCode,Missing Bssid argument");
7371 return 0;
7372 }
7373
7374 if (!ssid) {
7375 send_resp(dut, conn, SIGMA_ERROR,
7376 "ErrorCode,Missing SSID argument");
7377 return 0;
7378 }
7379
7380 if (!security) {
7381 send_resp(dut, conn, SIGMA_ERROR,
7382 "ErrorCode,Missing Security argument");
7383 return 0;
7384 }
7385
7386 if (!passphrase) {
7387 send_resp(dut, conn, SIGMA_ERROR,
7388 "ErrorCode,Missing Passphrase argument");
7389 return 0;
7390 }
7391
7392 if (!pin) {
7393 send_resp(dut, conn, SIGMA_ERROR,
7394 "ErrorCode,Missing PIN argument");
7395 return 0;
7396 }
7397
7398 if (strlen(ssid) >= 2 * sizeof(ssid_hex) ||
7399 strlen(passphrase) >= 2 * sizeof(passphrase_hex)) {
7400 send_resp(dut, conn, SIGMA_ERROR,
7401 "ErrorCode,Too long SSID/passphrase");
7402 return 0;
7403 }
7404
7405 ctrl = open_wpa_mon(intf);
7406 if (ctrl == NULL) {
7407 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
7408 "wpa_supplicant monitor connection");
7409 return -2;
7410 }
7411
7412 if (strcasecmp(security, "wpa2-psk") == 0) {
7413 keymgmt = "WPA2PSK";
7414 cipher = "CCMP";
7415 } else {
7416 wpa_ctrl_detach(ctrl);
7417 wpa_ctrl_close(ctrl);
7418 send_resp(dut, conn, SIGMA_ERROR,
7419 "ErrorCode,Unsupported Security value");
7420 return 0;
7421 }
7422
7423 ascii2hexstr(ssid, ssid_hex);
7424 ascii2hexstr(passphrase, passphrase_hex);
7425 snprintf(buf, sizeof(buf), "WPS_REG %s %s %s %s %s %s",
7426 bssid, pin, ssid_hex, keymgmt, cipher, passphrase_hex);
7427
7428 if (wpa_command(intf, buf) < 0) {
7429 wpa_ctrl_detach(ctrl);
7430 wpa_ctrl_close(ctrl);
7431 send_resp(dut, conn, SIGMA_ERROR,
7432 "ErrorCode,Failed to start registrar");
7433 return 0;
7434 }
7435
7436 snprintf(dut->er_oper_bssid, sizeof(dut->er_oper_bssid), "%s", bssid);
7437 dut->er_oper_performed = 1;
7438
7439 return wps_connection_event(dut, conn, ctrl, intf, 0);
7440}
7441
7442
7443static int cmd_sta_wps_connect_pw_token(struct sigma_dut *dut,
7444 struct sigma_conn *conn,
7445 struct sigma_cmd *cmd)
7446{
7447 struct wpa_ctrl *ctrl;
7448 const char *intf = get_param(cmd, "Interface");
7449 const char *bssid = get_param(cmd, "Bssid");
7450 char buf[100];
7451
7452 if (!bssid) {
7453 send_resp(dut, conn, SIGMA_ERROR,
7454 "ErrorCode,Missing Bssid argument");
7455 return 0;
7456 }
7457
7458 ctrl = open_wpa_mon(intf);
7459 if (ctrl == NULL) {
7460 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
7461 "wpa_supplicant monitor connection");
7462 return -2;
7463 }
7464
7465 snprintf(buf, sizeof(buf), "WPS_NFC %s", bssid);
7466
7467 if (wpa_command(intf, buf) < 0) {
7468 wpa_ctrl_detach(ctrl);
7469 wpa_ctrl_close(ctrl);
7470 send_resp(dut, conn, SIGMA_ERROR,
7471 "ErrorCode,Failed to start registrar");
7472 return 0;
7473 }
7474
7475 return wps_connection_event(dut, conn, ctrl, intf, 0);
7476}
7477
7478
7479static int req_intf(struct sigma_cmd *cmd)
7480{
7481 return get_param(cmd, "interface") == NULL ? -1 : 0;
7482}
7483
7484
7485void sta_register_cmds(void)
7486{
7487 sigma_dut_reg_cmd("sta_get_ip_config", req_intf,
7488 cmd_sta_get_ip_config);
7489 sigma_dut_reg_cmd("sta_set_ip_config", req_intf,
7490 cmd_sta_set_ip_config);
7491 sigma_dut_reg_cmd("sta_get_info", req_intf, cmd_sta_get_info);
7492 sigma_dut_reg_cmd("sta_get_mac_address", req_intf,
7493 cmd_sta_get_mac_address);
7494 sigma_dut_reg_cmd("sta_is_connected", req_intf, cmd_sta_is_connected);
7495 sigma_dut_reg_cmd("sta_verify_ip_connection", req_intf,
7496 cmd_sta_verify_ip_connection);
7497 sigma_dut_reg_cmd("sta_get_bssid", req_intf, cmd_sta_get_bssid);
7498 sigma_dut_reg_cmd("sta_set_encryption", req_intf,
7499 cmd_sta_set_encryption);
7500 sigma_dut_reg_cmd("sta_set_psk", req_intf, cmd_sta_set_psk);
7501 sigma_dut_reg_cmd("sta_set_eaptls", req_intf, cmd_sta_set_eaptls);
7502 sigma_dut_reg_cmd("sta_set_eapttls", req_intf, cmd_sta_set_eapttls);
7503 sigma_dut_reg_cmd("sta_set_eapsim", req_intf, cmd_sta_set_eapsim);
7504 sigma_dut_reg_cmd("sta_set_peap", req_intf, cmd_sta_set_peap);
7505 sigma_dut_reg_cmd("sta_set_eapfast", req_intf, cmd_sta_set_eapfast);
7506 sigma_dut_reg_cmd("sta_set_eapaka", req_intf, cmd_sta_set_eapaka);
7507 sigma_dut_reg_cmd("sta_set_eapakaprime", req_intf,
7508 cmd_sta_set_eapakaprime);
7509 sigma_dut_reg_cmd("sta_set_security", req_intf, cmd_sta_set_security);
7510 sigma_dut_reg_cmd("sta_set_uapsd", req_intf, cmd_sta_set_uapsd);
7511 /* TODO: sta_set_ibss */
7512 /* TODO: sta_set_mode */
7513 sigma_dut_reg_cmd("sta_set_wmm", req_intf, cmd_sta_set_wmm);
7514 sigma_dut_reg_cmd("sta_associate", req_intf, cmd_sta_associate);
7515 /* TODO: sta_up_load */
7516 sigma_dut_reg_cmd("sta_preset_testparameters", req_intf,
7517 cmd_sta_preset_testparameters);
7518 /* TODO: sta_set_system */
7519 sigma_dut_reg_cmd("sta_set_11n", req_intf, cmd_sta_set_11n);
7520 /* TODO: sta_set_rifs_test */
7521 sigma_dut_reg_cmd("sta_set_wireless", req_intf, cmd_sta_set_wireless);
7522 sigma_dut_reg_cmd("sta_send_addba", req_intf, cmd_sta_send_addba);
7523 /* TODO: sta_send_coexist_mgmt */
7524 sigma_dut_reg_cmd("sta_disconnect", req_intf, cmd_sta_disconnect);
7525 sigma_dut_reg_cmd("sta_reassoc", req_intf, cmd_sta_reassoc);
7526 sigma_dut_reg_cmd("sta_reassociate", req_intf, cmd_sta_reassoc);
7527 sigma_dut_reg_cmd("sta_reset_default", req_intf,
7528 cmd_sta_reset_default);
7529 sigma_dut_reg_cmd("sta_send_frame", req_intf, cmd_sta_send_frame);
7530 sigma_dut_reg_cmd("sta_set_macaddr", req_intf, cmd_sta_set_macaddr);
7531 sigma_dut_reg_cmd("sta_set_rfeature", req_intf, cmd_sta_set_rfeature);
7532 sigma_dut_reg_cmd("sta_set_radio", req_intf, cmd_sta_set_radio);
7533 sigma_dut_reg_cmd("sta_set_pwrsave", req_intf, cmd_sta_set_pwrsave);
7534 sigma_dut_reg_cmd("sta_bssid_pool", req_intf, cmd_sta_bssid_pool);
7535 sigma_dut_reg_cmd("sta_reset_parm", req_intf, cmd_sta_reset_parm);
7536 sigma_dut_reg_cmd("sta_get_key", req_intf, cmd_sta_get_key);
7537 sigma_dut_reg_cmd("sta_hs2_associate", req_intf,
7538 cmd_sta_hs2_associate);
7539 sigma_dut_reg_cmd("sta_add_credential", req_intf,
7540 cmd_sta_add_credential);
7541 sigma_dut_reg_cmd("sta_scan", req_intf, cmd_sta_scan);
7542 sigma_dut_reg_cmd("sta_set_systime", NULL, cmd_sta_set_systime);
7543 sigma_dut_reg_cmd("sta_osu", req_intf, cmd_sta_osu);
7544 sigma_dut_reg_cmd("sta_policy_update", req_intf, cmd_sta_policy_update);
7545 sigma_dut_reg_cmd("sta_er_config", NULL, cmd_sta_er_config);
7546 sigma_dut_reg_cmd("sta_wps_connect_pw_token", req_intf,
7547 cmd_sta_wps_connect_pw_token);
7548 sigma_dut_reg_cmd("sta_exec_action", req_intf, cmd_sta_exec_action);
7549 sigma_dut_reg_cmd("sta_get_events", req_intf, cmd_sta_get_events);
7550 sigma_dut_reg_cmd("sta_get_parameter", req_intf, cmd_sta_get_parameter);
7551}