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