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