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