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