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