blob: 6d68505a341630f0fc33eda4df04b54614b85631 [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");
1393 const char *ifname, *val, *alg;
1394 int id;
1395
1396 if (intf == NULL)
1397 return -1;
1398
1399 if (strcmp(intf, get_main_ifname()) == 0)
1400 ifname = get_station_ifname();
1401 else
1402 ifname = intf;
1403
1404 id = set_wpa_common(dut, conn, ifname, cmd);
1405 if (id < 0)
1406 return id;
1407
1408 val = get_param(cmd, "keyMgmtType");
1409 alg = get_param(cmd, "micAlg");
1410
1411 if (alg && strcasecmp(alg, "SHA-256") == 0) {
1412 if (set_network(ifname, id, "key_mgmt", "WPA-PSK-SHA256") < 0)
1413 return -2;
1414 } else if (alg && strcasecmp(alg, "SHA-1") == 0) {
1415 if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
1416 return -2;
Ashwini Patil6dbf7b02017-03-20 13:42:11 +05301417 } else if (val && strcasecmp(val, "wpa2-ft") == 0) {
1418 if (set_network(ifname, id, "key_mgmt", "FT-PSK") < 0)
1419 return -2;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001420 } else if ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
1421 dut->sta_pmf == STA_PMF_REQUIRED) {
1422 if (set_network(ifname, id, "key_mgmt",
1423 "WPA-PSK WPA-PSK-SHA256") < 0)
1424 return -2;
1425 } else if (dut->sta_pmf == STA_PMF_OPTIONAL) {
1426 if (set_network(ifname, id, "key_mgmt",
1427 "WPA-PSK WPA-PSK-SHA256") < 0)
1428 return -2;
1429 } else {
1430 if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
1431 return -2;
1432 }
1433
1434 val = get_param(cmd, "passPhrase");
1435 if (val == NULL)
1436 return -1;
1437 if (set_network_quoted(ifname, id, "psk", val) < 0)
1438 return -2;
1439
1440 return 1;
1441}
1442
1443
1444static int set_eap_common(struct sigma_dut *dut, struct sigma_conn *conn,
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301445 const char *ifname, int username_identity,
1446 struct sigma_cmd *cmd)
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001447{
1448 const char *val, *alg;
1449 int id;
1450 char buf[200];
1451#ifdef ANDROID
1452 unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
1453 int length;
1454#endif /* ANDROID */
1455
1456 id = set_wpa_common(dut, conn, ifname, cmd);
1457 if (id < 0)
1458 return id;
1459
1460 val = get_param(cmd, "keyMgmtType");
1461 alg = get_param(cmd, "micAlg");
1462
1463 if (alg && strcasecmp(alg, "SHA-256") == 0) {
1464 if (set_network(ifname, id, "key_mgmt", "WPA-EAP-SHA256") < 0)
1465 return -2;
1466 } else if (alg && strcasecmp(alg, "SHA-1") == 0) {
1467 if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
1468 return -2;
1469 } else if (val && strcasecmp(val, "wpa2-ft") == 0) {
1470 if (set_network(ifname, id, "key_mgmt", "FT-EAP") < 0)
1471 return -2;
1472 } else if ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
1473 dut->sta_pmf == STA_PMF_REQUIRED) {
1474 if (set_network(ifname, id, "key_mgmt",
1475 "WPA-EAP WPA-EAP-SHA256") < 0)
1476 return -2;
1477 } else if (dut->sta_pmf == STA_PMF_OPTIONAL) {
1478 if (set_network(ifname, id, "key_mgmt",
1479 "WPA-EAP WPA-EAP-SHA256") < 0)
1480 return -2;
1481 } else {
1482 if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
1483 return -2;
1484 }
1485
1486 val = get_param(cmd, "trustedRootCA");
1487 if (val) {
1488#ifdef ANDROID
1489 snprintf(buf, sizeof(buf), "CACERT_%s", val);
1490 length = android_keystore_get(ANDROID_KEYSTORE_GET, buf,
1491 kvalue);
1492 if (length > 0) {
1493 sigma_dut_print(dut, DUT_MSG_INFO,
1494 "Use Android keystore [%s]", buf);
1495 snprintf(buf, sizeof(buf), "keystore://CACERT_%s",
1496 val);
1497 goto ca_cert_selected;
1498 }
1499#endif /* ANDROID */
1500
1501 snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
1502#ifdef __linux__
1503 if (!file_exists(buf)) {
1504 char msg[300];
1505 snprintf(msg, sizeof(msg), "ErrorCode,trustedRootCA "
1506 "file (%s) not found", buf);
1507 send_resp(dut, conn, SIGMA_ERROR, msg);
1508 return -3;
1509 }
1510#endif /* __linux__ */
1511#ifdef ANDROID
1512ca_cert_selected:
1513#endif /* ANDROID */
1514 if (set_network_quoted(ifname, id, "ca_cert", buf) < 0)
1515 return -2;
1516 }
1517
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301518 if (username_identity) {
1519 val = get_param(cmd, "username");
1520 if (val) {
1521 if (set_network_quoted(ifname, id, "identity", val) < 0)
1522 return -2;
1523 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001524
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301525 val = get_param(cmd, "password");
1526 if (val) {
1527 if (set_network_quoted(ifname, id, "password", val) < 0)
1528 return -2;
1529 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001530 }
1531
1532 return id;
1533}
1534
1535
1536static int cmd_sta_set_eaptls(struct sigma_dut *dut, struct sigma_conn *conn,
1537 struct sigma_cmd *cmd)
1538{
1539 const char *intf = get_param(cmd, "Interface");
1540 const char *ifname, *val;
1541 int id;
1542 char buf[200];
1543#ifdef ANDROID
1544 unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
1545 int length;
1546 int jb_or_newer = 0;
1547 char prop[PROPERTY_VALUE_MAX];
1548#endif /* ANDROID */
1549
1550 if (intf == NULL)
1551 return -1;
1552
1553 if (strcmp(intf, get_main_ifname()) == 0)
1554 ifname = get_station_ifname();
1555 else
1556 ifname = intf;
1557
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301558 id = set_eap_common(dut, conn, ifname, 1, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001559 if (id < 0)
1560 return id;
1561
1562 if (set_network(ifname, id, "eap", "TLS") < 0)
1563 return -2;
1564
Pradeep Reddy POTTETI9f6c2132016-05-05 16:28:19 +05301565 if (!get_param(cmd, "username") &&
1566 set_network_quoted(ifname, id, "identity",
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001567 "wifi-user@wifilabs.local") < 0)
1568 return -2;
1569
1570 val = get_param(cmd, "clientCertificate");
1571 if (val == NULL)
1572 return -1;
1573#ifdef ANDROID
1574 snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
1575 length = android_keystore_get(ANDROID_KEYSTORE_GET, buf, kvalue);
1576 if (length < 0) {
1577 /*
1578 * JB started reporting keystore type mismatches, so retry with
1579 * the GET_PUBKEY command if the generic GET fails.
1580 */
1581 length = android_keystore_get(ANDROID_KEYSTORE_GET_PUBKEY,
1582 buf, kvalue);
1583 }
1584
1585 if (property_get("ro.build.version.release", prop, NULL) != 0) {
1586 sigma_dut_print(dut, DUT_MSG_DEBUG, "Android release %s", prop);
1587 if (strncmp(prop, "4.0", 3) != 0)
1588 jb_or_newer = 1;
1589 } else
1590 jb_or_newer = 1; /* assume newer */
1591
1592 if (jb_or_newer && length > 0) {
1593 sigma_dut_print(dut, DUT_MSG_INFO,
1594 "Use Android keystore [%s]", buf);
1595 if (set_network(ifname, id, "engine", "1") < 0)
1596 return -2;
1597 if (set_network_quoted(ifname, id, "engine_id", "keystore") < 0)
1598 return -2;
1599 snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
1600 if (set_network_quoted(ifname, id, "key_id", buf) < 0)
1601 return -2;
1602 snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
1603 if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
1604 return -2;
1605 return 1;
1606 } else if (length > 0) {
1607 sigma_dut_print(dut, DUT_MSG_INFO,
1608 "Use Android keystore [%s]", buf);
1609 snprintf(buf, sizeof(buf), "keystore://USRPKEY_%s", val);
1610 if (set_network_quoted(ifname, id, "private_key", buf) < 0)
1611 return -2;
1612 snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
1613 if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
1614 return -2;
1615 return 1;
1616 }
1617#endif /* ANDROID */
1618
1619 snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
1620#ifdef __linux__
1621 if (!file_exists(buf)) {
1622 char msg[300];
1623 snprintf(msg, sizeof(msg), "ErrorCode,clientCertificate file "
1624 "(%s) not found", buf);
1625 send_resp(dut, conn, SIGMA_ERROR, msg);
1626 return -3;
1627 }
1628#endif /* __linux__ */
1629 if (set_network_quoted(ifname, id, "private_key", buf) < 0)
1630 return -2;
1631 if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
1632 return -2;
1633
1634 if (set_network_quoted(ifname, id, "private_key_passwd", "wifi") < 0)
1635 return -2;
1636
1637 return 1;
1638}
1639
1640
1641static int cmd_sta_set_eapttls(struct sigma_dut *dut, struct sigma_conn *conn,
1642 struct sigma_cmd *cmd)
1643{
1644 const char *intf = get_param(cmd, "Interface");
1645 const char *ifname;
1646 int id;
1647
1648 if (intf == NULL)
1649 return -1;
1650
1651 if (strcmp(intf, get_main_ifname()) == 0)
1652 ifname = get_station_ifname();
1653 else
1654 ifname = intf;
1655
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301656 id = set_eap_common(dut, conn, ifname, 1, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001657 if (id < 0)
1658 return id;
1659
1660 if (set_network(ifname, id, "eap", "TTLS") < 0) {
1661 send_resp(dut, conn, SIGMA_ERROR,
1662 "errorCode,Failed to set TTLS method");
1663 return 0;
1664 }
1665
1666 if (set_network_quoted(ifname, id, "phase2", "auth=MSCHAPV2") < 0) {
1667 send_resp(dut, conn, SIGMA_ERROR,
1668 "errorCode,Failed to set MSCHAPv2 for TTLS Phase 2");
1669 return 0;
1670 }
1671
1672 return 1;
1673}
1674
1675
1676static int cmd_sta_set_eapsim(struct sigma_dut *dut, struct sigma_conn *conn,
1677 struct sigma_cmd *cmd)
1678{
1679 const char *intf = get_param(cmd, "Interface");
1680 const char *ifname;
1681 int id;
1682
1683 if (intf == NULL)
1684 return -1;
1685
1686 if (strcmp(intf, get_main_ifname()) == 0)
1687 ifname = get_station_ifname();
1688 else
1689 ifname = intf;
1690
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301691 id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001692 if (id < 0)
1693 return id;
1694
1695 if (set_network(ifname, id, "eap", "SIM") < 0)
1696 return -2;
1697
1698 return 1;
1699}
1700
1701
1702static int cmd_sta_set_peap(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, *val;
1707 int id;
1708 char buf[100];
1709
1710 if (intf == NULL)
1711 return -1;
1712
1713 if (strcmp(intf, get_main_ifname()) == 0)
1714 ifname = get_station_ifname();
1715 else
1716 ifname = intf;
1717
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301718 id = set_eap_common(dut, conn, ifname, 1, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001719 if (id < 0)
1720 return id;
1721
1722 if (set_network(ifname, id, "eap", "PEAP") < 0)
1723 return -2;
1724
1725 val = get_param(cmd, "innerEAP");
1726 if (val) {
1727 if (strcasecmp(val, "MSCHAPv2") == 0) {
1728 if (set_network_quoted(ifname, id, "phase2",
1729 "auth=MSCHAPV2") < 0)
1730 return -2;
1731 } else if (strcasecmp(val, "GTC") == 0) {
1732 if (set_network_quoted(ifname, id, "phase2",
1733 "auth=GTC") < 0)
1734 return -2;
1735 } else
1736 return -1;
1737 }
1738
1739 val = get_param(cmd, "peapVersion");
1740 if (val) {
1741 int ver = atoi(val);
1742 if (ver < 0 || ver > 1)
1743 return -1;
1744 snprintf(buf, sizeof(buf), "peapver=%d", ver);
1745 if (set_network_quoted(ifname, id, "phase1", buf) < 0)
1746 return -2;
1747 }
1748
1749 return 1;
1750}
1751
1752
1753static int cmd_sta_set_eapfast(struct sigma_dut *dut, struct sigma_conn *conn,
1754 struct sigma_cmd *cmd)
1755{
1756 const char *intf = get_param(cmd, "Interface");
1757 const char *ifname, *val;
1758 int id;
1759 char buf[100];
1760
1761 if (intf == NULL)
1762 return -1;
1763
1764 if (strcmp(intf, get_main_ifname()) == 0)
1765 ifname = get_station_ifname();
1766 else
1767 ifname = intf;
1768
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301769 id = set_eap_common(dut, conn, ifname, 1, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001770 if (id < 0)
1771 return id;
1772
1773 if (set_network(ifname, id, "eap", "FAST") < 0)
1774 return -2;
1775
1776 val = get_param(cmd, "innerEAP");
1777 if (val) {
1778 if (strcasecmp(val, "MSCHAPV2") == 0) {
1779 if (set_network_quoted(ifname, id, "phase2",
1780 "auth=MSCHAPV2") < 0)
1781 return -2;
1782 } else if (strcasecmp(val, "GTC") == 0) {
1783 if (set_network_quoted(ifname, id, "phase2",
1784 "auth=GTC") < 0)
1785 return -2;
1786 } else
1787 return -1;
1788 }
1789
1790 val = get_param(cmd, "validateServer");
1791 if (val) {
1792 /* TODO */
1793 sigma_dut_print(dut, DUT_MSG_INFO, "Ignored EAP-FAST "
1794 "validateServer=%s", val);
1795 }
1796
1797 val = get_param(cmd, "pacFile");
1798 if (val) {
1799 snprintf(buf, sizeof(buf), "blob://%s", val);
1800 if (set_network_quoted(ifname, id, "pac_file", buf) < 0)
1801 return -2;
1802 }
1803
1804 if (set_network_quoted(ifname, id, "phase1", "fast_provisioning=2") <
1805 0)
1806 return -2;
1807
1808 return 1;
1809}
1810
1811
1812static int cmd_sta_set_eapaka(struct sigma_dut *dut, struct sigma_conn *conn,
1813 struct sigma_cmd *cmd)
1814{
1815 const char *intf = get_param(cmd, "Interface");
1816 const char *ifname;
1817 int id;
1818
1819 if (intf == NULL)
1820 return -1;
1821
1822 if (strcmp(intf, get_main_ifname()) == 0)
1823 ifname = get_station_ifname();
1824 else
1825 ifname = intf;
1826
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301827 id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001828 if (id < 0)
1829 return id;
1830
1831 if (set_network(ifname, id, "eap", "AKA") < 0)
1832 return -2;
1833
1834 return 1;
1835}
1836
1837
1838static int cmd_sta_set_eapakaprime(struct sigma_dut *dut,
1839 struct sigma_conn *conn,
1840 struct sigma_cmd *cmd)
1841{
1842 const char *intf = get_param(cmd, "Interface");
1843 const char *ifname;
1844 int id;
1845
1846 if (intf == NULL)
1847 return -1;
1848
1849 if (strcmp(intf, get_main_ifname()) == 0)
1850 ifname = get_station_ifname();
1851 else
1852 ifname = intf;
1853
Bala Krishna Bhamidipati73d7af02016-03-24 12:27:56 +05301854 id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001855 if (id < 0)
1856 return id;
1857
1858 if (set_network(ifname, id, "eap", "AKA'") < 0)
1859 return -2;
1860
1861 return 1;
1862}
1863
1864
1865static int sta_set_open(struct sigma_dut *dut, 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 (strcmp(intf, get_main_ifname()) == 0)
1873 ifname = get_station_ifname();
1874 else
1875 ifname = intf;
1876
1877 id = add_network_common(dut, conn, ifname, cmd);
1878 if (id < 0)
1879 return id;
1880
1881 if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
1882 return -2;
1883
1884 return 1;
1885}
1886
1887
1888static int cmd_sta_set_security(struct sigma_dut *dut, struct sigma_conn *conn,
1889 struct sigma_cmd *cmd)
1890{
1891 const char *type = get_param(cmd, "Type");
1892
1893 if (type == NULL) {
1894 send_resp(dut, conn, SIGMA_ERROR,
1895 "ErrorCode,Missing Type argument");
1896 return 0;
1897 }
1898
1899 if (strcasecmp(type, "OPEN") == 0)
1900 return sta_set_open(dut, conn, cmd);
1901 if (strcasecmp(type, "PSK") == 0)
1902 return cmd_sta_set_psk(dut, conn, cmd);
1903 if (strcasecmp(type, "EAPTLS") == 0)
1904 return cmd_sta_set_eaptls(dut, conn, cmd);
1905 if (strcasecmp(type, "EAPTTLS") == 0)
1906 return cmd_sta_set_eapttls(dut, conn, cmd);
1907 if (strcasecmp(type, "EAPPEAP") == 0)
1908 return cmd_sta_set_peap(dut, conn, cmd);
1909 if (strcasecmp(type, "EAPSIM") == 0)
1910 return cmd_sta_set_eapsim(dut, conn, cmd);
1911 if (strcasecmp(type, "EAPFAST") == 0)
1912 return cmd_sta_set_eapfast(dut, conn, cmd);
1913 if (strcasecmp(type, "EAPAKA") == 0)
1914 return cmd_sta_set_eapaka(dut, conn, cmd);
1915 if (strcasecmp(type, "EAPAKAPRIME") == 0)
1916 return cmd_sta_set_eapakaprime(dut, conn, cmd);
1917
1918 send_resp(dut, conn, SIGMA_ERROR,
1919 "ErrorCode,Unsupported Type value");
1920 return 0;
1921}
1922
1923
1924int ath6kl_client_uapsd(struct sigma_dut *dut, const char *intf, int uapsd)
1925{
1926#ifdef __linux__
1927 /* special handling for ath6kl */
1928 char path[128], fname[128], *pos;
1929 ssize_t res;
1930 FILE *f;
1931
1932 snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", intf);
1933 res = readlink(path, path, sizeof(path));
1934 if (res < 0)
1935 return 0; /* not ath6kl */
1936
1937 if (res >= (int) sizeof(path))
1938 res = sizeof(path) - 1;
1939 path[res] = '\0';
1940 pos = strrchr(path, '/');
1941 if (pos == NULL)
1942 pos = path;
1943 else
1944 pos++;
1945 snprintf(fname, sizeof(fname),
1946 "/sys/kernel/debug/ieee80211/%s/ath6kl/"
1947 "create_qos", pos);
1948 if (!file_exists(fname))
1949 return 0; /* not ath6kl */
1950
1951 if (uapsd) {
1952 f = fopen(fname, "w");
1953 if (f == NULL)
1954 return -1;
1955
1956 sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl create_qos");
1957 fprintf(f, "4 2 2 1 2 9999999 9999999 9999999 7777777 0 4 "
1958 "45000 200 56789000 56789000 5678900 0 0 9999999 "
1959 "20000 0\n");
1960 fclose(f);
1961 } else {
1962 snprintf(fname, sizeof(fname),
1963 "/sys/kernel/debug/ieee80211/%s/ath6kl/"
1964 "delete_qos", pos);
1965
1966 f = fopen(fname, "w");
1967 if (f == NULL)
1968 return -1;
1969
1970 sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl delete_qos");
1971 fprintf(f, "2 4\n");
1972 fclose(f);
1973 }
1974#endif /* __linux__ */
1975
1976 return 0;
1977}
1978
1979
1980static int cmd_sta_set_uapsd(struct sigma_dut *dut, struct sigma_conn *conn,
1981 struct sigma_cmd *cmd)
1982{
1983 const char *intf = get_param(cmd, "Interface");
1984 /* const char *ssid = get_param(cmd, "ssid"); */
1985 const char *val;
1986 int max_sp_len = 4;
1987 int ac_be = 1, ac_bk = 1, ac_vi = 1, ac_vo = 1;
1988 char buf[100];
1989 int ret1, ret2;
1990
1991 val = get_param(cmd, "maxSPLength");
1992 if (val) {
1993 max_sp_len = atoi(val);
1994 if (max_sp_len != 0 && max_sp_len != 1 && max_sp_len != 2 &&
1995 max_sp_len != 4)
1996 return -1;
1997 }
1998
1999 val = get_param(cmd, "acBE");
2000 if (val)
2001 ac_be = atoi(val);
2002
2003 val = get_param(cmd, "acBK");
2004 if (val)
2005 ac_bk = atoi(val);
2006
2007 val = get_param(cmd, "acVI");
2008 if (val)
2009 ac_vi = atoi(val);
2010
2011 val = get_param(cmd, "acVO");
2012 if (val)
2013 ac_vo = atoi(val);
2014
2015 dut->client_uapsd = ac_be || ac_bk || ac_vi || ac_vo;
2016
2017 snprintf(buf, sizeof(buf), "P2P_SET client_apsd %d,%d,%d,%d;%d",
2018 ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
2019 ret1 = wpa_command(intf, buf);
2020
2021 snprintf(buf, sizeof(buf), "SET uapsd %d,%d,%d,%d;%d",
2022 ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
2023 ret2 = wpa_command(intf, buf);
2024
2025 if (ret1 && ret2) {
2026 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to set client mode "
2027 "UAPSD parameters.");
2028 return -2;
2029 }
2030
2031 if (ath6kl_client_uapsd(dut, intf, dut->client_uapsd) < 0) {
2032 send_resp(dut, conn, SIGMA_ERROR,
2033 "ErrorCode,Failed to set ath6kl QoS parameters");
2034 return 0;
2035 }
2036
2037 return 1;
2038}
2039
2040
2041static int cmd_sta_set_wmm(struct sigma_dut *dut, struct sigma_conn *conn,
2042 struct sigma_cmd *cmd)
2043{
2044 char buf[1000];
2045 const char *intf = get_param(cmd, "Interface");
2046 const char *grp = get_param(cmd, "Group");
2047 const char *act = get_param(cmd, "Action");
2048 const char *tid = get_param(cmd, "Tid");
2049 const char *dir = get_param(cmd, "Direction");
2050 const char *psb = get_param(cmd, "Psb");
2051 const char *up = get_param(cmd, "Up");
2052 const char *fixed = get_param(cmd, "Fixed");
2053 const char *size = get_param(cmd, "Size");
2054 const char *msize = get_param(cmd, "Maxsize");
2055 const char *minsi = get_param(cmd, "Min_srvc_intrvl");
2056 const char *maxsi = get_param(cmd, "Max_srvc_intrvl");
2057 const char *inact = get_param(cmd, "Inactivity");
2058 const char *sus = get_param(cmd, "Suspension");
2059 const char *mindr = get_param(cmd, "Mindatarate");
2060 const char *meandr = get_param(cmd, "Meandatarate");
2061 const char *peakdr = get_param(cmd, "Peakdatarate");
2062 const char *phyrate = get_param(cmd, "Phyrate");
2063 const char *burstsize = get_param(cmd, "Burstsize");
2064 const char *sba = get_param(cmd, "Sba");
2065 int direction;
2066 int handle;
2067 float sba_fv;
2068 int fixed_int;
2069 int psb_ts;
2070
2071 if (intf == NULL || grp == NULL || act == NULL )
2072 return -1;
2073
2074 if (strcasecmp(act, "addts") == 0) {
2075 if (tid == NULL || dir == NULL || psb == NULL ||
2076 up == NULL || fixed == NULL || size == NULL)
2077 return -1;
2078
2079 /*
2080 * Note: Sigma CAPI spec lists uplink, downlink, and bidi as the
2081 * possible values, but WMM-AC and V-E test scripts use "UP,
2082 * "DOWN", and "BIDI".
2083 */
2084 if (strcasecmp(dir, "uplink") == 0 ||
2085 strcasecmp(dir, "up") == 0) {
2086 direction = 0;
2087 } else if (strcasecmp(dir, "downlink") == 0 ||
2088 strcasecmp(dir, "down") == 0) {
2089 direction = 1;
2090 } else if (strcasecmp(dir, "bidi") == 0) {
2091 direction = 2;
2092 } else {
2093 sigma_dut_print(dut, DUT_MSG_ERROR,
2094 "Direction %s not supported", dir);
2095 return -1;
2096 }
2097
2098 if (strcasecmp(psb, "legacy") == 0) {
2099 psb_ts = 0;
2100 } else if (strcasecmp(psb, "uapsd") == 0) {
2101 psb_ts = 1;
2102 } else {
2103 sigma_dut_print(dut, DUT_MSG_ERROR,
2104 "PSB %s not supported", psb);
2105 return -1;
2106 }
2107
2108 if (atoi(tid) < 0 || atoi(tid) > 7) {
2109 sigma_dut_print(dut, DUT_MSG_ERROR,
2110 "TID %s not supported", tid);
2111 return -1;
2112 }
2113
2114 if (strcasecmp(fixed, "true") == 0) {
2115 fixed_int = 1;
2116 } else {
2117 fixed_int = 0;
2118 }
2119
2120 sba_fv = atof(sba);
2121
2122 dut->dialog_token++;
2123 handle = 7000 + dut->dialog_token;
2124
2125 /*
2126 * size: convert to hex
2127 * maxsi: convert to hex
2128 * mindr: convert to hex
2129 * meandr: convert to hex
2130 * peakdr: convert to hex
2131 * burstsize: convert to hex
2132 * phyrate: convert to hex
2133 * sba: convert to hex with modification
2134 * minsi: convert to integer
2135 * sus: convert to integer
2136 * inact: convert to integer
2137 * maxsi: convert to integer
2138 */
2139
2140 /*
2141 * The Nominal MSDU Size field is 2 octets long and contains an
2142 * unsigned integer that specifies the nominal size, in octets,
2143 * of MSDUs belonging to the traffic under this traffic
2144 * specification and is defined in Figure 16. If the Fixed
2145 * subfield is set to 1, then the size of the MSDU is fixed and
2146 * is indicated by the Size Subfield. If the Fixed subfield is
2147 * set to 0, then the size of the MSDU might not be fixed and
2148 * the Size indicates the nominal MSDU size.
2149 *
2150 * The Surplus Bandwidth Allowance Factor field is 2 octets long
2151 * and specifies the excess allocation of time (and bandwidth)
2152 * over and above the stated rates required to transport an MSDU
2153 * belonging to the traffic in this TSPEC. This field is
2154 * represented as an unsigned binary number with an implicit
2155 * binary point after the leftmost 3 bits. For example, an SBA
2156 * of 1.75 is represented as 0x3800. This field is included to
2157 * account for retransmissions. As such, the value of this field
2158 * must be greater than unity.
2159 */
2160
2161 snprintf(buf, sizeof(buf),
2162 "iwpriv %s addTspec %d %s %d %d %s 0x%X"
2163 " 0x%X 0x%X 0x%X"
2164 " 0x%X 0x%X 0x%X"
2165 " 0x%X %d %d %d %d"
2166 " %d %d",
2167 intf, handle, tid, direction, psb_ts, up,
2168 (unsigned int) ((fixed_int << 15) | atoi(size)),
2169 msize ? atoi(msize) : 0,
2170 mindr ? atoi(mindr) : 0,
2171 meandr ? atoi(meandr) : 0,
2172 peakdr ? atoi(peakdr) : 0,
2173 burstsize ? atoi(burstsize) : 0,
2174 phyrate ? atoi(phyrate) : 0,
2175 sba ? ((unsigned int) (((int) sba_fv << 13) |
2176 (int)((sba_fv - (int) sba_fv) *
2177 8192))) : 0,
2178 minsi ? atoi(minsi) : 0,
2179 sus ? atoi(sus) : 0,
2180 0, 0,
2181 inact ? atoi(inact) : 0,
2182 maxsi ? atoi(maxsi) : 0);
2183
2184 if (system(buf) != 0) {
2185 sigma_dut_print(dut, DUT_MSG_ERROR,
2186 "iwpriv addtspec request failed");
2187 send_resp(dut, conn, SIGMA_ERROR,
2188 "errorCode,Failed to execute addTspec command");
2189 return 0;
2190 }
2191
2192 sigma_dut_print(dut, DUT_MSG_INFO,
2193 "iwpriv addtspec request send");
2194
2195 /* Mapping handle to a TID */
2196 dut->tid_to_handle[atoi(tid)] = handle;
2197 } else if (strcasecmp(act, "delts") == 0) {
2198 if (tid == NULL)
2199 return -1;
2200
2201 if (atoi(tid) < 0 || atoi(tid) > 7) {
2202 sigma_dut_print(dut, DUT_MSG_ERROR,
2203 "TID %s not supported", tid);
2204 send_resp(dut, conn, SIGMA_ERROR,
2205 "errorCode,Unsupported TID");
2206 return 0;
2207 }
2208
2209 handle = dut->tid_to_handle[atoi(tid)];
2210
2211 if (handle < 7000 || handle > 7255) {
2212 /* Invalid handle ie no mapping for that TID */
2213 sigma_dut_print(dut, DUT_MSG_ERROR,
2214 "handle-> %d not found", handle);
2215 }
2216
2217 snprintf(buf, sizeof(buf), "iwpriv %s delTspec %d",
2218 intf, handle);
2219
2220 if (system(buf) != 0) {
2221 sigma_dut_print(dut, DUT_MSG_ERROR,
2222 "iwpriv deltspec request failed");
2223 send_resp(dut, conn, SIGMA_ERROR,
2224 "errorCode,Failed to execute delTspec command");
2225 return 0;
2226 }
2227
2228 sigma_dut_print(dut, DUT_MSG_INFO,
2229 "iwpriv deltspec request send");
2230
2231 dut->tid_to_handle[atoi(tid)] = 0;
2232 } else {
2233 sigma_dut_print(dut, DUT_MSG_ERROR,
2234 "Action type %s not supported", act);
2235 send_resp(dut, conn, SIGMA_ERROR,
2236 "errorCode,Unsupported Action");
2237 return 0;
2238 }
2239
2240 return 1;
2241}
2242
2243
2244static int cmd_sta_associate(struct sigma_dut *dut, struct sigma_conn *conn,
2245 struct sigma_cmd *cmd)
2246{
2247 /* const char *intf = get_param(cmd, "Interface"); */
2248 const char *ssid = get_param(cmd, "ssid");
2249 const char *wps_param = get_param(cmd, "WPS");
2250 const char *bssid = get_param(cmd, "bssid");
Jouni Malinen46a19b62017-06-23 14:31:27 +03002251 const char *chan = get_param(cmd, "channel");
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002252 int wps = 0;
Jouni Malinen46a19b62017-06-23 14:31:27 +03002253 char buf[100], extra[50];
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002254
2255 if (ssid == NULL)
2256 return -1;
2257
2258 if (wps_param &&
2259 (strcmp(wps_param, "1") == 0 || strcasecmp(wps_param, "On") == 0))
2260 wps = 1;
2261
2262 if (wps) {
2263 if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
2264 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS "
2265 "parameters not yet set");
2266 return 0;
2267 }
2268 if (dut->wps_method == WFA_CS_WPS_PBC) {
2269 if (wpa_command(get_station_ifname(), "WPS_PBC") < 0)
2270 return -2;
2271 } else {
2272 snprintf(buf, sizeof(buf), "WPS_PIN any %s",
2273 dut->wps_pin);
2274 if (wpa_command(get_station_ifname(), buf) < 0)
2275 return -2;
2276 }
2277 } else {
2278 if (strcmp(ssid, dut->infra_ssid) != 0) {
2279 printf("No network parameters known for network "
2280 "(ssid='%s')", ssid);
2281 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2282 "No network parameters known for network");
2283 return 0;
2284 }
2285
2286 if (bssid &&
2287 set_network(get_station_ifname(), dut->infra_network_id,
2288 "bssid", bssid) < 0) {
2289 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2290 "Invalid bssid argument");
2291 return 0;
2292 }
2293
Jouni Malinen46a19b62017-06-23 14:31:27 +03002294 extra[0] = '\0';
2295 if (chan)
2296 snprintf(extra, sizeof(extra), " freq=%u",
2297 channel_to_freq(atoi(chan)));
2298 snprintf(buf, sizeof(buf), "SELECT_NETWORK %d%s",
2299 dut->infra_network_id, extra);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002300 if (wpa_command(get_station_ifname(), buf) < 0) {
2301 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to select "
2302 "network id %d on %s",
2303 dut->infra_network_id,
2304 get_station_ifname());
2305 return -2;
2306 }
2307 }
2308
2309 return 1;
2310}
2311
2312
2313static int run_hs20_osu(struct sigma_dut *dut, const char *params)
2314{
2315 char buf[500], cmd[200];
2316 int res;
2317
2318 /* Use hs20-osu-client file at the current dir, if found; otherwise use
2319 * default path */
2320 res = snprintf(cmd, sizeof(cmd),
2321 "%s -w \"%s\" -r hs20-osu-client.res %s%s -dddKt -f Logs/hs20-osu-client.txt",
2322 file_exists("./hs20-osu-client") ?
2323 "./hs20-osu-client" : "hs20-osu-client",
2324 sigma_wpas_ctrl,
2325 dut->summary_log ? "-s " : "",
2326 dut->summary_log ? dut->summary_log : "");
2327 if (res < 0 || res >= (int) sizeof(cmd))
2328 return -1;
2329
2330 res = snprintf(buf, sizeof(buf), "%s %s", cmd, params);
2331 if (res < 0 || res >= (int) sizeof(buf))
2332 return -1;
2333 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
2334
2335 if (system(buf) != 0) {
2336 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to run: %s", buf);
2337 return -1;
2338 }
2339 sigma_dut_print(dut, DUT_MSG_DEBUG,
2340 "Completed hs20-osu-client operation");
2341
2342 return 0;
2343}
2344
2345
2346static int download_ppsmo(struct sigma_dut *dut,
2347 struct sigma_conn *conn,
2348 const char *intf,
2349 struct sigma_cmd *cmd)
2350{
2351 const char *name, *path, *val;
2352 char url[500], buf[600], fbuf[100];
2353 char *fqdn = NULL;
2354
2355 name = get_param(cmd, "FileName");
2356 path = get_param(cmd, "FilePath");
2357 if (name == NULL || path == NULL)
2358 return -1;
2359
2360 if (strcasecmp(path, "VendorSpecific") == 0) {
2361 snprintf(url, sizeof(url), "PPS/%s", name);
2362 sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured PPS MO "
2363 "from the device (%s)", url);
2364 if (!file_exists(url)) {
2365 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
2366 "PPS MO file does not exist");
2367 return 0;
2368 }
2369 snprintf(buf, sizeof(buf), "cp %s pps-tnds.xml", url);
2370 if (system(buf) != 0) {
2371 send_resp(dut, conn, SIGMA_ERROR,
2372 "errorCode,Failed to copy PPS MO");
2373 return 0;
2374 }
2375 } else if (strncasecmp(path, "http:", 5) != 0 &&
2376 strncasecmp(path, "https:", 6) != 0) {
2377 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2378 "Unsupported FilePath value");
2379 return 0;
2380 } else {
2381 snprintf(url, sizeof(url), "%s/%s", path, name);
2382 sigma_dut_print(dut, DUT_MSG_INFO, "Downloading PPS MO from %s",
2383 url);
2384 snprintf(buf, sizeof(buf), "wget -T 10 -t 3 -O pps-tnds.xml '%s'", url);
2385 remove("pps-tnds.xml");
2386 if (system(buf) != 0) {
2387 send_resp(dut, conn, SIGMA_ERROR,
2388 "errorCode,Failed to download PPS MO");
2389 return 0;
2390 }
2391 }
2392
2393 if (run_hs20_osu(dut, "from_tnds pps-tnds.xml pps.xml") < 0) {
2394 send_resp(dut, conn, SIGMA_ERROR,
2395 "errorCode,Failed to parse downloaded PPSMO");
2396 return 0;
2397 }
2398 unlink("pps-tnds.xml");
2399
2400 val = get_param(cmd, "managementTreeURI");
2401 if (val) {
2402 const char *pos, *end;
2403 sigma_dut_print(dut, DUT_MSG_DEBUG, "managementTreeURI: %s",
2404 val);
2405 if (strncmp(val, "./Wi-Fi/", 8) != 0) {
2406 send_resp(dut, conn, SIGMA_ERROR,
2407 "errorCode,Invalid managementTreeURI prefix");
2408 return 0;
2409 }
2410 pos = val + 8;
2411 end = strchr(pos, '/');
2412 if (end == NULL ||
2413 strcmp(end, "/PerProviderSubscription") != 0) {
2414 send_resp(dut, conn, SIGMA_ERROR,
2415 "errorCode,Invalid managementTreeURI postfix");
2416 return 0;
2417 }
2418 if (end - pos >= (int) sizeof(fbuf)) {
2419 send_resp(dut, conn, SIGMA_ERROR,
2420 "errorCode,Too long FQDN in managementTreeURI");
2421 return 0;
2422 }
2423 memcpy(fbuf, pos, end - pos);
2424 fbuf[end - pos] = '\0';
2425 fqdn = fbuf;
2426 sigma_dut_print(dut, DUT_MSG_INFO,
2427 "FQDN from managementTreeURI: %s", fqdn);
2428 } else if (run_hs20_osu(dut, "get_fqdn pps.xml") == 0) {
2429 FILE *f = fopen("pps-fqdn", "r");
2430 if (f) {
2431 if (fgets(fbuf, sizeof(fbuf), f)) {
2432 fbuf[sizeof(fbuf) - 1] = '\0';
2433 fqdn = fbuf;
2434 sigma_dut_print(dut, DUT_MSG_DEBUG,
2435 "Use FQDN %s", fqdn);
2436 }
2437 fclose(f);
2438 }
2439 }
2440
2441 if (fqdn == NULL) {
2442 send_resp(dut, conn, SIGMA_ERROR,
2443 "errorCode,No FQDN specified");
2444 return 0;
2445 }
2446
2447 mkdir("SP", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
2448 snprintf(buf, sizeof(buf), "SP/%s", fqdn);
2449 mkdir(buf, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
2450
2451 snprintf(buf, sizeof(buf), "SP/%s/pps.xml", fqdn);
2452 if (rename("pps.xml", buf) < 0) {
2453 send_resp(dut, conn, SIGMA_ERROR,
2454 "errorCode,Could not move PPS MO");
2455 return 0;
2456 }
2457
2458 if (strcasecmp(path, "VendorSpecific") == 0) {
2459 snprintf(buf, sizeof(buf), "cp Certs/ca.pem SP/%s/ca.pem",
2460 fqdn);
2461 if (system(buf)) {
2462 send_resp(dut, conn, SIGMA_ERROR,
2463 "errorCode,Failed to copy OSU CA cert");
2464 return 0;
2465 }
2466
2467 snprintf(buf, sizeof(buf),
2468 "cp Certs/aaa-ca.pem SP/%s/aaa-ca.pem",
2469 fqdn);
2470 if (system(buf)) {
2471 send_resp(dut, conn, SIGMA_ERROR,
2472 "errorCode,Failed to copy AAA CA cert");
2473 return 0;
2474 }
2475 } else {
2476 snprintf(buf, sizeof(buf),
2477 "dl_osu_ca SP/%s/pps.xml SP/%s/ca.pem",
2478 fqdn, fqdn);
2479 if (run_hs20_osu(dut, buf) < 0) {
2480 send_resp(dut, conn, SIGMA_ERROR,
2481 "errorCode,Failed to download OSU CA cert");
2482 return 0;
2483 }
2484
2485 snprintf(buf, sizeof(buf),
2486 "dl_aaa_ca SP/%s/pps.xml SP/%s/aaa-ca.pem",
2487 fqdn, fqdn);
2488 if (run_hs20_osu(dut, buf) < 0) {
2489 sigma_dut_print(dut, DUT_MSG_INFO,
2490 "Failed to download AAA CA cert");
2491 }
2492 }
2493
2494 if (file_exists("next-client-cert.pem")) {
2495 snprintf(buf, sizeof(buf), "SP/%s/client-cert.pem", fqdn);
2496 if (rename("next-client-cert.pem", buf) < 0) {
2497 send_resp(dut, conn, SIGMA_ERROR,
2498 "errorCode,Could not move client certificate");
2499 return 0;
2500 }
2501 }
2502
2503 if (file_exists("next-client-key.pem")) {
2504 snprintf(buf, sizeof(buf), "SP/%s/client-key.pem", fqdn);
2505 if (rename("next-client-key.pem", buf) < 0) {
2506 send_resp(dut, conn, SIGMA_ERROR,
2507 "errorCode,Could not move client key");
2508 return 0;
2509 }
2510 }
2511
2512 snprintf(buf, sizeof(buf), "set_pps SP/%s/pps.xml", fqdn);
2513 if (run_hs20_osu(dut, buf) < 0) {
2514 send_resp(dut, conn, SIGMA_ERROR,
2515 "errorCode,Failed to configure credential from "
2516 "PPSMO");
2517 return 0;
2518 }
2519
2520 return 1;
2521}
2522
2523
2524static int download_cert(struct sigma_dut *dut,
2525 struct sigma_conn *conn,
2526 const char *intf,
2527 struct sigma_cmd *cmd)
2528{
2529 const char *name, *path;
2530 char url[500], buf[600];
2531
2532 name = get_param(cmd, "FileName");
2533 path = get_param(cmd, "FilePath");
2534 if (name == NULL || path == NULL)
2535 return -1;
2536
2537 if (strcasecmp(path, "VendorSpecific") == 0) {
2538 snprintf(url, sizeof(url), "Certs/%s-cert.pem", name);
2539 sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
2540 "certificate from the device (%s)", url);
2541 if (!file_exists(url)) {
2542 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
2543 "certificate file does not exist");
2544 return 0;
2545 }
2546 snprintf(buf, sizeof(buf), "cp %s next-client-cert.pem", url);
2547 if (system(buf) != 0) {
2548 send_resp(dut, conn, SIGMA_ERROR,
2549 "errorCode,Failed to copy client "
2550 "certificate");
2551 return 0;
2552 }
2553
2554 snprintf(url, sizeof(url), "Certs/%s-key.pem", name);
2555 sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
2556 "private key from the device (%s)", url);
2557 if (!file_exists(url)) {
2558 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
2559 "private key file does not exist");
2560 return 0;
2561 }
2562 snprintf(buf, sizeof(buf), "cp %s next-client-key.pem", url);
2563 if (system(buf) != 0) {
2564 send_resp(dut, conn, SIGMA_ERROR,
2565 "errorCode,Failed to copy client key");
2566 return 0;
2567 }
2568 } else if (strncasecmp(path, "http:", 5) != 0 &&
2569 strncasecmp(path, "https:", 6) != 0) {
2570 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
2571 "Unsupported FilePath value");
2572 return 0;
2573 } else {
2574 snprintf(url, sizeof(url), "%s/%s.pem", path, name);
2575 sigma_dut_print(dut, DUT_MSG_INFO, "Downloading client "
2576 "certificate/key from %s", url);
2577 snprintf(buf, sizeof(buf),
2578 "wget -T 10 -t 3 -O next-client-cert.pem '%s'", url);
2579 if (system(buf) != 0) {
2580 send_resp(dut, conn, SIGMA_ERROR,
2581 "errorCode,Failed to download client "
2582 "certificate");
2583 return 0;
2584 }
2585
2586 if (system("cp next-client-cert.pem next-client-key.pem") != 0)
2587 {
2588 send_resp(dut, conn, SIGMA_ERROR,
2589 "errorCode,Failed to copy client key");
2590 return 0;
2591 }
2592 }
2593
2594 return 1;
2595}
2596
2597
2598static int cmd_sta_preset_testparameters_hs2_r2(struct sigma_dut *dut,
2599 struct sigma_conn *conn,
2600 const char *intf,
2601 struct sigma_cmd *cmd)
2602{
2603 const char *val;
2604
2605 val = get_param(cmd, "FileType");
2606 if (val && strcasecmp(val, "PPSMO") == 0)
2607 return download_ppsmo(dut, conn, intf, cmd);
2608 if (val && strcasecmp(val, "CERT") == 0)
2609 return download_cert(dut, conn, intf, cmd);
2610 if (val) {
2611 send_resp(dut, conn, SIGMA_ERROR,
2612 "ErrorCode,Unsupported FileType");
2613 return 0;
2614 }
2615
2616 return 1;
2617}
2618
2619
2620static void ath_sta_set_noack(struct sigma_dut *dut, const char *intf,
2621 const char *val)
2622{
2623 int counter = 0;
2624 char token[50];
2625 char *result;
2626 char buf[100];
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05302627 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002628
Peng Xub8fc5cc2017-05-10 17:27:28 -07002629 strlcpy(token, val, sizeof(token));
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002630 token[sizeof(token) - 1] = '\0';
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05302631 result = strtok_r(token, ":", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002632 while (result) {
2633 if (strcmp(result, "disable") == 0) {
2634 snprintf(buf, sizeof(buf),
2635 "iwpriv %s noackpolicy %d 1 0",
2636 intf, counter);
2637 } else {
2638 snprintf(buf, sizeof(buf),
2639 "iwpriv %s noackpolicy %d 1 1",
2640 intf, counter);
2641 }
2642 if (system(buf) != 0) {
2643 sigma_dut_print(dut, DUT_MSG_ERROR,
2644 "iwpriv noackpolicy failed");
2645 }
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05302646 result = strtok_r(NULL, ":", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002647 counter++;
2648 }
2649}
2650
2651
2652static void ath_sta_set_rts(struct sigma_dut *dut, const char *intf,
2653 const char *val)
2654{
2655 char buf[100];
2656
2657 snprintf(buf, sizeof(buf), "iwconfig %s rts %s", intf, val);
2658 if (system(buf) != 0) {
2659 sigma_dut_print(dut, DUT_MSG_ERROR, "iwconfig RTS failed");
2660 }
2661}
2662
2663
2664static void ath_sta_set_wmm(struct sigma_dut *dut, const char *intf,
2665 const char *val)
2666{
2667 char buf[100];
2668
2669 if (strcasecmp(val, "off") == 0) {
2670 snprintf(buf, sizeof(buf), "iwpriv %s wmm 0", intf);
2671 if (system(buf) != 0) {
2672 sigma_dut_print(dut, DUT_MSG_ERROR,
2673 "Failed to turn off WMM");
2674 }
2675 }
2676}
2677
2678
2679static void ath_sta_set_sgi(struct sigma_dut *dut, const char *intf,
2680 const char *val)
2681{
2682 char buf[100];
2683 int sgi20;
2684
2685 sgi20 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
2686
2687 snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi20);
2688 if (system(buf) != 0)
2689 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv shortgi failed");
2690}
2691
2692
2693static void ath_sta_set_11nrates(struct sigma_dut *dut, const char *intf,
2694 const char *val)
2695{
2696 char buf[100];
Pradeep Reddy POTTETI67376b72016-10-25 20:08:17 +05302697 int rate_code, v;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002698
2699 /* Disable Tx Beam forming when using a fixed rate */
2700 ath_disable_txbf(dut, intf);
2701
Pradeep Reddy POTTETI67376b72016-10-25 20:08:17 +05302702 v = atoi(val);
2703 if (v < 0 || v > 32) {
2704 sigma_dut_print(dut, DUT_MSG_ERROR,
2705 "Invalid Fixed MCS rate: %d", v);
2706 return;
2707 }
2708 rate_code = 0x80 + v;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002709
2710 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0x%x",
2711 intf, rate_code);
2712 if (system(buf) != 0) {
2713 sigma_dut_print(dut, DUT_MSG_ERROR,
2714 "iwpriv set11NRates failed");
2715 }
2716
2717 /* Channel width gets messed up, fix this */
2718 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d", intf, dut->chwidth);
2719 if (system(buf) != 0)
2720 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv chwidth failed");
2721}
2722
2723
2724static void ath_sta_set_amsdu(struct sigma_dut *dut, const char *intf,
2725 const char *val)
2726{
2727 char buf[60];
2728
2729 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)
2730 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 2", intf);
2731 else
2732 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
2733
2734 if (system(buf) != 0)
2735 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv amsdu failed");
2736}
2737
2738
Deepak Dhamdhere80356cb2016-03-28 16:48:32 -07002739static int iwpriv_sta_set_ampdu(struct sigma_dut *dut, const char *intf,
2740 int ampdu)
2741{
2742 char buf[60];
2743
2744 snprintf(buf, sizeof(buf), "iwpriv %s ampdu %d", intf, ampdu);
2745 if (system(buf) != 0) {
2746 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv ampdu failed");
2747 return -1;
2748 }
2749
2750 return 0;
2751}
2752
2753
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002754static void ath_sta_set_stbc(struct sigma_dut *dut, const char *intf,
2755 const char *val)
2756{
2757 char buf[60];
2758
2759 snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc %s", intf, val);
2760 if (system(buf) != 0) {
2761 sigma_dut_print(dut, DUT_MSG_ERROR,
2762 "iwpriv tx_stbc failed");
2763 }
2764
2765 snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc %s", intf, val);
2766 if (system(buf) != 0) {
2767 sigma_dut_print(dut, DUT_MSG_ERROR,
2768 "iwpriv rx_stbc failed");
2769 }
2770}
2771
2772
2773static int wcn_sta_set_cts_width(struct sigma_dut *dut, const char *intf,
2774 const char *val)
2775{
2776 char buf[60];
2777
Peng Xucc317ed2017-05-18 16:44:37 -07002778 if (strcmp(val, "160") == 0) {
2779 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 5", intf);
2780 } else if (strcmp(val, "80") == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +02002781 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
2782 } else if (strcmp(val, "40") == 0) {
2783 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 2", intf);
2784 } else if (strcmp(val, "20") == 0) {
2785 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 1", intf);
2786 } else if (strcasecmp(val, "Auto") == 0) {
2787 buf[0] = '\0';
2788 } else {
2789 sigma_dut_print(dut, DUT_MSG_ERROR,
2790 "WIDTH/CTS_WIDTH value not supported");
2791 return -1;
2792 }
2793
2794 if (buf[0] != '\0' && system(buf) != 0) {
2795 sigma_dut_print(dut, DUT_MSG_ERROR,
2796 "Failed to set WIDTH/CTS_WIDTH");
2797 return -1;
2798 }
2799
2800 return 0;
2801}
2802
2803
2804int ath_set_width(struct sigma_dut *dut, struct sigma_conn *conn,
2805 const char *intf, const char *val)
2806{
2807 char buf[60];
2808
2809 if (strcasecmp(val, "Auto") == 0) {
2810 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
2811 dut->chwidth = 0;
2812 } else if (strcasecmp(val, "20") == 0) {
2813 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
2814 dut->chwidth = 0;
2815 } else if (strcasecmp(val, "40") == 0) {
2816 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 1", intf);
2817 dut->chwidth = 1;
2818 } else if (strcasecmp(val, "80") == 0) {
2819 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
2820 dut->chwidth = 2;
2821 } else if (strcasecmp(val, "160") == 0) {
2822 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 3", intf);
2823 dut->chwidth = 3;
2824 } else {
2825 send_resp(dut, conn, SIGMA_ERROR,
2826 "ErrorCode,WIDTH not supported");
2827 return -1;
2828 }
2829
2830 if (system(buf) != 0) {
2831 sigma_dut_print(dut, DUT_MSG_ERROR,
2832 "iwpriv chwidth failed");
2833 }
2834
2835 return 0;
2836}
2837
2838
2839static int wcn_sta_set_sp_stream(struct sigma_dut *dut, const char *intf,
2840 const char *val)
2841{
2842 char buf[60];
2843
2844 if (strcmp(val, "1SS") == 0) {
2845 snprintf(buf, sizeof(buf), "iwpriv %s nss 1", intf);
2846 } else if (strcmp(val, "2SS") == 0) {
2847 snprintf(buf, sizeof(buf), "iwpriv %s nss 2", intf);
2848 } else {
2849 sigma_dut_print(dut, DUT_MSG_ERROR,
2850 "SP_STREAM value not supported");
2851 return -1;
2852 }
2853
2854 if (system(buf) != 0) {
2855 sigma_dut_print(dut, DUT_MSG_ERROR,
2856 "Failed to set SP_STREAM");
2857 return -1;
2858 }
2859
2860 return 0;
2861}
2862
2863
Pradeep Reddy POTTETI4a1f6b32016-11-23 13:15:21 +05302864static void wcn_sta_set_stbc(struct sigma_dut *dut, const char *intf,
2865 const char *val)
2866{
2867 char buf[60];
2868
2869 snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc %s", intf, val);
2870 if (system(buf) != 0)
2871 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv tx_stbc failed");
2872
2873 snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc %s", intf, val);
2874 if (system(buf) != 0)
2875 sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv rx_stbc failed");
2876}
2877
2878
Ashwini Patil68d02cd2017-01-10 15:39:16 +05302879static int mbo_set_cellular_data_capa(struct sigma_dut *dut,
2880 struct sigma_conn *conn,
2881 const char *intf, int capa)
2882{
2883 char buf[32];
2884
2885 if (capa > 0 && capa < 4) {
2886 snprintf(buf, sizeof(buf), "SET mbo_cell_capa %d", capa);
2887 if (wpa_command(intf, buf) < 0) {
2888 send_resp(dut, conn, SIGMA_ERROR,
2889 "ErrorCode, Failed to set cellular data capability");
2890 return 0;
2891 }
2892 return 1;
2893 }
2894
2895 sigma_dut_print(dut, DUT_MSG_ERROR,
2896 "Invalid Cellular data capability: %d", capa);
2897 send_resp(dut, conn, SIGMA_INVALID,
2898 "ErrorCode,Invalid cellular data capability");
2899 return 0;
2900}
2901
2902
Ashwini Patil9183fdb2017-04-13 16:58:25 +05302903static int mbo_set_roaming(struct sigma_dut *dut, struct sigma_conn *conn,
2904 const char *intf, const char *val)
2905{
2906 if (strcasecmp(val, "Disable") == 0) {
2907 if (wpa_command(intf, "SET roaming 0") < 0) {
2908 send_resp(dut, conn, SIGMA_ERROR,
2909 "ErrorCode,Failed to disable roaming");
2910 return 0;
2911 }
2912 return 1;
2913 }
2914
2915 if (strcasecmp(val, "Enable") == 0) {
2916 if (wpa_command(intf, "SET roaming 1") < 0) {
2917 send_resp(dut, conn, SIGMA_ERROR,
2918 "ErrorCode,Failed to enable roaming");
2919 return 0;
2920 }
2921 return 1;
2922 }
2923
2924 sigma_dut_print(dut, DUT_MSG_ERROR,
2925 "Invalid value provided for roaming: %s", val);
2926 send_resp(dut, conn, SIGMA_INVALID,
2927 "ErrorCode,Unknown value provided for Roaming");
2928 return 0;
2929}
2930
2931
Ashwini Patila75de5a2017-04-13 16:35:05 +05302932static int mbo_set_assoc_disallow(struct sigma_dut *dut,
2933 struct sigma_conn *conn,
2934 const char *intf, const char *val)
2935{
2936 if (strcasecmp(val, "Disable") == 0) {
2937 if (wpa_command(intf, "SET ignore_assoc_disallow 1") < 0) {
2938 send_resp(dut, conn, SIGMA_ERROR,
2939 "ErrorCode,Failed to disable Assoc_disallow");
2940 return 0;
2941 }
2942 return 1;
2943 }
2944
2945 if (strcasecmp(val, "Enable") == 0) {
2946 if (wpa_command(intf, "SET ignore_assoc_disallow 0") < 0) {
2947 send_resp(dut, conn, SIGMA_ERROR,
2948 "ErrorCode,Failed to enable Assoc_disallow");
2949 return 0;
2950 }
2951 return 1;
2952 }
2953
2954 sigma_dut_print(dut, DUT_MSG_ERROR,
2955 "Invalid value provided for Assoc_disallow: %s", val);
2956 send_resp(dut, conn, SIGMA_INVALID,
2957 "ErrorCode,Unknown value provided for Assoc_disallow");
2958 return 0;
2959}
2960
2961
Ashwini Patilc63161e2017-04-13 16:30:23 +05302962static int mbo_set_bss_trans_req(struct sigma_dut *dut, struct sigma_conn *conn,
2963 const char *intf, const char *val)
2964{
2965 if (strcasecmp(val, "Reject") == 0) {
2966 if (wpa_command(intf, "SET reject_btm_req_reason 1") < 0) {
2967 send_resp(dut, conn, SIGMA_ERROR,
2968 "ErrorCode,Failed to Reject BTM Request");
2969 return 0;
2970 }
2971 return 1;
2972 }
2973
2974 if (strcasecmp(val, "Accept") == 0) {
2975 if (wpa_command(intf, "SET reject_btm_req_reason 0") < 0) {
2976 send_resp(dut, conn, SIGMA_ERROR,
2977 "ErrorCode,Failed to Accept BTM Request");
2978 return 0;
2979 }
2980 return 1;
2981 }
2982
2983 sigma_dut_print(dut, DUT_MSG_ERROR,
2984 "Invalid value provided for BSS_Transition: %s", val);
2985 send_resp(dut, conn, SIGMA_INVALID,
2986 "ErrorCode,Unknown value provided for BSS_Transition");
2987 return 0;
2988}
2989
2990
Ashwini Patil00402582017-04-13 12:29:39 +05302991static int mbo_set_non_pref_ch_list(struct sigma_dut *dut,
2992 struct sigma_conn *conn,
2993 const char *intf,
2994 struct sigma_cmd *cmd)
2995{
2996 const char *ch, *pref, *op_class, *reason;
2997 char buf[120];
2998 int len, ret;
2999
3000 pref = get_param(cmd, "Ch_Pref");
3001 if (!pref)
3002 return 1;
3003
3004 if (strcasecmp(pref, "clear") == 0) {
3005 free(dut->non_pref_ch_list);
3006 dut->non_pref_ch_list = NULL;
3007 } else {
3008 op_class = get_param(cmd, "Ch_Op_Class");
3009 if (!op_class) {
3010 send_resp(dut, conn, SIGMA_INVALID,
3011 "ErrorCode,Ch_Op_Class not provided");
3012 return 0;
3013 }
3014
3015 ch = get_param(cmd, "Ch_Pref_Num");
3016 if (!ch) {
3017 send_resp(dut, conn, SIGMA_INVALID,
3018 "ErrorCode,Ch_Pref_Num not provided");
3019 return 0;
3020 }
3021
3022 reason = get_param(cmd, "Ch_Reason_Code");
3023 if (!reason) {
3024 send_resp(dut, conn, SIGMA_INVALID,
3025 "ErrorCode,Ch_Reason_Code not provided");
3026 return 0;
3027 }
3028
3029 if (!dut->non_pref_ch_list) {
3030 dut->non_pref_ch_list =
3031 calloc(1, NON_PREF_CH_LIST_SIZE);
3032 if (!dut->non_pref_ch_list) {
3033 send_resp(dut, conn, SIGMA_ERROR,
3034 "ErrorCode,Failed to allocate memory for non_pref_ch_list");
3035 return 0;
3036 }
3037 }
3038 len = strlen(dut->non_pref_ch_list);
3039 ret = snprintf(dut->non_pref_ch_list + len,
3040 NON_PREF_CH_LIST_SIZE - len,
3041 " %s:%s:%s:%s", op_class, ch, pref, reason);
3042 if (ret > 0 && ret < NON_PREF_CH_LIST_SIZE - len) {
3043 sigma_dut_print(dut, DUT_MSG_DEBUG, "non_pref_list: %s",
3044 dut->non_pref_ch_list);
3045 } else {
3046 sigma_dut_print(dut, DUT_MSG_ERROR,
3047 "snprintf failed for non_pref_list, ret = %d",
3048 ret);
3049 send_resp(dut, conn, SIGMA_ERROR,
3050 "ErrorCode,snprintf failed");
3051 free(dut->non_pref_ch_list);
3052 dut->non_pref_ch_list = NULL;
3053 return 0;
3054 }
3055 }
3056
3057 ret = snprintf(buf, sizeof(buf), "SET non_pref_chan%s",
3058 dut->non_pref_ch_list ? dut->non_pref_ch_list : " ");
3059 if (ret < 0 || ret >= (int) sizeof(buf)) {
3060 sigma_dut_print(dut, DUT_MSG_DEBUG,
3061 "snprintf failed for set non_pref_chan, ret: %d",
3062 ret);
3063 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,snprint failed");
3064 return 0;
3065 }
3066
3067 if (wpa_command(intf, buf) < 0) {
3068 send_resp(dut, conn, SIGMA_ERROR,
3069 "ErrorCode,Failed to set non-preferred channel list");
3070 return 0;
3071 }
3072
3073 return 1;
3074}
3075
3076
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003077static int cmd_sta_preset_testparameters(struct sigma_dut *dut,
3078 struct sigma_conn *conn,
3079 struct sigma_cmd *cmd)
3080{
3081 const char *intf = get_param(cmd, "Interface");
3082 const char *val;
3083
3084 val = get_param(cmd, "Program");
Peng Xue9fa7952017-05-09 15:59:49 -07003085 if (val && strcasecmp(val, "HS2-R2") == 0)
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003086 return cmd_sta_preset_testparameters_hs2_r2(dut, conn, intf,
3087 cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003088
priyadharshini gowthamand66913a2016-07-29 15:11:17 -07003089 if (val && strcasecmp(val, "LOC") == 0)
3090 return loc_cmd_sta_preset_testparameters(dut, conn, cmd);
3091
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003092#ifdef ANDROID_NAN
3093 if (val && strcasecmp(val, "NAN") == 0)
3094 return nan_cmd_sta_preset_testparameters(dut, conn, cmd);
3095#endif /* ANDROID_NAN */
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07003096#ifdef MIRACAST
3097 if (val && (strcasecmp(val, "WFD") == 0 ||
3098 strcasecmp(val, "DisplayR2") == 0))
3099 return miracast_preset_testparameters(dut, conn, cmd);
3100#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003101
Ashwini Patil68d02cd2017-01-10 15:39:16 +05303102 if (val && strcasecmp(val, "MBO") == 0) {
3103 val = get_param(cmd, "Cellular_Data_Cap");
3104 if (val &&
3105 mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
3106 return 0;
Ashwini Patil00402582017-04-13 12:29:39 +05303107
3108 val = get_param(cmd, "Ch_Pref");
3109 if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
3110 return 0;
3111
Ashwini Patilc63161e2017-04-13 16:30:23 +05303112 val = get_param(cmd, "BSS_Transition");
3113 if (val && mbo_set_bss_trans_req(dut, conn, intf, val) == 0)
3114 return 0;
3115
Ashwini Patila75de5a2017-04-13 16:35:05 +05303116 val = get_param(cmd, "Assoc_Disallow");
3117 if (val && mbo_set_assoc_disallow(dut, conn, intf, val) == 0)
3118 return 0;
3119
Ashwini Patil9183fdb2017-04-13 16:58:25 +05303120 val = get_param(cmd, "Roaming");
3121 if (val && mbo_set_roaming(dut, conn, intf, val) == 0)
3122 return 0;
3123
Ashwini Patil68d02cd2017-01-10 15:39:16 +05303124 return 1;
3125 }
3126
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003127#if 0
3128 val = get_param(cmd, "Supplicant");
3129 if (val && strcasecmp(val, "Default") != 0) {
3130 send_resp(dut, conn, SIGMA_ERROR,
3131 "ErrorCode,Only default(Vendor) supplicant "
3132 "supported");
3133 return 0;
3134 }
3135#endif
3136
3137 val = get_param(cmd, "RTS");
3138 if (val) {
3139 switch (get_driver_type()) {
3140 case DRIVER_ATHEROS:
3141 ath_sta_set_rts(dut, intf, val);
3142 break;
3143 default:
3144#if 0
3145 send_resp(dut, conn, SIGMA_ERROR,
3146 "ErrorCode,Setting RTS not supported");
3147 return 0;
3148#else
3149 sigma_dut_print(dut, DUT_MSG_DEBUG,
3150 "Setting RTS not supported");
3151 break;
3152#endif
3153 }
3154 }
3155
3156#if 0
3157 val = get_param(cmd, "FRGMNT");
3158 if (val) {
3159 /* TODO */
3160 send_resp(dut, conn, SIGMA_ERROR,
3161 "ErrorCode,Setting FRGMNT not supported");
3162 return 0;
3163 }
3164#endif
3165
3166#if 0
3167 val = get_param(cmd, "Preamble");
3168 if (val) {
3169 /* TODO: Long/Short */
3170 send_resp(dut, conn, SIGMA_ERROR,
3171 "ErrorCode,Setting Preamble not supported");
3172 return 0;
3173 }
3174#endif
3175
3176 val = get_param(cmd, "Mode");
3177 if (val) {
3178 if (strcmp(val, "11b") == 0 ||
3179 strcmp(val, "11g") == 0 ||
3180 strcmp(val, "11a") == 0 ||
3181 strcmp(val, "11n") == 0 ||
3182 strcmp(val, "11ng") == 0 ||
3183 strcmp(val, "11nl") == 0 ||
3184 strcmp(val, "11nl(nabg)") == 0 ||
3185 strcmp(val, "AC") == 0 ||
3186 strcmp(val, "11AC") == 0 ||
3187 strcmp(val, "11ac") == 0 ||
3188 strcmp(val, "11na") == 0 ||
3189 strcmp(val, "11an") == 0) {
3190 /* STA supports all modes by default */
3191 } else {
3192 send_resp(dut, conn, SIGMA_ERROR,
3193 "ErrorCode,Setting Mode not supported");
3194 return 0;
3195 }
3196 }
3197
3198 val = get_param(cmd, "wmm");
3199 if (val) {
3200 switch (get_driver_type()) {
3201 case DRIVER_ATHEROS:
3202 ath_sta_set_wmm(dut, intf, val);
3203 break;
3204 default:
3205 sigma_dut_print(dut, DUT_MSG_DEBUG,
3206 "Setting wmm not supported");
3207 break;
3208 }
3209 }
3210
3211 val = get_param(cmd, "Powersave");
3212 if (val) {
3213 if (strcmp(val, "0") == 0 || strcasecmp(val, "off") == 0) {
3214 if (wpa_command(get_station_ifname(),
3215 "P2P_SET ps 0") < 0)
3216 return -2;
3217 /* Make sure test modes are disabled */
3218 wpa_command(get_station_ifname(), "P2P_SET ps 98");
3219 wpa_command(get_station_ifname(), "P2P_SET ps 96");
3220 } else if (strcmp(val, "1") == 0 ||
3221 strcasecmp(val, "PSPoll") == 0 ||
3222 strcasecmp(val, "on") == 0) {
3223 /* Disable default power save mode */
3224 wpa_command(get_station_ifname(), "P2P_SET ps 0");
3225 /* Enable PS-Poll test mode */
3226 if (wpa_command(get_station_ifname(),
3227 "P2P_SET ps 97") < 0 ||
3228 wpa_command(get_station_ifname(),
3229 "P2P_SET ps 99") < 0)
3230 return -2;
3231 } else if (strcmp(val, "2") == 0 ||
3232 strcasecmp(val, "Fast") == 0) {
3233 /* TODO */
3234 send_resp(dut, conn, SIGMA_ERROR,
3235 "ErrorCode,Powersave=Fast not supported");
3236 return 0;
3237 } else if (strcmp(val, "3") == 0 ||
3238 strcasecmp(val, "PSNonPoll") == 0) {
3239 /* Make sure test modes are disabled */
3240 wpa_command(get_station_ifname(), "P2P_SET ps 98");
3241 wpa_command(get_station_ifname(), "P2P_SET ps 96");
3242
3243 /* Enable default power save mode */
3244 if (wpa_command(get_station_ifname(),
3245 "P2P_SET ps 1") < 0)
3246 return -2;
3247 } else
3248 return -1;
3249 }
3250
3251 val = get_param(cmd, "NoAck");
3252 if (val) {
3253 switch (get_driver_type()) {
3254 case DRIVER_ATHEROS:
3255 ath_sta_set_noack(dut, intf, val);
3256 break;
3257 default:
3258 send_resp(dut, conn, SIGMA_ERROR,
3259 "ErrorCode,Setting NoAck not supported");
3260 return 0;
3261 }
3262 }
3263
3264 val = get_param(cmd, "IgnoreChswitchProhibit");
3265 if (val) {
3266 /* TODO: Enabled/disabled */
3267 if (strcasecmp(val, "Enabled") == 0) {
3268 send_resp(dut, conn, SIGMA_ERROR,
3269 "ErrorCode,Enabling IgnoreChswitchProhibit "
3270 "not supported");
3271 return 0;
3272 }
3273 }
3274
3275 val = get_param(cmd, "TDLS");
3276 if (val) {
3277 if (strcasecmp(val, "Disabled") == 0) {
3278 if (wpa_command(intf, "SET tdls_disabled 1")) {
3279 send_resp(dut, conn, SIGMA_ERROR,
3280 "ErrorCode,Failed to disable TDLS");
3281 return 0;
3282 }
3283 } else if (strcasecmp(val, "Enabled") == 0) {
3284 if (wpa_command(intf, "SET tdls_disabled 0")) {
3285 send_resp(dut, conn, SIGMA_ERROR,
3286 "ErrorCode,Failed to enable TDLS");
3287 return 0;
3288 }
3289 } else {
3290 send_resp(dut, conn, SIGMA_ERROR,
3291 "ErrorCode,Unsupported TDLS value");
3292 return 0;
3293 }
3294 }
3295
3296 val = get_param(cmd, "TDLSmode");
3297 if (val) {
3298 if (strcasecmp(val, "Default") == 0) {
3299 wpa_command(intf, "SET tdls_testing 0");
3300 } else if (strcasecmp(val, "APProhibit") == 0) {
3301 if (wpa_command(intf, "SET tdls_testing 0x400")) {
3302 send_resp(dut, conn, SIGMA_ERROR,
3303 "ErrorCode,Failed to enable ignore "
3304 "APProhibit TDLS mode");
3305 return 0;
3306 }
3307 } else if (strcasecmp(val, "HiLoMac") == 0) {
3308 /* STA should respond with TDLS setup req for a TDLS
3309 * setup req */
3310 if (wpa_command(intf, "SET tdls_testing 0x80")) {
3311 send_resp(dut, conn, SIGMA_ERROR,
3312 "ErrorCode,Failed to enable HiLoMac "
3313 "TDLS mode");
3314 return 0;
3315 }
3316 } else if (strcasecmp(val, "WeakSecurity") == 0) {
3317 /*
3318 * Since all security modes are enabled by default when
3319 * Sigma control is used, there is no need to do
3320 * anything here.
3321 */
3322 } else if (strcasecmp(val, "ExistLink") == 0) {
3323 /*
3324 * Since we allow new TDLS Setup Request even if there
3325 * is an existing link, nothing needs to be done for
3326 * this.
3327 */
3328 } else {
3329 /* TODO:
3330 * ExistLink: STA should send TDLS setup req even if
3331 * direct link already exists
3332 */
3333 send_resp(dut, conn, SIGMA_ERROR,
3334 "ErrorCode,Unsupported TDLSmode value");
3335 return 0;
3336 }
3337 }
3338
3339 val = get_param(cmd, "FakePubKey");
3340 if (val && atoi(val) && wpa_command(intf, "SET wps_corrupt_pkhash 1")) {
3341 send_resp(dut, conn, SIGMA_ERROR,
3342 "ErrorCode,Failed to enable FakePubKey");
3343 return 0;
3344 }
3345
3346 return 1;
3347}
3348
3349
3350static const char * ath_get_radio_name(const char *radio_name)
3351{
3352 if (radio_name == NULL)
3353 return "wifi0";
3354 if (strcmp(radio_name, "wifi1") == 0)
3355 return "wifi1";
3356 if (strcmp(radio_name, "wifi2") == 0)
3357 return "wifi2";
3358 return "wifi0";
3359}
3360
3361
3362static void ath_sta_set_txsp_stream(struct sigma_dut *dut, const char *intf,
3363 const char *val)
3364{
3365 char buf[60];
3366 unsigned int vht_mcsmap = 0;
3367 int txchainmask = 0;
3368 const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
3369
3370 if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
3371 if (dut->testbed_flag_txsp == 1) {
3372 vht_mcsmap = 0xfffc;
3373 dut->testbed_flag_txsp = 0;
3374 } else {
3375 vht_mcsmap = 0xfffe;
3376 }
3377 txchainmask = 1;
3378 } else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
3379 if (dut->testbed_flag_txsp == 1) {
3380 vht_mcsmap = 0xfff0;
3381 dut->testbed_flag_txsp = 0;
3382 } else {
3383 vht_mcsmap = 0xfffa;
3384 }
3385 txchainmask = 3;
3386 } else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
3387 if (dut->testbed_flag_txsp == 1) {
3388 vht_mcsmap = 0xffc0;
3389 dut->testbed_flag_txsp = 0;
3390 } else {
3391 vht_mcsmap = 0xffea;
3392 }
3393 txchainmask = 7;
3394 } else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
3395 if (dut->testbed_flag_txsp == 1) {
3396 vht_mcsmap = 0xff00;
3397 dut->testbed_flag_txsp = 0;
3398 } else {
3399 vht_mcsmap = 0xffaa;
3400 }
3401 txchainmask = 15;
3402 } else {
3403 if (dut->testbed_flag_txsp == 1) {
3404 vht_mcsmap = 0xffc0;
3405 dut->testbed_flag_txsp = 0;
3406 } else {
3407 vht_mcsmap = 0xffea;
3408 }
3409 }
3410
3411 if (txchainmask) {
3412 snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
3413 basedev, txchainmask);
3414 if (system(buf) != 0) {
3415 sigma_dut_print(dut, DUT_MSG_ERROR,
3416 "iwpriv txchainmask failed");
3417 }
3418 }
3419
3420 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
3421 intf, vht_mcsmap);
3422 if (system(buf) != 0) {
3423 sigma_dut_print(dut, DUT_MSG_ERROR,
3424 "iwpriv %s vht_mcsmap 0x%04x failed",
3425 intf, vht_mcsmap);
3426 }
3427}
3428
3429
3430static void ath_sta_set_rxsp_stream(struct sigma_dut *dut, const char *intf,
3431 const char *val)
3432{
3433 char buf[60];
3434 unsigned int vht_mcsmap = 0;
3435 int rxchainmask = 0;
3436 const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
3437
3438 if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
3439 if (dut->testbed_flag_rxsp == 1) {
3440 vht_mcsmap = 0xfffc;
3441 dut->testbed_flag_rxsp = 0;
3442 } else {
3443 vht_mcsmap = 0xfffe;
3444 }
3445 rxchainmask = 1;
3446 } else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
3447 if (dut->testbed_flag_rxsp == 1) {
3448 vht_mcsmap = 0xfff0;
3449 dut->testbed_flag_rxsp = 0;
3450 } else {
3451 vht_mcsmap = 0xfffa;
3452 }
3453 rxchainmask = 3;
3454 } else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
3455 if (dut->testbed_flag_rxsp == 1) {
3456 vht_mcsmap = 0xffc0;
3457 dut->testbed_flag_rxsp = 0;
3458 } else {
3459 vht_mcsmap = 0xffea;
3460 }
3461 rxchainmask = 7;
3462 } else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
3463 if (dut->testbed_flag_rxsp == 1) {
3464 vht_mcsmap = 0xff00;
3465 dut->testbed_flag_rxsp = 0;
3466 } else {
3467 vht_mcsmap = 0xffaa;
3468 }
3469 rxchainmask = 15;
3470 } else {
3471 if (dut->testbed_flag_rxsp == 1) {
3472 vht_mcsmap = 0xffc0;
3473 dut->testbed_flag_rxsp = 0;
3474 } else {
3475 vht_mcsmap = 0xffea;
3476 }
3477 }
3478
3479 if (rxchainmask) {
3480 snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
3481 basedev, rxchainmask);
3482 if (system(buf) != 0) {
3483 sigma_dut_print(dut, DUT_MSG_ERROR,
3484 "iwpriv rxchainmask failed");
3485 }
3486 }
3487
3488 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
3489 intf, vht_mcsmap);
3490 if (system(buf) != 0) {
3491 sigma_dut_print(dut, DUT_MSG_ERROR,
3492 "iwpriv %s vht_mcsmap 0x%04x",
3493 intf, vht_mcsmap);
3494 }
3495}
3496
3497
3498void ath_set_zero_crc(struct sigma_dut *dut, const char *val)
3499{
3500 if (strcasecmp(val, "enable") == 0) {
3501 if (system("athdiag --set --address=0x2a204 --and=0xbfffffff")
3502 != 0) {
3503 sigma_dut_print(dut, DUT_MSG_ERROR,
3504 "Disable BB_VHTSIGB_CRC_CALC failed");
3505 }
3506
3507 if (system("athdiag --set --address=0x2a204 --or=0x80000000")
3508 != 0) {
3509 sigma_dut_print(dut, DUT_MSG_ERROR,
3510 "Enable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
3511 }
3512 } else {
3513 if (system("athdiag --set --address=0x2a204 --and=0x7fffffff")
3514 != 0) {
3515 sigma_dut_print(dut, DUT_MSG_ERROR,
3516 "Disable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
3517 }
3518
3519 if (system("athdiag --set --address=0x2a204 --or=0x40000000")
3520 != 0) {
3521 sigma_dut_print(dut, DUT_MSG_ERROR,
3522 "Enable BB_VHTSIGB_CRC_CALC failed");
3523 }
3524 }
3525}
3526
3527
3528static int cmd_sta_set_wireless_common(const char *intf, struct sigma_dut *dut,
3529 struct sigma_conn *conn,
3530 struct sigma_cmd *cmd)
3531{
3532 const char *val;
3533 int ampdu = -1;
3534 char buf[30];
3535
3536 val = get_param(cmd, "40_INTOLERANT");
3537 if (val) {
3538 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3539 /* TODO: iwpriv ht40intol through wpa_supplicant */
3540 send_resp(dut, conn, SIGMA_ERROR,
3541 "ErrorCode,40_INTOLERANT not supported");
3542 return 0;
3543 }
3544 }
3545
3546 val = get_param(cmd, "ADDBA_REJECT");
3547 if (val) {
3548 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3549 /* reject any ADDBA with status "decline" */
3550 ampdu = 0;
3551 } else {
3552 /* accept ADDBA */
3553 ampdu = 1;
3554 }
3555 }
3556
3557 val = get_param(cmd, "AMPDU");
3558 if (val) {
3559 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3560 /* enable AMPDU Aggregation */
3561 if (ampdu == 0) {
3562 send_resp(dut, conn, SIGMA_ERROR,
3563 "ErrorCode,Mismatch in "
3564 "addba_reject/ampdu - "
3565 "not supported");
3566 return 0;
3567 }
3568 ampdu = 1;
3569 } else {
3570 /* disable AMPDU Aggregation */
3571 if (ampdu == 1) {
3572 send_resp(dut, conn, SIGMA_ERROR,
3573 "ErrorCode,Mismatch in "
3574 "addba_reject/ampdu - "
3575 "not supported");
3576 return 0;
3577 }
3578 ampdu = 0;
3579 }
3580 }
3581
3582 if (ampdu >= 0) {
3583 sigma_dut_print(dut, DUT_MSG_DEBUG, "%s A-MPDU aggregation",
3584 ampdu ? "Enabling" : "Disabling");
3585 snprintf(buf, sizeof(buf), "SET ampdu %d", ampdu);
Deepak Dhamdhere80356cb2016-03-28 16:48:32 -07003586 if (wpa_command(intf, buf) < 0 &&
3587 iwpriv_sta_set_ampdu(dut, intf, ampdu) < 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003588 send_resp(dut, conn, SIGMA_ERROR,
3589 "ErrorCode,set aggr failed");
3590 return 0;
3591 }
3592 }
3593
3594 val = get_param(cmd, "AMSDU");
3595 if (val) {
3596 switch (get_driver_type()) {
3597 case DRIVER_ATHEROS:
3598 ath_sta_set_amsdu(dut, intf, val);
3599 break;
3600 default:
3601 if (strcmp(val, "1") == 0 ||
3602 strcasecmp(val, "Enable") == 0) {
3603 /* Enable AMSDU Aggregation */
3604 send_resp(dut, conn, SIGMA_ERROR,
3605 "ErrorCode,AMSDU aggregation not supported");
3606 return 0;
3607 }
3608 break;
3609 }
3610 }
3611
3612 val = get_param(cmd, "STBC_RX");
3613 if (val) {
3614 switch (get_driver_type()) {
3615 case DRIVER_ATHEROS:
3616 ath_sta_set_stbc(dut, intf, val);
3617 break;
Pradeep Reddy POTTETI4a1f6b32016-11-23 13:15:21 +05303618 case DRIVER_WCN:
3619 wcn_sta_set_stbc(dut, intf, val);
3620 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003621 default:
3622 send_resp(dut, conn, SIGMA_ERROR,
3623 "ErrorCode,STBC_RX not supported");
3624 return 0;
3625 }
3626 }
3627
3628 val = get_param(cmd, "WIDTH");
3629 if (val) {
3630 switch (get_driver_type()) {
3631 case DRIVER_WCN:
3632 if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
3633 send_resp(dut, conn, SIGMA_ERROR,
3634 "ErrorCode,Failed to set WIDTH");
3635 return 0;
3636 }
3637 break;
3638 case DRIVER_ATHEROS:
3639 if (ath_set_width(dut, conn, intf, val) < 0)
3640 return 0;
3641 break;
3642 default:
3643 sigma_dut_print(dut, DUT_MSG_ERROR,
3644 "Setting WIDTH not supported");
3645 break;
3646 }
3647 }
3648
3649 val = get_param(cmd, "SMPS");
3650 if (val) {
3651 /* TODO: Dynamic/0, Static/1, No Limit/2 */
3652 send_resp(dut, conn, SIGMA_ERROR,
3653 "ErrorCode,SMPS not supported");
3654 return 0;
3655 }
3656
3657 val = get_param(cmd, "TXSP_STREAM");
3658 if (val) {
3659 switch (get_driver_type()) {
3660 case DRIVER_WCN:
3661 if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
3662 send_resp(dut, conn, SIGMA_ERROR,
3663 "ErrorCode,Failed to set TXSP_STREAM");
3664 return 0;
3665 }
3666 break;
3667 case DRIVER_ATHEROS:
3668 ath_sta_set_txsp_stream(dut, intf, val);
3669 break;
3670 default:
3671 sigma_dut_print(dut, DUT_MSG_ERROR,
3672 "Setting TXSP_STREAM not supported");
3673 break;
3674 }
3675 }
3676
3677 val = get_param(cmd, "RXSP_STREAM");
3678 if (val) {
3679 switch (get_driver_type()) {
3680 case DRIVER_WCN:
3681 if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
3682 send_resp(dut, conn, SIGMA_ERROR,
3683 "ErrorCode,Failed to set RXSP_STREAM");
3684 return 0;
3685 }
3686 break;
3687 case DRIVER_ATHEROS:
3688 ath_sta_set_rxsp_stream(dut, intf, val);
3689 break;
3690 default:
3691 sigma_dut_print(dut, DUT_MSG_ERROR,
3692 "Setting RXSP_STREAM not supported");
3693 break;
3694 }
3695 }
3696
3697 val = get_param(cmd, "DYN_BW_SGNL");
3698 if (val) {
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003699 switch (get_driver_type()) {
3700 case DRIVER_WCN:
Peng Xuc59afd32016-11-21 15:01:11 -08003701 if (strcasecmp(val, "enable") == 0) {
3702 snprintf(buf, sizeof(buf),
3703 "iwpriv %s cwmenable 1", intf);
3704 if (system(buf) != 0) {
3705 sigma_dut_print(dut, DUT_MSG_ERROR,
3706 "iwpriv cwmenable 1 failed");
3707 return 0;
3708 }
3709 } else if (strcasecmp(val, "disable") == 0) {
3710 snprintf(buf, sizeof(buf),
3711 "iwpriv %s cwmenable 0", intf);
3712 if (system(buf) != 0) {
3713 sigma_dut_print(dut, DUT_MSG_ERROR,
3714 "iwpriv cwmenable 0 failed");
3715 return 0;
3716 }
3717 } else {
3718 sigma_dut_print(dut, DUT_MSG_ERROR,
3719 "Unsupported DYN_BW_SGL");
3720 }
3721
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003722 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
3723 if (system(buf) != 0) {
3724 sigma_dut_print(dut, DUT_MSG_ERROR,
3725 "Failed to set cts_cbw in DYN_BW_SGNL");
3726 return 0;
3727 }
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003728 break;
3729 case DRIVER_ATHEROS:
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08003730 novap_reset(dut, intf);
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003731 ath_config_dyn_bw_sig(dut, intf, val);
3732 break;
3733 default:
3734 sigma_dut_print(dut, DUT_MSG_ERROR,
3735 "Failed to set DYN_BW_SGNL");
3736 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003737 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003738 }
3739
3740 val = get_param(cmd, "RTS_FORCE");
3741 if (val) {
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08003742 novap_reset(dut, intf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003743 if (strcasecmp(val, "Enable") == 0) {
3744 snprintf(buf, sizeof(buf), "iwconfig %s rts 64", intf);
Priyadharshini Gowthamanabdb2122015-11-17 11:52:19 +02003745 if (system(buf) != 0) {
3746 sigma_dut_print(dut, DUT_MSG_ERROR,
3747 "Failed to set RTS_FORCE 64");
3748 }
priyadharshini gowthaman270870e2015-12-09 10:10:23 -08003749 snprintf(buf, sizeof(buf),
3750 "wifitool %s beeliner_fw_test 100 1", intf);
3751 if (system(buf) != 0) {
3752 sigma_dut_print(dut, DUT_MSG_ERROR,
3753 "wifitool beeliner_fw_test 100 1 failed");
3754 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003755 } else if (strcasecmp(val, "Disable") == 0) {
3756 snprintf(buf, sizeof(buf), "iwconfig %s rts 2347",
3757 intf);
Priyadharshini Gowthamanabdb2122015-11-17 11:52:19 +02003758 if (system(buf) != 0) {
3759 sigma_dut_print(dut, DUT_MSG_ERROR,
3760 "Failed to set RTS_FORCE 2347");
3761 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003762 } else {
3763 send_resp(dut, conn, SIGMA_ERROR,
3764 "ErrorCode,RTS_FORCE value not supported");
3765 return 0;
3766 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003767 }
3768
3769 val = get_param(cmd, "CTS_WIDTH");
3770 if (val) {
3771 switch (get_driver_type()) {
3772 case DRIVER_WCN:
3773 if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
3774 send_resp(dut, conn, SIGMA_ERROR,
3775 "ErrorCode,Failed to set CTS_WIDTH");
3776 return 0;
3777 }
3778 break;
3779 case DRIVER_ATHEROS:
3780 ath_set_cts_width(dut, intf, val);
3781 break;
3782 default:
3783 sigma_dut_print(dut, DUT_MSG_ERROR,
3784 "Setting CTS_WIDTH not supported");
3785 break;
3786 }
3787 }
3788
3789 val = get_param(cmd, "BW_SGNL");
3790 if (val) {
3791 if (strcasecmp(val, "Enable") == 0) {
3792 snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1",
3793 intf);
3794 } else if (strcasecmp(val, "Disable") == 0) {
3795 /* TODO: Disable */
3796 buf[0] = '\0';
3797 } else {
3798 send_resp(dut, conn, SIGMA_ERROR,
3799 "ErrorCode,BW_SGNL value not supported");
3800 return 0;
3801 }
3802
3803 if (buf[0] != '\0' && system(buf) != 0) {
3804 sigma_dut_print(dut, DUT_MSG_ERROR,
3805 "Failed to set BW_SGNL");
3806 }
3807 }
3808
3809 val = get_param(cmd, "Band");
3810 if (val) {
3811 if (strcmp(val, "2.4") == 0 || strcmp(val, "5") == 0) {
3812 /* STA supports all bands by default */
3813 } else {
3814 send_resp(dut, conn, SIGMA_ERROR,
3815 "ErrorCode,Unsupported Band");
3816 return 0;
3817 }
3818 }
3819
3820 val = get_param(cmd, "zero_crc");
3821 if (val) {
3822 switch (get_driver_type()) {
3823 case DRIVER_ATHEROS:
3824 ath_set_zero_crc(dut, val);
3825 break;
3826 default:
3827 break;
3828 }
3829 }
3830
3831 return 1;
3832}
3833
3834
3835static int sta_set_60g_common(struct sigma_dut *dut, struct sigma_conn *conn,
3836 struct sigma_cmd *cmd)
3837{
3838 const char *val;
3839 char buf[100];
3840
3841 val = get_param(cmd, "MSDUSize");
3842 if (val) {
3843 int mtu;
3844
3845 dut->amsdu_size = atoi(val);
3846 if (dut->amsdu_size > IEEE80211_MAX_DATA_LEN_DMG ||
3847 dut->amsdu_size < IEEE80211_SNAP_LEN_DMG) {
3848 sigma_dut_print(dut, DUT_MSG_ERROR,
3849 "MSDUSize %d is above max %d or below min %d",
3850 dut->amsdu_size,
3851 IEEE80211_MAX_DATA_LEN_DMG,
3852 IEEE80211_SNAP_LEN_DMG);
3853 dut->amsdu_size = 0;
3854 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3855 }
3856
3857 mtu = dut->amsdu_size - IEEE80211_SNAP_LEN_DMG;
3858 sigma_dut_print(dut, DUT_MSG_DEBUG,
3859 "Setting amsdu_size to %d", mtu);
3860 snprintf(buf, sizeof(buf), "ifconfig %s mtu %d",
3861 get_station_ifname(), mtu);
3862
3863 if (system(buf) != 0) {
3864 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set %s",
3865 buf);
3866 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3867 }
3868 }
3869
3870 val = get_param(cmd, "BAckRcvBuf");
3871 if (val) {
3872 dut->back_rcv_buf = atoi(val);
3873 if (dut->back_rcv_buf == 0) {
3874 sigma_dut_print(dut, DUT_MSG_ERROR,
3875 "Failed to convert %s or value is 0",
3876 val);
3877 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3878 }
3879
3880 sigma_dut_print(dut, DUT_MSG_DEBUG,
3881 "Setting BAckRcvBuf to %s", val);
3882 }
3883
3884 return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
3885}
3886
3887
3888static int sta_pcp_start(struct sigma_dut *dut, struct sigma_conn *conn,
3889 struct sigma_cmd *cmd)
3890{
3891 int net_id;
3892 char *ifname;
3893 const char *val;
3894 char buf[100];
3895
3896 dut->mode = SIGMA_MODE_STATION;
3897 ifname = get_main_ifname();
3898 if (wpa_command(ifname, "PING") != 0) {
3899 sigma_dut_print(dut, DUT_MSG_ERROR, "Supplicant not running");
3900 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3901 }
3902
3903 wpa_command(ifname, "FLUSH");
3904 net_id = add_network_common(dut, conn, ifname, cmd);
3905 if (net_id < 0) {
3906 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add network");
3907 return net_id;
3908 }
3909
3910 /* TODO: mode=2 for the AP; in the future, replace for mode PCP */
3911 if (set_network(ifname, net_id, "mode", "2") < 0) {
3912 sigma_dut_print(dut, DUT_MSG_ERROR,
3913 "Failed to set supplicant network mode");
3914 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3915 }
3916
3917 sigma_dut_print(dut, DUT_MSG_DEBUG,
3918 "Supplicant set network with mode 2");
3919
3920 val = get_param(cmd, "Security");
3921 if (val && strcasecmp(val, "OPEN") == 0) {
3922 dut->ap_key_mgmt = AP_OPEN;
3923 if (set_network(ifname, net_id, "key_mgmt", "NONE") < 0) {
3924 sigma_dut_print(dut, DUT_MSG_ERROR,
3925 "Failed to set supplicant to %s security",
3926 val);
3927 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3928 }
3929 } else if (val && strcasecmp(val, "WPA2-PSK") == 0) {
3930 dut->ap_key_mgmt = AP_WPA2_PSK;
3931 if (set_network(ifname, net_id, "key_mgmt", "WPA-PSK") < 0) {
3932 sigma_dut_print(dut, DUT_MSG_ERROR,
3933 "Failed to set supplicant to %s security",
3934 val);
3935 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3936 }
3937
3938 if (set_network(ifname, net_id, "proto", "RSN") < 0) {
3939 sigma_dut_print(dut, DUT_MSG_ERROR,
3940 "Failed to set supplicant to proto RSN");
3941 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3942 }
3943 } else if (val) {
3944 sigma_dut_print(dut, DUT_MSG_ERROR,
3945 "Requested Security %s is not supported on 60GHz",
3946 val);
3947 return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
3948 }
3949
3950 val = get_param(cmd, "Encrypt");
3951 if (val && strcasecmp(val, "AES-GCMP") == 0) {
3952 if (set_network(ifname, net_id, "pairwise", "GCMP") < 0) {
3953 sigma_dut_print(dut, DUT_MSG_ERROR,
3954 "Failed to set supplicant to pairwise GCMP");
3955 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3956 }
3957 if (set_network(ifname, net_id, "group", "GCMP") < 0) {
3958 sigma_dut_print(dut, DUT_MSG_ERROR,
3959 "Failed to set supplicant to group GCMP");
3960 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3961 }
3962 } else if (val) {
3963 sigma_dut_print(dut, DUT_MSG_ERROR,
3964 "Requested Encrypt %s is not supported on 60 GHz",
3965 val);
3966 return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
3967 }
3968
3969 val = get_param(cmd, "PSK");
3970 if (val && set_network_quoted(ifname, net_id, "psk", val) < 0) {
3971 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set psk %s",
3972 val);
3973 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3974 }
3975
3976 /* Convert 60G channel to freq */
3977 switch (dut->ap_channel) {
3978 case 1:
3979 val = "58320";
3980 break;
3981 case 2:
3982 val = "60480";
3983 break;
3984 case 3:
3985 val = "62640";
3986 break;
3987 default:
3988 sigma_dut_print(dut, DUT_MSG_ERROR,
3989 "Failed to configure channel %d. Not supported",
3990 dut->ap_channel);
3991 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3992 }
3993
3994 if (set_network(ifname, net_id, "frequency", val) < 0) {
3995 sigma_dut_print(dut, DUT_MSG_ERROR,
3996 "Failed to set supplicant network frequency");
3997 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3998 }
3999
4000 sigma_dut_print(dut, DUT_MSG_DEBUG,
4001 "Supplicant set network with frequency");
4002
4003 snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", net_id);
4004 if (wpa_command(ifname, buf) < 0) {
4005 sigma_dut_print(dut, DUT_MSG_INFO,
4006 "Failed to select network id %d on %s",
4007 net_id, ifname);
4008 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
4009 }
4010
4011 sigma_dut_print(dut, DUT_MSG_DEBUG, "Selected network");
4012
4013 return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
4014}
4015
4016
Lior David67543f52017-01-03 19:04:22 +02004017static int wil6210_set_abft_len(struct sigma_dut *dut, int abft_len)
4018{
4019 char buf[128], fname[128];
4020 FILE *f;
4021
4022 if (wil6210_get_debugfs_dir(dut, buf, sizeof(buf))) {
4023 sigma_dut_print(dut, DUT_MSG_ERROR,
4024 "failed to get wil6210 debugfs dir");
4025 return -1;
4026 }
4027
4028 snprintf(fname, sizeof(fname), "%s/abft_len", buf);
4029 f = fopen(fname, "w");
4030 if (!f) {
4031 sigma_dut_print(dut, DUT_MSG_ERROR,
4032 "failed to open: %s", fname);
4033 return -1;
4034 }
4035
4036 fprintf(f, "%d\n", abft_len);
4037 fclose(f);
4038
4039 return 0;
4040}
4041
4042
4043static int sta_set_60g_abft_len(struct sigma_dut *dut, struct sigma_conn *conn,
4044 int abft_len)
4045{
4046 switch (get_driver_type()) {
4047 case DRIVER_WIL6210:
4048 return wil6210_set_abft_len(dut, abft_len);
4049 default:
4050 sigma_dut_print(dut, DUT_MSG_ERROR,
4051 "set abft_len not supported");
4052 return -1;
4053 }
4054}
4055
4056
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004057static int sta_set_60g_pcp(struct sigma_dut *dut, struct sigma_conn *conn,
4058 struct sigma_cmd *cmd)
4059{
4060 const char *val;
Lior David67543f52017-01-03 19:04:22 +02004061 unsigned int abft_len = 1; /* default is one slot */
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004062
4063 if (dut->dev_role != DEVROLE_PCP) {
4064 send_resp(dut, conn, SIGMA_INVALID,
4065 "ErrorCode,Invalid DevRole");
4066 return 0;
4067 }
4068
4069 val = get_param(cmd, "SSID");
4070 if (val) {
4071 if (strlen(val) > sizeof(dut->ap_ssid) - 1) {
4072 send_resp(dut, conn, SIGMA_INVALID,
4073 "ErrorCode,Invalid SSID");
4074 return -1;
4075 }
4076
Peng Xub8fc5cc2017-05-10 17:27:28 -07004077 strlcpy(dut->ap_ssid, val, sizeof(dut->ap_ssid));
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004078 }
4079
4080 val = get_param(cmd, "CHANNEL");
4081 if (val) {
4082 const char *pos;
4083
4084 dut->ap_channel = atoi(val);
4085 pos = strchr(val, ';');
4086 if (pos) {
4087 pos++;
4088 dut->ap_channel_1 = atoi(pos);
4089 }
4090 }
4091
4092 switch (dut->ap_channel) {
4093 case 1:
4094 case 2:
4095 case 3:
4096 break;
4097 default:
4098 sigma_dut_print(dut, DUT_MSG_ERROR,
4099 "Channel %d is not supported", dut->ap_channel);
4100 send_resp(dut, conn, SIGMA_ERROR,
4101 "Requested channel is not supported");
4102 return -1;
4103 }
4104
4105 val = get_param(cmd, "BCNINT");
4106 if (val)
4107 dut->ap_bcnint = atoi(val);
4108
4109
4110 val = get_param(cmd, "ExtSchIE");
4111 if (val) {
4112 send_resp(dut, conn, SIGMA_ERROR,
4113 "ErrorCode,ExtSchIE is not supported yet");
4114 return -1;
4115 }
4116
4117 val = get_param(cmd, "AllocType");
4118 if (val) {
4119 send_resp(dut, conn, SIGMA_ERROR,
4120 "ErrorCode,AllocType is not supported yet");
4121 return -1;
4122 }
4123
4124 val = get_param(cmd, "PercentBI");
4125 if (val) {
4126 send_resp(dut, conn, SIGMA_ERROR,
4127 "ErrorCode,PercentBI is not supported yet");
4128 return -1;
4129 }
4130
4131 val = get_param(cmd, "CBAPOnly");
4132 if (val) {
4133 send_resp(dut, conn, SIGMA_ERROR,
4134 "ErrorCode,CBAPOnly is not supported yet");
4135 return -1;
4136 }
4137
4138 val = get_param(cmd, "AMPDU");
4139 if (val) {
4140 if (strcasecmp(val, "Enable") == 0)
4141 dut->ap_ampdu = 1;
4142 else if (strcasecmp(val, "Disable") == 0)
4143 dut->ap_ampdu = 2;
4144 else {
4145 send_resp(dut, conn, SIGMA_ERROR,
4146 "ErrorCode,AMPDU value is not Enable nor Disabled");
4147 return -1;
4148 }
4149 }
4150
4151 val = get_param(cmd, "AMSDU");
4152 if (val) {
4153 if (strcasecmp(val, "Enable") == 0)
4154 dut->ap_amsdu = 1;
4155 else if (strcasecmp(val, "Disable") == 0)
4156 dut->ap_amsdu = 2;
4157 }
4158
4159 val = get_param(cmd, "NumMSDU");
4160 if (val) {
4161 send_resp(dut, conn, SIGMA_ERROR,
4162 "ErrorCode, NumMSDU is not supported yet");
4163 return -1;
4164 }
4165
4166 val = get_param(cmd, "ABFTLRang");
4167 if (val) {
4168 sigma_dut_print(dut, DUT_MSG_DEBUG,
Lior David67543f52017-01-03 19:04:22 +02004169 "ABFTLRang parameter %s", val);
4170 if (strcmp(val, "Gt1") == 0)
4171 abft_len = 2; /* 2 slots in this case */
4172 }
4173
4174 if (sta_set_60g_abft_len(dut, conn, abft_len)) {
4175 send_resp(dut, conn, SIGMA_ERROR,
4176 "ErrorCode, Can't set ABFT length");
4177 return -1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004178 }
4179
4180 if (sta_pcp_start(dut, conn, cmd) < 0) {
4181 send_resp(dut, conn, SIGMA_ERROR,
4182 "ErrorCode, Can't start PCP role");
4183 return -1;
4184 }
4185
4186 return sta_set_60g_common(dut, conn, cmd);
4187}
4188
4189
4190static int sta_set_60g_sta(struct sigma_dut *dut, struct sigma_conn *conn,
4191 struct sigma_cmd *cmd)
4192{
4193 const char *val = get_param(cmd, "DiscoveryMode");
4194
4195 if (dut->dev_role != DEVROLE_STA) {
4196 send_resp(dut, conn, SIGMA_INVALID,
4197 "ErrorCode,Invalid DevRole");
4198 return 0;
4199 }
4200
4201 if (val) {
4202 sigma_dut_print(dut, DUT_MSG_DEBUG, "Discovery: %s", val);
4203 /* Ignore Discovery mode till Driver expose API. */
4204#if 0
4205 if (strcasecmp(val, "1") == 0) {
4206 send_resp(dut, conn, SIGMA_INVALID,
4207 "ErrorCode,DiscoveryMode 1 not supported");
4208 return 0;
4209 }
4210
4211 if (strcasecmp(val, "0") == 0) {
4212 /* OK */
4213 } else {
4214 send_resp(dut, conn, SIGMA_INVALID,
4215 "ErrorCode,DiscoveryMode not supported");
4216 return 0;
4217 }
4218#endif
4219 }
4220
4221 if (start_sta_mode(dut) != 0)
4222 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
4223 return sta_set_60g_common(dut, conn, cmd);
4224}
4225
4226
4227static int cmd_sta_disconnect(struct sigma_dut *dut, struct sigma_conn *conn,
4228 struct sigma_cmd *cmd)
4229{
4230 const char *intf = get_param(cmd, "Interface");
4231 disconnect_station(dut);
4232 /* Try to ignore old scan results to avoid HS 2.0R2 test case failures
4233 * due to cached results. */
4234 wpa_command(intf, "SET ignore_old_scan_res 1");
4235 wpa_command(intf, "BSS_FLUSH");
4236 return 1;
4237}
4238
4239
4240static int cmd_sta_reassoc(struct sigma_dut *dut, struct sigma_conn *conn,
4241 struct sigma_cmd *cmd)
4242{
4243 const char *intf = get_param(cmd, "Interface");
4244 const char *bssid = get_param(cmd, "bssid");
4245 const char *val = get_param(cmd, "CHANNEL");
4246 struct wpa_ctrl *ctrl;
4247 char buf[100];
4248 int res;
4249 int chan = 0;
Ashwini Patil467efef2017-05-25 12:18:27 +05304250 int status = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004251
4252 if (bssid == NULL) {
4253 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing bssid "
4254 "argument");
4255 return 0;
4256 }
4257
4258 if (val)
4259 chan = atoi(val);
4260
4261 if (wifi_chip_type != DRIVER_WCN && wifi_chip_type != DRIVER_AR6003) {
4262 /* The current network may be from sta_associate or
4263 * sta_hs2_associate
4264 */
4265 if (set_network(intf, dut->infra_network_id, "bssid", bssid) <
4266 0 ||
4267 set_network(intf, 0, "bssid", bssid) < 0)
4268 return -2;
4269 }
4270
4271 ctrl = open_wpa_mon(intf);
4272 if (ctrl == NULL) {
4273 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
4274 "wpa_supplicant monitor connection");
4275 return -1;
4276 }
4277
4278 if (wifi_chip_type == DRIVER_WCN) {
4279#ifdef ANDROID
Ashwini Patil4c8158f2017-05-25 12:49:21 +05304280 if (chan) {
4281 unsigned int freq;
4282
4283 freq = channel_to_freq(chan);
4284 if (!freq) {
4285 sigma_dut_print(dut, DUT_MSG_ERROR,
4286 "Invalid channel number provided: %d",
4287 chan);
4288 send_resp(dut, conn, SIGMA_INVALID,
4289 "ErrorCode,Invalid channel number");
4290 goto close_mon_conn;
4291 }
4292 res = snprintf(buf, sizeof(buf),
4293 "SCAN TYPE=ONLY freq=%d", freq);
4294 } else {
4295 res = snprintf(buf, sizeof(buf), "SCAN TYPE=ONLY");
4296 }
4297 if (res < 0 || res >= (int) sizeof(buf)) {
4298 send_resp(dut, conn, SIGMA_ERROR,
4299 "ErrorCode,snprintf failed");
4300 goto close_mon_conn;
4301 }
4302 if (wpa_command(intf, buf) < 0) {
4303 sigma_dut_print(dut, DUT_MSG_INFO,
4304 "Failed to start scan");
4305 send_resp(dut, conn, SIGMA_ERROR,
4306 "ErrorCode,scan failed");
4307 goto close_mon_conn;
4308 }
4309
4310 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
4311 buf, sizeof(buf));
4312 if (res < 0) {
4313 sigma_dut_print(dut, DUT_MSG_INFO,
4314 "Scan did not complete");
4315 send_resp(dut, conn, SIGMA_ERROR,
4316 "ErrorCode,scan did not complete");
4317 goto close_mon_conn;
4318 }
4319
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004320 if (set_network(intf, dut->infra_network_id, "bssid", "any")
4321 < 0) {
4322 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
4323 "bssid to any during FASTREASSOC");
Ashwini Patil467efef2017-05-25 12:18:27 +05304324 status = -2;
4325 goto close_mon_conn;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004326 }
4327 res = snprintf(buf, sizeof(buf), "DRIVER FASTREASSOC %s %d",
4328 bssid, chan);
4329 if (res > 0 && res < (int) sizeof(buf))
4330 res = wpa_command(intf, buf);
4331
4332 if (res < 0 || res >= (int) sizeof(buf)) {
4333 send_resp(dut, conn, SIGMA_ERROR,
4334 "errorCode,Failed to run DRIVER FASTREASSOC");
Ashwini Patil467efef2017-05-25 12:18:27 +05304335 goto close_mon_conn;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004336 }
4337#else /* ANDROID */
4338 sigma_dut_print(dut, DUT_MSG_DEBUG,
4339 "Reassoc using iwpriv - skip chan=%d info",
4340 chan);
4341 snprintf(buf, sizeof(buf), "iwpriv %s reassoc", intf);
4342 if (system(buf) != 0) {
4343 sigma_dut_print(dut, DUT_MSG_ERROR, "%s failed", buf);
Ashwini Patil467efef2017-05-25 12:18:27 +05304344 status = -2;
4345 goto close_mon_conn;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004346 }
4347#endif /* ANDROID */
4348 sigma_dut_print(dut, DUT_MSG_INFO,
4349 "sta_reassoc: Run %s successful", buf);
4350 } else if (wpa_command(intf, "REASSOCIATE")) {
4351 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
4352 "request reassociation");
Ashwini Patil467efef2017-05-25 12:18:27 +05304353 goto close_mon_conn;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004354 }
4355
4356 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
4357 buf, sizeof(buf));
Ashwini Patil467efef2017-05-25 12:18:27 +05304358 if (res < 0) {
4359 sigma_dut_print(dut, DUT_MSG_INFO, "Connection did not complete");
4360 status = -1;
4361 goto close_mon_conn;
4362 }
4363 status = 1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004364
Ashwini Patil467efef2017-05-25 12:18:27 +05304365close_mon_conn:
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004366 wpa_ctrl_detach(ctrl);
4367 wpa_ctrl_close(ctrl);
Ashwini Patil467efef2017-05-25 12:18:27 +05304368 return status;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004369}
4370
4371
4372static void hs2_clear_credentials(const char *intf)
4373{
4374 wpa_command(intf, "REMOVE_CRED all");
4375}
4376
4377
Lior Davidcc88b562017-01-03 18:52:09 +02004378#ifdef __linux__
4379static int wil6210_get_aid(struct sigma_dut *dut, const char *bssid,
4380 unsigned int *aid)
4381{
Lior David0fe101e2017-03-09 16:09:50 +02004382 const char *pattern = "AID[ \t]+([0-9]+)";
Lior Davidcc88b562017-01-03 18:52:09 +02004383
Lior David0fe101e2017-03-09 16:09:50 +02004384 return wil6210_get_sta_info_field(dut, bssid, pattern, aid);
Lior Davidcc88b562017-01-03 18:52:09 +02004385}
4386#endif /* __linux__ */
4387
4388
4389static int sta_get_aid_60g(struct sigma_dut *dut, const char *bssid,
4390 unsigned int *aid)
4391{
4392 switch (get_driver_type()) {
4393#ifdef __linux__
4394 case DRIVER_WIL6210:
4395 return wil6210_get_aid(dut, bssid, aid);
4396#endif /* __linux__ */
4397 default:
4398 sigma_dut_print(dut, DUT_MSG_ERROR, "get AID not supported");
4399 return -1;
4400 }
4401}
4402
4403
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004404static int sta_get_parameter_60g(struct sigma_dut *dut, struct sigma_conn *conn,
4405 struct sigma_cmd *cmd)
4406{
4407 char buf[MAX_CMD_LEN];
4408 char bss_list[MAX_CMD_LEN];
4409 const char *parameter = get_param(cmd, "Parameter");
4410
4411 if (parameter == NULL)
4412 return -1;
4413
Lior Davidcc88b562017-01-03 18:52:09 +02004414 if (strcasecmp(parameter, "AID") == 0) {
4415 unsigned int aid = 0;
4416 char bssid[20];
4417
4418 if (get_wpa_status(get_station_ifname(), "bssid",
4419 bssid, sizeof(bssid)) < 0) {
4420 sigma_dut_print(dut, DUT_MSG_ERROR,
4421 "could not get bssid");
4422 return -2;
4423 }
4424
4425 if (sta_get_aid_60g(dut, bssid, &aid))
4426 return -2;
4427
4428 snprintf(buf, sizeof(buf), "aid,%d", aid);
4429 sigma_dut_print(dut, DUT_MSG_INFO, "%s", buf);
4430 send_resp(dut, conn, SIGMA_COMPLETE, buf);
4431 return 0;
4432 }
4433
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004434 if (strcasecmp(parameter, "DiscoveredDevList") == 0) {
4435 char *bss_line;
4436 char *bss_id = NULL;
4437 const char *ifname = get_param(cmd, "Interface");
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304438 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004439
4440 if (ifname == NULL) {
4441 sigma_dut_print(dut, DUT_MSG_INFO,
4442 "For get DiscoveredDevList need Interface name.");
4443 return -1;
4444 }
4445
4446 /*
4447 * Use "BSS RANGE=ALL MASK=0x2" which provides a list
4448 * of BSSIDs in "bssid=<BSSID>\n"
4449 */
4450 if (wpa_command_resp(ifname, "BSS RANGE=ALL MASK=0x2",
4451 bss_list,
4452 sizeof(bss_list)) < 0) {
4453 sigma_dut_print(dut, DUT_MSG_ERROR,
4454 "Failed to get bss list");
4455 return -1;
4456 }
4457
4458 sigma_dut_print(dut, DUT_MSG_DEBUG,
4459 "bss list for ifname:%s is:%s",
4460 ifname, bss_list);
4461
4462 snprintf(buf, sizeof(buf), "DeviceList");
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304463 bss_line = strtok_r(bss_list, "\n", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004464 while (bss_line) {
4465 if (sscanf(bss_line, "bssid=%ms", &bss_id) > 0 &&
4466 bss_id) {
4467 int len;
4468
4469 len = snprintf(buf + strlen(buf),
4470 sizeof(buf) - strlen(buf),
4471 ",%s", bss_id);
4472 free(bss_id);
4473 bss_id = NULL;
4474 if (len < 0) {
4475 sigma_dut_print(dut,
4476 DUT_MSG_ERROR,
4477 "Failed to read BSSID");
4478 send_resp(dut, conn, SIGMA_ERROR,
4479 "ErrorCode,Failed to read BSS ID");
4480 return 0;
4481 }
4482
4483 if ((size_t) len >= sizeof(buf) - strlen(buf)) {
4484 sigma_dut_print(dut,
4485 DUT_MSG_ERROR,
4486 "Response buf too small for list");
4487 send_resp(dut, conn,
4488 SIGMA_ERROR,
4489 "ErrorCode,Response buf too small for list");
4490 return 0;
4491 }
4492 }
4493
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304494 bss_line = strtok_r(NULL, "\n", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004495 }
4496
4497 sigma_dut_print(dut, DUT_MSG_INFO, "DiscoveredDevList is %s",
4498 buf);
4499 send_resp(dut, conn, SIGMA_COMPLETE, buf);
4500 return 0;
4501 }
4502
4503 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4504 return 0;
4505}
4506
4507
4508static int cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
4509 struct sigma_cmd *cmd)
4510{
4511 const char *program = get_param(cmd, "Program");
4512
4513 if (program == NULL)
4514 return -1;
4515
4516 if (strcasecmp(program, "P2PNFC") == 0)
4517 return p2p_cmd_sta_get_parameter(dut, conn, cmd);
4518
4519 if (strcasecmp(program, "60ghz") == 0)
4520 return sta_get_parameter_60g(dut, conn, cmd);
4521
4522#ifdef ANDROID_NAN
4523 if (strcasecmp(program, "NAN") == 0)
Amarnath Hullur Subramanyam1854ec62016-08-11 19:29:35 -07004524 return nan_cmd_sta_get_parameter(dut, conn, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004525#endif /* ANDROID_NAN */
4526
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004527#ifdef MIRACAST
4528 if (strcasecmp(program, "WFD") == 0 ||
4529 strcasecmp(program, "DisplayR2") == 0)
4530 return miracast_cmd_sta_get_parameter(dut, conn, cmd);
4531#endif /* MIRACAST */
4532
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004533 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4534 return 0;
4535}
4536
4537
4538static void sta_reset_default_ath(struct sigma_dut *dut, const char *intf,
4539 const char *type)
4540{
4541 char buf[100];
4542
4543 if (dut->program == PROGRAM_VHT) {
4544 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
4545 if (system(buf) != 0) {
4546 sigma_dut_print(dut, DUT_MSG_ERROR,
4547 "iwpriv %s chwidth failed", intf);
4548 }
4549
4550 snprintf(buf, sizeof(buf), "iwpriv %s mode 11ACVHT80", intf);
4551 if (system(buf) != 0) {
4552 sigma_dut_print(dut, DUT_MSG_ERROR,
4553 "iwpriv %s mode 11ACVHT80 failed",
4554 intf);
4555 }
4556
4557 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs -1", intf);
4558 if (system(buf) != 0) {
4559 sigma_dut_print(dut, DUT_MSG_ERROR,
4560 "iwpriv %s vhtmcs -1 failed", intf);
4561 }
4562 }
4563
4564 if (dut->program == PROGRAM_HT) {
4565 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
4566 if (system(buf) != 0) {
4567 sigma_dut_print(dut, DUT_MSG_ERROR,
4568 "iwpriv %s chwidth failed", intf);
4569 }
4570
4571 snprintf(buf, sizeof(buf), "iwpriv %s mode 11naht40", intf);
4572 if (system(buf) != 0) {
4573 sigma_dut_print(dut, DUT_MSG_ERROR,
4574 "iwpriv %s mode 11naht40 failed",
4575 intf);
4576 }
4577
4578 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0", intf);
4579 if (system(buf) != 0) {
4580 sigma_dut_print(dut, DUT_MSG_ERROR,
4581 "iwpriv set11NRates failed");
4582 }
4583 }
4584
4585 if (dut->program == PROGRAM_VHT || dut->program == PROGRAM_HT) {
4586 snprintf(buf, sizeof(buf), "iwpriv %s powersave 0", intf);
4587 if (system(buf) != 0) {
4588 sigma_dut_print(dut, DUT_MSG_ERROR,
4589 "disabling powersave failed");
4590 }
4591
4592 /* Reset CTS width */
4593 snprintf(buf, sizeof(buf), "wifitool %s beeliner_fw_test 54 0",
4594 intf);
4595 if (system(buf) != 0) {
4596 sigma_dut_print(dut, DUT_MSG_ERROR,
4597 "wifitool %s beeliner_fw_test 54 0 failed",
4598 intf);
4599 }
4600
4601 /* Enable Dynamic Bandwidth signalling by default */
4602 snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1", intf);
4603 if (system(buf) != 0) {
4604 sigma_dut_print(dut, DUT_MSG_ERROR,
4605 "iwpriv %s cwmenable 1 failed", intf);
4606 }
4607
4608 snprintf(buf, sizeof(buf), "iwconfig %s rts 2347", intf);
4609 if (system(buf) != 0) {
4610 sigma_dut_print(dut, DUT_MSG_ERROR,
4611 "iwpriv rts failed");
4612 }
4613 }
4614
4615 if (type && strcasecmp(type, "Testbed") == 0) {
4616 dut->testbed_flag_txsp = 1;
4617 dut->testbed_flag_rxsp = 1;
4618 /* STA has to set spatial stream to 2 per Appendix H */
4619 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0xfff0", intf);
4620 if (system(buf) != 0) {
4621 sigma_dut_print(dut, DUT_MSG_ERROR,
4622 "iwpriv vht_mcsmap failed");
4623 }
4624
4625 /* Disable LDPC per Appendix H */
4626 snprintf(buf, sizeof(buf), "iwpriv %s ldpc 0", intf);
4627 if (system(buf) != 0) {
4628 sigma_dut_print(dut, DUT_MSG_ERROR,
4629 "iwpriv %s ldpc 0 failed", intf);
4630 }
4631
4632 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
4633 if (system(buf) != 0) {
4634 sigma_dut_print(dut, DUT_MSG_ERROR,
4635 "iwpriv amsdu failed");
4636 }
4637
4638 /* TODO: Disable STBC 2x1 transmit and receive */
4639 snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc 0", intf);
4640 if (system(buf) != 0) {
4641 sigma_dut_print(dut, DUT_MSG_ERROR,
4642 "Disable tx_stbc 0 failed");
4643 }
4644
4645 snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc 0", intf);
4646 if (system(buf) != 0) {
4647 sigma_dut_print(dut, DUT_MSG_ERROR,
4648 "Disable rx_stbc 0 failed");
4649 }
4650
4651 /* STA has to disable Short GI per Appendix H */
4652 snprintf(buf, sizeof(buf), "iwpriv %s shortgi 0", intf);
4653 if (system(buf) != 0) {
4654 sigma_dut_print(dut, DUT_MSG_ERROR,
4655 "iwpriv %s shortgi 0 failed", intf);
4656 }
4657 }
4658
4659 if (type && strcasecmp(type, "DUT") == 0) {
4660 snprintf(buf, sizeof(buf), "iwpriv %s nss 3", intf);
4661 if (system(buf) != 0) {
4662 sigma_dut_print(dut, DUT_MSG_ERROR,
4663 "iwpriv %s nss 3 failed", intf);
4664 }
4665
4666 snprintf(buf, sizeof(buf), "iwpriv %s shortgi 1", intf);
4667 if (system(buf) != 0) {
4668 sigma_dut_print(dut, DUT_MSG_ERROR,
4669 "iwpriv %s shortgi 1 failed", intf);
4670 }
4671 }
4672}
4673
4674
4675static int cmd_sta_reset_default(struct sigma_dut *dut,
4676 struct sigma_conn *conn,
4677 struct sigma_cmd *cmd)
4678{
4679 int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn,
4680 struct sigma_cmd *cmd);
4681 const char *intf = get_param(cmd, "Interface");
4682 const char *type;
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004683 const char *program = get_param(cmd, "program");
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004684
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004685 if (!program)
4686 program = get_param(cmd, "prog");
4687 dut->program = sigma_program_to_enum(program);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004688 dut->device_type = STA_unknown;
4689 type = get_param(cmd, "type");
4690 if (type && strcasecmp(type, "Testbed") == 0)
4691 dut->device_type = STA_testbed;
4692 if (type && strcasecmp(type, "DUT") == 0)
4693 dut->device_type = STA_dut;
4694
4695 if (dut->program == PROGRAM_TDLS) {
4696 /* Clear TDLS testing mode */
4697 wpa_command(intf, "SET tdls_disabled 0");
4698 wpa_command(intf, "SET tdls_testing 0");
4699 dut->no_tpk_expiration = 0;
Pradeep Reddy POTTETI8ce2a232016-10-28 12:17:32 +05304700 if (get_driver_type() == DRIVER_WCN) {
4701 /* Enable the WCN driver in TDLS Explicit trigger mode
4702 */
4703 wpa_command(intf, "SET tdls_external_control 0");
4704 wpa_command(intf, "SET tdls_trigger_control 0");
4705 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004706 }
4707
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004708#ifdef MIRACAST
4709 if (dut->program == PROGRAM_WFD ||
4710 dut->program == PROGRAM_DISPLAYR2)
4711 miracast_sta_reset_default(dut, conn, cmd);
4712#endif /* MIRACAST */
4713
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004714 switch (get_driver_type()) {
4715 case DRIVER_ATHEROS:
4716 sta_reset_default_ath(dut, intf, type);
4717 break;
4718 default:
4719 break;
4720 }
4721
4722#ifdef ANDROID_NAN
4723 if (dut->program == PROGRAM_NAN)
4724 nan_cmd_sta_reset_default(dut, conn, cmd);
4725#endif /* ANDROID_NAN */
4726
4727 if (dut->program == PROGRAM_HS2_R2) {
4728 unlink("SP/wi-fi.org/pps.xml");
4729 if (system("rm -r SP/*") != 0) {
4730 }
4731 unlink("next-client-cert.pem");
4732 unlink("next-client-key.pem");
4733 }
4734
4735 if (dut->program == PROGRAM_60GHZ) {
4736 const char *dev_role = get_param(cmd, "DevRole");
4737
4738 if (!dev_role) {
4739 send_resp(dut, conn, SIGMA_ERROR,
4740 "errorCode,Missing DevRole argument");
4741 return 0;
4742 }
4743
4744 if (strcasecmp(dev_role, "STA") == 0)
4745 dut->dev_role = DEVROLE_STA;
4746 else if (strcasecmp(dev_role, "PCP") == 0)
4747 dut->dev_role = DEVROLE_PCP;
4748 else {
4749 send_resp(dut, conn, SIGMA_ERROR,
4750 "errorCode,Unknown DevRole");
4751 return 0;
4752 }
4753
4754 if (dut->device_type == STA_unknown) {
4755 sigma_dut_print(dut, DUT_MSG_ERROR,
4756 "Device type is not STA testbed or DUT");
4757 send_resp(dut, conn, SIGMA_ERROR,
4758 "errorCode,Unknown device type");
4759 return 0;
4760 }
4761 }
4762
4763 wpa_command(intf, "WPS_ER_STOP");
4764 wpa_command(intf, "FLUSH");
4765 wpa_command(intf, "SET radio_disabled 0");
4766
4767 if (dut->tmp_mac_addr && dut->set_macaddr) {
4768 dut->tmp_mac_addr = 0;
4769 if (system(dut->set_macaddr) != 0) {
4770 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to clear "
4771 "temporary MAC address");
4772 }
4773 }
4774
4775 set_ps(intf, dut, 0);
4776
4777 if (dut->program == PROGRAM_HS2 || dut->program == PROGRAM_HS2_R2) {
4778 wpa_command(intf, "SET interworking 1");
4779 wpa_command(intf, "SET hs20 1");
4780 }
4781
4782 if (dut->program == PROGRAM_HS2_R2) {
4783 wpa_command(intf, "SET pmf 1");
4784 } else {
4785 wpa_command(intf, "SET pmf 0");
4786 }
4787
4788 hs2_clear_credentials(intf);
4789 wpa_command(intf, "SET hessid 00:00:00:00:00:00");
4790 wpa_command(intf, "SET access_network_type 15");
4791
4792 static_ip_file(0, NULL, NULL, NULL);
4793 kill_dhcp_client(dut, intf);
4794 clear_ip_addr(dut, intf);
4795
4796 dut->er_oper_performed = 0;
4797 dut->er_oper_bssid[0] = '\0';
4798
priyadharshini gowthamanad6cbba2016-10-04 10:39:58 -07004799 if (dut->program == PROGRAM_LOC) {
4800 /* Disable Interworking by default */
4801 wpa_command(get_station_ifname(), "SET interworking 0");
4802 }
4803
Ashwini Patil00402582017-04-13 12:29:39 +05304804 if (dut->program == PROGRAM_MBO) {
4805 free(dut->non_pref_ch_list);
4806 dut->non_pref_ch_list = NULL;
Ashwini Patil5acd7382017-04-13 15:55:04 +05304807 free(dut->btm_query_cand_list);
4808 dut->btm_query_cand_list = NULL;
Ashwini Patilc63161e2017-04-13 16:30:23 +05304809 wpa_command(intf, "SET reject_btm_req_reason 0");
Ashwini Patila75de5a2017-04-13 16:35:05 +05304810 wpa_command(intf, "SET ignore_assoc_disallow 0");
Ashwini Patild174f2c2017-04-13 16:49:46 +05304811 wpa_command(intf, "SET gas_address3 0");
Ashwini Patil9183fdb2017-04-13 16:58:25 +05304812 wpa_command(intf, "SET roaming 1");
Ashwini Patil00402582017-04-13 12:29:39 +05304813 }
4814
Priyadharshini Gowthamana7dfd492015-11-09 14:34:08 -08004815 if (dut->program != PROGRAM_VHT)
4816 return cmd_sta_p2p_reset(dut, conn, cmd);
4817 return 1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004818}
4819
4820
4821static int cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
4822 struct sigma_cmd *cmd)
4823{
4824 const char *program = get_param(cmd, "Program");
4825
4826 if (program == NULL)
4827 return -1;
4828#ifdef ANDROID_NAN
4829 if (strcasecmp(program, "NAN") == 0)
4830 return nan_cmd_sta_get_events(dut, conn, cmd);
4831#endif /* ANDROID_NAN */
4832 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4833 return 0;
4834}
4835
4836
4837static int cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
4838 struct sigma_cmd *cmd)
4839{
4840 const char *program = get_param(cmd, "Prog");
4841
4842 if (program == NULL)
4843 return -1;
4844#ifdef ANDROID_NAN
4845 if (strcasecmp(program, "NAN") == 0)
4846 return nan_cmd_sta_exec_action(dut, conn, cmd);
4847#endif /* ANDROID_NAN */
priyadharshini gowthamand66913a2016-07-29 15:11:17 -07004848 if (strcasecmp(program, "Loc") == 0)
4849 return loc_cmd_sta_exec_action(dut, conn, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004850 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4851 return 0;
4852}
4853
4854
4855static int cmd_sta_set_11n(struct sigma_dut *dut, struct sigma_conn *conn,
4856 struct sigma_cmd *cmd)
4857{
4858 const char *intf = get_param(cmd, "Interface");
4859 const char *val, *mcs32, *rate;
4860
4861 val = get_param(cmd, "GREENFIELD");
4862 if (val) {
4863 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
4864 /* Enable GD */
4865 send_resp(dut, conn, SIGMA_ERROR,
4866 "ErrorCode,GF not supported");
4867 return 0;
4868 }
4869 }
4870
4871 val = get_param(cmd, "SGI20");
4872 if (val) {
4873 switch (get_driver_type()) {
4874 case DRIVER_ATHEROS:
4875 ath_sta_set_sgi(dut, intf, val);
4876 break;
4877 default:
4878 send_resp(dut, conn, SIGMA_ERROR,
4879 "ErrorCode,SGI20 not supported");
4880 return 0;
4881 }
4882 }
4883
4884 mcs32 = get_param(cmd, "MCS32"); /* HT Duplicate Mode Enable/Disable */
4885 rate = get_param(cmd, "MCS_FIXEDRATE"); /* Fixed MCS rate (0..31) */
4886 if (mcs32 && rate) {
4887 /* TODO */
4888 send_resp(dut, conn, SIGMA_ERROR,
4889 "ErrorCode,MCS32,MCS_FIXEDRATE not supported");
4890 return 0;
4891 } else if (mcs32 && !rate) {
4892 /* TODO */
4893 send_resp(dut, conn, SIGMA_ERROR,
4894 "ErrorCode,MCS32 not supported");
4895 return 0;
4896 } else if (!mcs32 && rate) {
4897 switch (get_driver_type()) {
4898 case DRIVER_ATHEROS:
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08004899 novap_reset(dut, intf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004900 ath_sta_set_11nrates(dut, intf, rate);
4901 break;
4902 default:
4903 send_resp(dut, conn, SIGMA_ERROR,
4904 "ErrorCode,MCS32_FIXEDRATE not supported");
4905 return 0;
4906 }
4907 }
4908
4909 return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
4910}
4911
4912
4913static int cmd_sta_set_wireless_vht(struct sigma_dut *dut,
4914 struct sigma_conn *conn,
4915 struct sigma_cmd *cmd)
4916{
4917 const char *intf = get_param(cmd, "Interface");
4918 const char *val;
4919 char buf[30];
4920 int tkip = -1;
4921 int wep = -1;
4922
4923 val = get_param(cmd, "SGI80");
4924 if (val) {
4925 int sgi80;
4926
4927 sgi80 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4928 snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi80);
4929 if (system(buf) != 0) {
4930 sigma_dut_print(dut, DUT_MSG_ERROR,
4931 "iwpriv shortgi failed");
4932 }
4933 }
4934
4935 val = get_param(cmd, "TxBF");
4936 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
4937 snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfee 1", intf);
4938 if (system(buf) != 0) {
4939 sigma_dut_print(dut, DUT_MSG_ERROR,
4940 "iwpriv vhtsubfee failed");
4941 }
4942 snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfer 1", intf);
4943 if (system(buf) != 0) {
4944 sigma_dut_print(dut, DUT_MSG_ERROR,
4945 "iwpriv vhtsubfer failed");
4946 }
4947 }
4948
4949 val = get_param(cmd, "MU_TxBF");
4950 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
4951 switch (get_driver_type()) {
4952 case DRIVER_ATHEROS:
4953 ath_sta_set_txsp_stream(dut, intf, "1SS");
4954 ath_sta_set_rxsp_stream(dut, intf, "1SS");
4955 case DRIVER_WCN:
4956 if (wcn_sta_set_sp_stream(dut, intf, "1SS") < 0) {
4957 send_resp(dut, conn, SIGMA_ERROR,
4958 "ErrorCode,Failed to set RX/TXSP_STREAM");
4959 return 0;
4960 }
4961 default:
4962 sigma_dut_print(dut, DUT_MSG_ERROR,
4963 "Setting SP_STREAM not supported");
4964 break;
4965 }
4966 snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfee 1", intf);
4967 if (system(buf) != 0) {
4968 sigma_dut_print(dut, DUT_MSG_ERROR,
4969 "iwpriv vhtmubfee failed");
4970 }
4971 snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfer 1", intf);
4972 if (system(buf) != 0) {
4973 sigma_dut_print(dut, DUT_MSG_ERROR,
4974 "iwpriv vhtmubfer failed");
4975 }
4976 }
4977
4978 val = get_param(cmd, "LDPC");
4979 if (val) {
4980 int ldpc;
4981
4982 ldpc = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4983 snprintf(buf, sizeof(buf), "iwpriv %s ldpc %d", intf, ldpc);
4984 if (system(buf) != 0) {
4985 sigma_dut_print(dut, DUT_MSG_ERROR,
4986 "iwpriv ldpc failed");
4987 }
4988 }
4989
4990 val = get_param(cmd, "opt_md_notif_ie");
4991 if (val) {
4992 char *result = NULL;
4993 char delim[] = ";";
4994 char token[30];
4995 int value, config_val = 0;
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304996 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004997
Peng Xub8fc5cc2017-05-10 17:27:28 -07004998 strlcpy(token, val, sizeof(token));
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304999 result = strtok_r(token, delim, &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005000
5001 /* Extract the NSS information */
5002 if (result) {
5003 value = atoi(result);
5004 switch (value) {
5005 case 1:
5006 config_val = 1;
5007 break;
5008 case 2:
5009 config_val = 3;
5010 break;
5011 case 3:
5012 config_val = 7;
5013 break;
5014 case 4:
5015 config_val = 15;
5016 break;
5017 default:
5018 config_val = 3;
5019 break;
5020 }
5021
5022 snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
5023 intf, config_val);
5024 if (system(buf) != 0) {
5025 sigma_dut_print(dut, DUT_MSG_ERROR,
5026 "iwpriv rxchainmask failed");
5027 }
5028
5029 snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
5030 intf, config_val);
5031 if (system(buf) != 0) {
5032 sigma_dut_print(dut, DUT_MSG_ERROR,
5033 "iwpriv txchainmask failed");
5034 }
5035 }
5036
5037 /* Extract the channel width information */
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305038 result = strtok_r(NULL, delim, &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005039 if (result) {
5040 value = atoi(result);
5041 switch (value) {
5042 case 20:
5043 config_val = 0;
5044 break;
5045 case 40:
5046 config_val = 1;
5047 break;
5048 case 80:
5049 config_val = 2;
5050 break;
5051 case 160:
5052 config_val = 3;
5053 break;
5054 default:
5055 config_val = 2;
5056 break;
5057 }
5058
5059 dut->chwidth = config_val;
5060
5061 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
5062 intf, config_val);
5063 if (system(buf) != 0) {
5064 sigma_dut_print(dut, DUT_MSG_ERROR,
5065 "iwpriv chwidth failed");
5066 }
5067 }
5068
5069 snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", intf);
5070 if (system(buf) != 0) {
5071 sigma_dut_print(dut, DUT_MSG_ERROR,
5072 "iwpriv opmode_notify failed");
5073 }
5074 }
5075
5076 val = get_param(cmd, "nss_mcs_cap");
5077 if (val) {
5078 int nss, mcs;
5079 char token[20];
5080 char *result = NULL;
5081 unsigned int vht_mcsmap = 0;
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305082 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005083
Peng Xub8fc5cc2017-05-10 17:27:28 -07005084 strlcpy(token, val, sizeof(token));
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305085 result = strtok_r(token, ";", &saveptr);
Pradeep Reddy POTTETIcd649a22016-01-29 12:55:59 +05305086 if (!result) {
5087 sigma_dut_print(dut, DUT_MSG_ERROR,
5088 "VHT NSS not specified");
5089 return 0;
5090 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005091 nss = atoi(result);
5092
5093 snprintf(buf, sizeof(buf), "iwpriv %s nss %d", intf, nss);
5094 if (system(buf) != 0) {
5095 sigma_dut_print(dut, DUT_MSG_ERROR,
5096 "iwpriv nss failed");
5097 }
5098
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305099 result = strtok_r(NULL, ";", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005100 if (result == NULL) {
5101 sigma_dut_print(dut, DUT_MSG_ERROR,
5102 "VHTMCS NOT SPECIFIED!");
5103 return 0;
5104 }
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305105 result = strtok_r(result, "-", &saveptr);
5106 result = strtok_r(NULL, "-", &saveptr);
Pradeep Reddy POTTETIcd649a22016-01-29 12:55:59 +05305107 if (!result) {
5108 sigma_dut_print(dut, DUT_MSG_ERROR,
5109 "VHT MCS not specified");
5110 return 0;
5111 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005112 mcs = atoi(result);
5113
5114 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d", intf, mcs);
5115 if (system(buf) != 0) {
5116 sigma_dut_print(dut, DUT_MSG_ERROR,
5117 "iwpriv mcs failed");
5118 }
5119
5120 switch (nss) {
5121 case 1:
5122 switch (mcs) {
5123 case 7:
5124 vht_mcsmap = 0xfffc;
5125 break;
5126 case 8:
5127 vht_mcsmap = 0xfffd;
5128 break;
5129 case 9:
5130 vht_mcsmap = 0xfffe;
5131 break;
5132 default:
5133 vht_mcsmap = 0xfffe;
5134 break;
5135 }
5136 break;
5137 case 2:
5138 switch (mcs) {
5139 case 7:
5140 vht_mcsmap = 0xfff0;
5141 break;
5142 case 8:
5143 vht_mcsmap = 0xfff5;
5144 break;
5145 case 9:
5146 vht_mcsmap = 0xfffa;
5147 break;
5148 default:
5149 vht_mcsmap = 0xfffa;
5150 break;
5151 }
5152 break;
5153 case 3:
5154 switch (mcs) {
5155 case 7:
5156 vht_mcsmap = 0xffc0;
5157 break;
5158 case 8:
5159 vht_mcsmap = 0xffd5;
5160 break;
5161 case 9:
5162 vht_mcsmap = 0xffea;
5163 break;
5164 default:
5165 vht_mcsmap = 0xffea;
5166 break;
5167 }
5168 break;
5169 default:
5170 vht_mcsmap = 0xffea;
5171 break;
5172 }
5173 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
5174 intf, vht_mcsmap);
5175 if (system(buf) != 0) {
5176 sigma_dut_print(dut, DUT_MSG_ERROR,
5177 "iwpriv vht_mcsmap failed");
5178 }
5179 }
5180
5181 /* UNSUPPORTED: val = get_param(cmd, "Tx_lgi_rate"); */
5182
5183 val = get_param(cmd, "Vht_tkip");
5184 if (val)
5185 tkip = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
5186
5187 val = get_param(cmd, "Vht_wep");
5188 if (val)
5189 wep = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
5190
5191 if (tkip != -1 || wep != -1) {
5192 if ((tkip == 1 && wep != 0) || (wep == 1 && tkip != 0)) {
5193 snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 1",
5194 intf);
5195 } else if ((tkip == 0 && wep != 1) || (wep == 0 && tkip != 1)) {
5196 snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 0",
5197 intf);
5198 } else {
5199 sigma_dut_print(dut, DUT_MSG_ERROR,
5200 "ErrorCode,mixed mode of VHT TKIP/WEP not supported");
5201 return 0;
5202 }
5203
5204 if (system(buf) != 0) {
5205 sigma_dut_print(dut, DUT_MSG_ERROR,
5206 "iwpriv htweptkip failed");
5207 }
5208 }
5209
5210 val = get_param(cmd, "txBandwidth");
5211 if (val) {
5212 switch (get_driver_type()) {
5213 case DRIVER_ATHEROS:
5214 if (ath_set_width(dut, conn, intf, val) < 0) {
5215 send_resp(dut, conn, SIGMA_ERROR,
5216 "ErrorCode,Failed to set txBandwidth");
5217 return 0;
5218 }
5219 break;
5220 default:
5221 sigma_dut_print(dut, DUT_MSG_ERROR,
5222 "Setting txBandwidth not supported");
5223 break;
5224 }
5225 }
5226
5227 return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
5228}
5229
5230
5231static int sta_set_wireless_60g(struct sigma_dut *dut,
5232 struct sigma_conn *conn,
5233 struct sigma_cmd *cmd)
5234{
5235 const char *dev_role = get_param(cmd, "DevRole");
5236
5237 if (!dev_role) {
5238 send_resp(dut, conn, SIGMA_INVALID,
5239 "ErrorCode,DevRole not specified");
5240 return 0;
5241 }
5242
5243 if (strcasecmp(dev_role, "PCP") == 0)
5244 return sta_set_60g_pcp(dut, conn, cmd);
5245 if (strcasecmp(dev_role, "STA") == 0)
5246 return sta_set_60g_sta(dut, conn, cmd);
5247 send_resp(dut, conn, SIGMA_INVALID,
5248 "ErrorCode,DevRole not supported");
5249 return 0;
5250}
5251
5252
5253static int cmd_sta_set_wireless(struct sigma_dut *dut, struct sigma_conn *conn,
5254 struct sigma_cmd *cmd)
5255{
5256 const char *val;
5257
5258 val = get_param(cmd, "Program");
5259 if (val) {
5260 if (strcasecmp(val, "11n") == 0)
5261 return cmd_sta_set_11n(dut, conn, cmd);
5262 if (strcasecmp(val, "VHT") == 0)
5263 return cmd_sta_set_wireless_vht(dut, conn, cmd);
5264 if (strcasecmp(val, "60ghz") == 0)
5265 return sta_set_wireless_60g(dut, conn, cmd);
5266 send_resp(dut, conn, SIGMA_ERROR,
5267 "ErrorCode,Program value not supported");
5268 } else {
5269 send_resp(dut, conn, SIGMA_ERROR,
5270 "ErrorCode,Program argument not available");
5271 }
5272
5273 return 0;
5274}
5275
5276
5277static void ath_sta_inject_frame(struct sigma_dut *dut, const char *intf,
5278 int tid)
5279{
5280 char buf[100];
5281 int tid_to_dscp [] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 };
5282
Pradeep Reddy POTTETId31d1322016-10-13 17:22:03 +05305283 if (tid < 0 ||
5284 tid >= (int) (sizeof(tid_to_dscp) / sizeof(tid_to_dscp[0]))) {
5285 sigma_dut_print(dut, DUT_MSG_ERROR, "Unsupported TID: %d", tid);
5286 return;
5287 }
5288
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005289 /*
5290 * Two ways to ensure that addba request with a
5291 * non zero TID could be sent out. EV 117296
5292 */
5293 snprintf(buf, sizeof(buf),
5294 "ping -c 8 -Q %d `arp -a | grep wlan0 | awk '{print $2}' | tr -d '()'`",
5295 tid);
5296 if (system(buf) != 0) {
5297 sigma_dut_print(dut, DUT_MSG_ERROR,
5298 "Ping did not send out");
5299 }
5300
5301 snprintf(buf, sizeof(buf),
5302 "iwconfig %s | grep Access | awk '{print $6}' > %s",
5303 intf, VI_QOS_TMP_FILE);
5304 if (system(buf) != 0)
5305 return;
5306
5307 snprintf(buf, sizeof(buf),
5308 "ifconfig %s | grep HWaddr | cut -b 39-56 >> %s",
5309 intf, VI_QOS_TMP_FILE);
5310 if (system(buf) != 0)
5311 sigma_dut_print(dut, DUT_MSG_ERROR, "HWaddr matching failed");
5312
5313 snprintf(buf,sizeof(buf), "sed -n '3,$p' %s >> %s",
5314 VI_QOS_REFFILE, VI_QOS_TMP_FILE);
5315 if (system(buf) != 0) {
5316 sigma_dut_print(dut, DUT_MSG_ERROR,
5317 "VI_QOS_TEMP_FILE generation error failed");
5318 }
5319 snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
5320 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
5321 if (system(buf) != 0) {
5322 sigma_dut_print(dut, DUT_MSG_ERROR,
5323 "VI_QOS_FILE generation failed");
5324 }
5325
5326 snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
5327 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
5328 if (system(buf) != 0) {
5329 sigma_dut_print(dut, DUT_MSG_ERROR,
5330 "VI_QOS_FILE generation failed");
5331 }
5332
5333 snprintf(buf, sizeof(buf), "ethinject %s %s", intf, VI_QOS_FILE);
5334 if (system(buf) != 0) {
5335 }
5336}
5337
5338
5339static int ath_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
5340 struct sigma_cmd *cmd)
5341{
5342 const char *intf = get_param(cmd, "Interface");
5343 const char *val;
5344 int tid = 0;
5345 char buf[100];
5346
5347 val = get_param(cmd, "TID");
5348 if (val) {
5349 tid = atoi(val);
5350 if (tid)
5351 ath_sta_inject_frame(dut, intf, tid);
5352 }
5353
5354 /* Command sequence for ADDBA request on Peregrine based devices */
5355 snprintf(buf, sizeof(buf), "iwpriv %s setaddbaoper 1", intf);
5356 if (system(buf) != 0) {
5357 sigma_dut_print(dut, DUT_MSG_ERROR,
5358 "iwpriv setaddbaoper failed");
5359 }
5360
5361 snprintf(buf, sizeof(buf), "wifitool %s senddelba 1 %d 1 4", intf, tid);
5362 if (system(buf) != 0) {
5363 sigma_dut_print(dut, DUT_MSG_ERROR,
5364 "wifitool senddelba failed");
5365 }
5366
5367 snprintf(buf, sizeof(buf), "wifitool %s sendaddba 1 %d 64", intf, tid);
5368 if (system(buf) != 0) {
5369 sigma_dut_print(dut, DUT_MSG_ERROR,
5370 "wifitool sendaddba failed");
5371 }
5372
5373 /* UNSUPPORTED: val = get_param(cmd, "Dest_mac"); */
5374
5375 return 1;
5376}
5377
5378
Lior David9981b512017-01-20 13:16:40 +02005379#ifdef __linux__
5380
5381static int wil6210_send_addba(struct sigma_dut *dut, const char *dest_mac,
5382 int agg_size)
5383{
5384 char dir[128], buf[128];
5385 FILE *f;
5386 regex_t re;
5387 regmatch_t m[2];
5388 int rc, ret = -1, vring_id, found;
5389
5390 if (wil6210_get_debugfs_dir(dut, dir, sizeof(dir))) {
5391 sigma_dut_print(dut, DUT_MSG_ERROR,
5392 "failed to get wil6210 debugfs dir");
5393 return -1;
5394 }
5395
5396 snprintf(buf, sizeof(buf), "%s/vrings", dir);
5397 f = fopen(buf, "r");
5398 if (!f) {
5399 sigma_dut_print(dut, DUT_MSG_ERROR, "failed to open: %s", buf);
5400 return -1;
5401 }
5402
5403 if (regcomp(&re, "VRING tx_[ \t]*([0-9]+)", REG_EXTENDED)) {
5404 sigma_dut_print(dut, DUT_MSG_ERROR, "regcomp failed");
5405 goto out;
5406 }
5407
5408 /* find TX VRING for the mac address */
5409 found = 0;
5410 while (fgets(buf, sizeof(buf), f)) {
5411 if (strcasestr(buf, dest_mac)) {
5412 found = 1;
5413 break;
5414 }
5415 }
5416
5417 if (!found) {
5418 sigma_dut_print(dut, DUT_MSG_ERROR,
5419 "no TX VRING for %s", dest_mac);
5420 goto out;
5421 }
5422
5423 /* extract VRING ID, "VRING tx_<id> = {" */
5424 if (!fgets(buf, sizeof(buf), f)) {
5425 sigma_dut_print(dut, DUT_MSG_ERROR,
5426 "no VRING start line for %s", dest_mac);
5427 goto out;
5428 }
5429
5430 rc = regexec(&re, buf, 2, m, 0);
5431 regfree(&re);
5432 if (rc || m[1].rm_so < 0) {
5433 sigma_dut_print(dut, DUT_MSG_ERROR,
5434 "no VRING TX ID for %s", dest_mac);
5435 goto out;
5436 }
5437 buf[m[1].rm_eo] = 0;
5438 vring_id = atoi(&buf[m[1].rm_so]);
5439
5440 /* send the addba command */
5441 fclose(f);
5442 snprintf(buf, sizeof(buf), "%s/back", dir);
5443 f = fopen(buf, "w");
5444 if (!f) {
5445 sigma_dut_print(dut, DUT_MSG_ERROR,
5446 "failed to open: %s", buf);
5447 return -1;
5448 }
5449
5450 fprintf(f, "add %d %d\n", vring_id, agg_size);
5451
5452 ret = 0;
5453
5454out:
5455 fclose(f);
5456
5457 return ret;
5458}
5459
5460
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005461static int send_addba_60g(struct sigma_dut *dut, struct sigma_conn *conn,
5462 struct sigma_cmd *cmd)
5463{
5464 const char *val;
5465 int tid = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005466
5467 val = get_param(cmd, "TID");
5468 if (val) {
5469 tid = atoi(val);
5470 if (tid != 0) {
5471 sigma_dut_print(dut, DUT_MSG_ERROR,
5472 "Ignore TID %d for send_addba use TID 0 for 60g since only 0 required on TX",
5473 tid);
5474 }
5475 }
5476
5477 val = get_param(cmd, "Dest_mac");
5478 if (!val) {
5479 sigma_dut_print(dut, DUT_MSG_ERROR,
5480 "Currently not supporting addba for 60G without Dest_mac");
5481 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
5482 }
5483
Lior David9981b512017-01-20 13:16:40 +02005484 if (wil6210_send_addba(dut, val, dut->back_rcv_buf))
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005485 return -1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005486
5487 return 1;
5488}
5489
Lior David9981b512017-01-20 13:16:40 +02005490#endif /* __linux__ */
5491
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005492
5493static int cmd_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
5494 struct sigma_cmd *cmd)
5495{
5496 switch (get_driver_type()) {
5497 case DRIVER_ATHEROS:
5498 return ath_sta_send_addba(dut, conn, cmd);
Lior David9981b512017-01-20 13:16:40 +02005499#ifdef __linux__
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005500 case DRIVER_WIL6210:
5501 return send_addba_60g(dut, conn, cmd);
Lior David9981b512017-01-20 13:16:40 +02005502#endif /* __linux__ */
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005503 default:
5504 /*
5505 * There is no driver specific implementation for other drivers.
5506 * Ignore the command and report COMPLETE since the following
5507 * throughput test operation will end up sending ADDBA anyway.
5508 */
5509 return 1;
5510 }
5511}
5512
5513
5514int inject_eth_frame(int s, const void *data, size_t len,
5515 unsigned short ethtype, char *dst, char *src)
5516{
5517 struct iovec iov[4] = {
5518 {
5519 .iov_base = dst,
5520 .iov_len = ETH_ALEN,
5521 },
5522 {
5523 .iov_base = src,
5524 .iov_len = ETH_ALEN,
5525 },
5526 {
5527 .iov_base = &ethtype,
5528 .iov_len = sizeof(unsigned short),
5529 },
5530 {
5531 .iov_base = (void *) data,
5532 .iov_len = len,
5533 }
5534 };
5535 struct msghdr msg = {
5536 .msg_name = NULL,
5537 .msg_namelen = 0,
5538 .msg_iov = iov,
5539 .msg_iovlen = 4,
5540 .msg_control = NULL,
5541 .msg_controllen = 0,
5542 .msg_flags = 0,
5543 };
5544
5545 return sendmsg(s, &msg, 0);
5546}
5547
5548#if defined(__linux__) || defined(__QNXNTO__)
5549
5550int inject_frame(int s, const void *data, size_t len, int encrypt)
5551{
5552#define IEEE80211_RADIOTAP_F_WEP 0x04
5553#define IEEE80211_RADIOTAP_F_FRAG 0x08
5554 unsigned char rtap_hdr[] = {
5555 0x00, 0x00, /* radiotap version */
5556 0x0e, 0x00, /* radiotap length */
5557 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
5558 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
5559 0x00, /* padding */
5560 0x00, 0x00, /* RX and TX flags to indicate that */
5561 0x00, 0x00, /* this is the injected frame directly */
5562 };
5563 struct iovec iov[2] = {
5564 {
5565 .iov_base = &rtap_hdr,
5566 .iov_len = sizeof(rtap_hdr),
5567 },
5568 {
5569 .iov_base = (void *) data,
5570 .iov_len = len,
5571 }
5572 };
5573 struct msghdr msg = {
5574 .msg_name = NULL,
5575 .msg_namelen = 0,
5576 .msg_iov = iov,
5577 .msg_iovlen = 2,
5578 .msg_control = NULL,
5579 .msg_controllen = 0,
5580 .msg_flags = 0,
5581 };
5582
5583 if (encrypt)
5584 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
5585
5586 return sendmsg(s, &msg, 0);
5587}
5588
5589
5590int open_monitor(const char *ifname)
5591{
5592#ifdef __QNXNTO__
5593 struct sockaddr_dl ll;
5594 int s;
5595
5596 memset(&ll, 0, sizeof(ll));
5597 ll.sdl_family = AF_LINK;
5598 ll.sdl_index = if_nametoindex(ifname);
5599 if (ll.sdl_index == 0) {
5600 perror("if_nametoindex");
5601 return -1;
5602 }
5603 s = socket(PF_INET, SOCK_RAW, 0);
5604#else /* __QNXNTO__ */
5605 struct sockaddr_ll ll;
5606 int s;
5607
5608 memset(&ll, 0, sizeof(ll));
5609 ll.sll_family = AF_PACKET;
5610 ll.sll_ifindex = if_nametoindex(ifname);
5611 if (ll.sll_ifindex == 0) {
5612 perror("if_nametoindex");
5613 return -1;
5614 }
5615 s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
5616#endif /* __QNXNTO__ */
5617 if (s < 0) {
5618 perror("socket[PF_PACKET,SOCK_RAW]");
5619 return -1;
5620 }
5621
5622 if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
5623 perror("monitor socket bind");
5624 close(s);
5625 return -1;
5626 }
5627
5628 return s;
5629}
5630
5631
5632static int hex2num(char c)
5633{
5634 if (c >= '0' && c <= '9')
5635 return c - '0';
5636 if (c >= 'a' && c <= 'f')
5637 return c - 'a' + 10;
5638 if (c >= 'A' && c <= 'F')
5639 return c - 'A' + 10;
5640 return -1;
5641}
5642
5643
5644int hwaddr_aton(const char *txt, unsigned char *addr)
5645{
5646 int i;
5647
5648 for (i = 0; i < 6; i++) {
5649 int a, b;
5650
5651 a = hex2num(*txt++);
5652 if (a < 0)
5653 return -1;
5654 b = hex2num(*txt++);
5655 if (b < 0)
5656 return -1;
5657 *addr++ = (a << 4) | b;
5658 if (i < 5 && *txt++ != ':')
5659 return -1;
5660 }
5661
5662 return 0;
5663}
5664
5665#endif /* defined(__linux__) || defined(__QNXNTO__) */
5666
5667enum send_frame_type {
5668 DISASSOC, DEAUTH, SAQUERY, AUTH, ASSOCREQ, REASSOCREQ, DLS_REQ
5669};
5670enum send_frame_protection {
5671 CORRECT_KEY, INCORRECT_KEY, UNPROTECTED
5672};
5673
5674
5675static int sta_inject_frame(struct sigma_dut *dut, struct sigma_conn *conn,
5676 enum send_frame_type frame,
5677 enum send_frame_protection protected,
5678 const char *dest)
5679{
5680#ifdef __linux__
5681 unsigned char buf[1000], *pos;
5682 int s, res;
5683 char bssid[20], addr[20];
5684 char result[32], ssid[100];
5685 size_t ssid_len;
5686
5687 if (get_wpa_status(get_station_ifname(), "wpa_state", result,
5688 sizeof(result)) < 0 ||
5689 strncmp(result, "COMPLETED", 9) != 0) {
5690 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Not connected");
5691 return 0;
5692 }
5693
5694 if (get_wpa_status(get_station_ifname(), "bssid", bssid, sizeof(bssid))
5695 < 0) {
5696 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
5697 "current BSSID");
5698 return 0;
5699 }
5700
5701 if (get_wpa_status(get_station_ifname(), "address", addr, sizeof(addr))
5702 < 0) {
5703 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
5704 "own MAC address");
5705 return 0;
5706 }
5707
5708 if (get_wpa_status(get_station_ifname(), "ssid", ssid, sizeof(ssid))
5709 < 0) {
5710 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
5711 "current SSID");
5712 return 0;
5713 }
5714 ssid_len = strlen(ssid);
5715
5716 pos = buf;
5717
5718 /* Frame Control */
5719 switch (frame) {
5720 case DISASSOC:
5721 *pos++ = 0xa0;
5722 break;
5723 case DEAUTH:
5724 *pos++ = 0xc0;
5725 break;
5726 case SAQUERY:
5727 *pos++ = 0xd0;
5728 break;
5729 case AUTH:
5730 *pos++ = 0xb0;
5731 break;
5732 case ASSOCREQ:
5733 *pos++ = 0x00;
5734 break;
5735 case REASSOCREQ:
5736 *pos++ = 0x20;
5737 break;
5738 case DLS_REQ:
5739 *pos++ = 0xd0;
5740 break;
5741 }
5742
5743 if (protected == INCORRECT_KEY)
5744 *pos++ = 0x40; /* Set Protected field to 1 */
5745 else
5746 *pos++ = 0x00;
5747
5748 /* Duration */
5749 *pos++ = 0x00;
5750 *pos++ = 0x00;
5751
5752 /* addr1 = DA (current AP) */
5753 hwaddr_aton(bssid, pos);
5754 pos += 6;
5755 /* addr2 = SA (own address) */
5756 hwaddr_aton(addr, pos);
5757 pos += 6;
5758 /* addr3 = BSSID (current AP) */
5759 hwaddr_aton(bssid, pos);
5760 pos += 6;
5761
5762 /* Seq# (to be filled by driver/mac80211) */
5763 *pos++ = 0x00;
5764 *pos++ = 0x00;
5765
5766 if (protected == INCORRECT_KEY) {
5767 /* CCMP parameters */
5768 memcpy(pos, "\x61\x01\x00\x20\x00\x10\x00\x00", 8);
5769 pos += 8;
5770 }
5771
5772 if (protected == INCORRECT_KEY) {
5773 switch (frame) {
5774 case DEAUTH:
5775 /* Reason code (encrypted) */
5776 memcpy(pos, "\xa7\x39", 2);
5777 pos += 2;
5778 break;
5779 case DISASSOC:
5780 /* Reason code (encrypted) */
5781 memcpy(pos, "\xa7\x39", 2);
5782 pos += 2;
5783 break;
5784 case SAQUERY:
5785 /* Category|Action|TransID (encrypted) */
5786 memcpy(pos, "\x6f\xbd\xe9\x4d", 4);
5787 pos += 4;
5788 break;
5789 default:
5790 return -1;
5791 }
5792
5793 /* CCMP MIC */
5794 memcpy(pos, "\xc8\xd8\x3b\x06\x5d\xb7\x25\x68", 8);
5795 pos += 8;
5796 } else {
5797 switch (frame) {
5798 case DEAUTH:
5799 /* reason code = 8 */
5800 *pos++ = 0x08;
5801 *pos++ = 0x00;
5802 break;
5803 case DISASSOC:
5804 /* reason code = 8 */
5805 *pos++ = 0x08;
5806 *pos++ = 0x00;
5807 break;
5808 case SAQUERY:
5809 /* Category - SA Query */
5810 *pos++ = 0x08;
5811 /* SA query Action - Request */
5812 *pos++ = 0x00;
5813 /* Transaction ID */
5814 *pos++ = 0x12;
5815 *pos++ = 0x34;
5816 break;
5817 case AUTH:
5818 /* Auth Alg (Open) */
5819 *pos++ = 0x00;
5820 *pos++ = 0x00;
5821 /* Seq# */
5822 *pos++ = 0x01;
5823 *pos++ = 0x00;
5824 /* Status code */
5825 *pos++ = 0x00;
5826 *pos++ = 0x00;
5827 break;
5828 case ASSOCREQ:
5829 /* Capability Information */
5830 *pos++ = 0x31;
5831 *pos++ = 0x04;
5832 /* Listen Interval */
5833 *pos++ = 0x0a;
5834 *pos++ = 0x00;
5835 /* SSID */
5836 *pos++ = 0x00;
5837 *pos++ = ssid_len;
5838 memcpy(pos, ssid, ssid_len);
5839 pos += ssid_len;
5840 /* Supported Rates */
5841 memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
5842 10);
5843 pos += 10;
5844 /* Extended Supported Rates */
5845 memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
5846 pos += 6;
5847 /* RSN */
5848 memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
5849 "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
5850 "\x00\x00\x00\x00\x0f\xac\x06", 28);
5851 pos += 28;
5852 break;
5853 case REASSOCREQ:
5854 /* Capability Information */
5855 *pos++ = 0x31;
5856 *pos++ = 0x04;
5857 /* Listen Interval */
5858 *pos++ = 0x0a;
5859 *pos++ = 0x00;
5860 /* Current AP */
5861 hwaddr_aton(bssid, pos);
5862 pos += 6;
5863 /* SSID */
5864 *pos++ = 0x00;
5865 *pos++ = ssid_len;
5866 memcpy(pos, ssid, ssid_len);
5867 pos += ssid_len;
5868 /* Supported Rates */
5869 memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
5870 10);
5871 pos += 10;
5872 /* Extended Supported Rates */
5873 memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
5874 pos += 6;
5875 /* RSN */
5876 memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
5877 "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
5878 "\x00\x00\x00\x00\x0f\xac\x06", 28);
5879 pos += 28;
5880 break;
5881 case DLS_REQ:
5882 /* Category - DLS */
5883 *pos++ = 0x02;
5884 /* DLS Action - Request */
5885 *pos++ = 0x00;
5886 /* Destination MACAddress */
5887 if (dest)
5888 hwaddr_aton(dest, pos);
5889 else
5890 memset(pos, 0, 6);
5891 pos += 6;
5892 /* Source MACAddress */
5893 hwaddr_aton(addr, pos);
5894 pos += 6;
5895 /* Capability Information */
5896 *pos++ = 0x10; /* Privacy */
5897 *pos++ = 0x06; /* QoS */
5898 /* DLS Timeout Value */
5899 *pos++ = 0x00;
5900 *pos++ = 0x01;
5901 /* Supported rates */
5902 *pos++ = 0x01;
5903 *pos++ = 0x08;
5904 *pos++ = 0x0c; /* 6 Mbps */
5905 *pos++ = 0x12; /* 9 Mbps */
5906 *pos++ = 0x18; /* 12 Mbps */
5907 *pos++ = 0x24; /* 18 Mbps */
5908 *pos++ = 0x30; /* 24 Mbps */
5909 *pos++ = 0x48; /* 36 Mbps */
5910 *pos++ = 0x60; /* 48 Mbps */
5911 *pos++ = 0x6c; /* 54 Mbps */
5912 /* TODO: Extended Supported Rates */
5913 /* TODO: HT Capabilities */
5914 break;
5915 }
5916 }
5917
5918 s = open_monitor("sigmadut");
5919 if (s < 0) {
5920 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
5921 "monitor socket");
5922 return 0;
5923 }
5924
5925 res = inject_frame(s, buf, pos - buf, protected == CORRECT_KEY);
5926 if (res < 0) {
5927 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
5928 "inject frame");
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05305929 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005930 return 0;
5931 }
5932 if (res < pos - buf) {
5933 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Only partial "
5934 "frame sent");
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05305935 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005936 return 0;
5937 }
5938
5939 close(s);
5940
5941 return 1;
5942#else /* __linux__ */
5943 send_resp(dut, conn, SIGMA_ERROR, "errorCode,sta_send_frame not "
5944 "yet supported");
5945 return 0;
5946#endif /* __linux__ */
5947}
5948
5949
5950static int cmd_sta_send_frame_tdls(struct sigma_dut *dut,
5951 struct sigma_conn *conn,
5952 struct sigma_cmd *cmd)
5953{
5954 const char *intf = get_param(cmd, "Interface");
5955 const char *sta, *val;
5956 unsigned char addr[ETH_ALEN];
5957 char buf[100];
5958
5959 sta = get_param(cmd, "peer");
5960 if (sta == NULL)
5961 sta = get_param(cmd, "station");
5962 if (sta == NULL) {
5963 send_resp(dut, conn, SIGMA_ERROR,
5964 "ErrorCode,Missing peer address");
5965 return 0;
5966 }
5967 if (hwaddr_aton(sta, addr) < 0) {
5968 send_resp(dut, conn, SIGMA_ERROR,
5969 "ErrorCode,Invalid peer address");
5970 return 0;
5971 }
5972
5973 val = get_param(cmd, "type");
5974 if (val == NULL)
5975 return -1;
5976
5977 if (strcasecmp(val, "DISCOVERY") == 0) {
5978 snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", sta);
5979 if (wpa_command(intf, buf) < 0) {
5980 send_resp(dut, conn, SIGMA_ERROR,
5981 "ErrorCode,Failed to send TDLS discovery");
5982 return 0;
5983 }
5984 return 1;
5985 }
5986
5987 if (strcasecmp(val, "SETUP") == 0) {
5988 int status = 0, timeout = 0;
5989
5990 val = get_param(cmd, "Status");
5991 if (val)
5992 status = atoi(val);
5993
5994 val = get_param(cmd, "Timeout");
5995 if (val)
5996 timeout = atoi(val);
5997
5998 if (status != 0 && status != 37) {
5999 send_resp(dut, conn, SIGMA_ERROR,
6000 "ErrorCode,Unsupported status value");
6001 return 0;
6002 }
6003
6004 if (timeout != 0 && timeout != 301) {
6005 send_resp(dut, conn, SIGMA_ERROR,
6006 "ErrorCode,Unsupported timeout value");
6007 return 0;
6008 }
6009
6010 if (status && timeout) {
6011 send_resp(dut, conn, SIGMA_ERROR,
6012 "ErrorCode,Unsupported timeout+status "
6013 "combination");
6014 return 0;
6015 }
6016
6017 if (status == 37 &&
6018 wpa_command(intf, "SET tdls_testing 0x200")) {
6019 send_resp(dut, conn, SIGMA_ERROR,
6020 "ErrorCode,Failed to enable "
6021 "decline setup response test mode");
6022 return 0;
6023 }
6024
6025 if (timeout == 301) {
6026 int res;
6027 if (dut->no_tpk_expiration)
6028 res = wpa_command(intf,
6029 "SET tdls_testing 0x108");
6030 else
6031 res = wpa_command(intf,
6032 "SET tdls_testing 0x8");
6033 if (res) {
6034 send_resp(dut, conn, SIGMA_ERROR,
6035 "ErrorCode,Failed to set short TPK "
6036 "lifetime");
6037 return 0;
6038 }
6039 }
6040
6041 snprintf(buf, sizeof(buf), "TDLS_SETUP %s", sta);
6042 if (wpa_command(intf, buf) < 0) {
6043 send_resp(dut, conn, SIGMA_ERROR,
6044 "ErrorCode,Failed to send TDLS setup");
6045 return 0;
6046 }
6047 return 1;
6048 }
6049
6050 if (strcasecmp(val, "TEARDOWN") == 0) {
6051 snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", sta);
6052 if (wpa_command(intf, buf) < 0) {
6053 send_resp(dut, conn, SIGMA_ERROR,
6054 "ErrorCode,Failed to send TDLS teardown");
6055 return 0;
6056 }
6057 return 1;
6058 }
6059
6060 send_resp(dut, conn, SIGMA_ERROR,
6061 "ErrorCode,Unsupported TDLS frame");
6062 return 0;
6063}
6064
6065
6066static int sta_ap_known(const char *ifname, const char *bssid)
6067{
6068 char buf[4096];
6069
6070 snprintf(buf, sizeof(buf), "BSS %s", bssid);
6071 if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
6072 return 0;
6073 if (strncmp(buf, "id=", 3) != 0)
6074 return 0;
6075 return 1;
6076}
6077
6078
6079static int sta_scan_ap(struct sigma_dut *dut, const char *ifname,
6080 const char *bssid)
6081{
6082 int res;
6083 struct wpa_ctrl *ctrl;
6084 char buf[256];
6085
6086 if (sta_ap_known(ifname, bssid))
6087 return 0;
6088 sigma_dut_print(dut, DUT_MSG_DEBUG,
6089 "AP not in BSS table - start scan");
6090
6091 ctrl = open_wpa_mon(ifname);
6092 if (ctrl == NULL) {
6093 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
6094 "wpa_supplicant monitor connection");
6095 return -1;
6096 }
6097
6098 if (wpa_command(ifname, "SCAN") < 0) {
6099 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to start scan");
6100 wpa_ctrl_detach(ctrl);
6101 wpa_ctrl_close(ctrl);
6102 return -1;
6103 }
6104
6105 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
6106 buf, sizeof(buf));
6107
6108 wpa_ctrl_detach(ctrl);
6109 wpa_ctrl_close(ctrl);
6110
6111 if (res < 0) {
6112 sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
6113 return -1;
6114 }
6115
6116 if (sta_ap_known(ifname, bssid))
6117 return 0;
6118 sigma_dut_print(dut, DUT_MSG_INFO, "AP not in BSS table");
6119 return -1;
6120}
6121
6122
6123static int cmd_sta_send_frame_hs2_neighadv(struct sigma_dut *dut,
6124 struct sigma_conn *conn,
6125 struct sigma_cmd *cmd,
6126 const char *intf)
6127{
6128 char buf[200];
6129
6130 snprintf(buf, sizeof(buf), "ndsend 2001:DB8::1 %s", intf);
6131 if (system(buf) != 0) {
6132 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to run "
6133 "ndsend");
6134 return 0;
6135 }
6136
6137 return 1;
6138}
6139
6140
6141static int cmd_sta_send_frame_hs2_neighsolreq(struct sigma_dut *dut,
6142 struct sigma_conn *conn,
6143 struct sigma_cmd *cmd,
6144 const char *intf)
6145{
6146 char buf[200];
6147 const char *ip = get_param(cmd, "SenderIP");
6148
6149 snprintf(buf, sizeof(buf), "ndisc6 -nm %s %s -r 4", ip, intf);
6150 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6151 if (system(buf) == 0) {
6152 sigma_dut_print(dut, DUT_MSG_INFO,
6153 "Neighbor Solicitation got a response "
6154 "for %s@%s", ip, intf);
6155 }
6156
6157 return 1;
6158}
6159
6160
6161static int cmd_sta_send_frame_hs2_arpprobe(struct sigma_dut *dut,
6162 struct sigma_conn *conn,
6163 struct sigma_cmd *cmd,
6164 const char *ifname)
6165{
6166 char buf[200];
6167 const char *ip = get_param(cmd, "SenderIP");
6168
6169 if (ip == NULL) {
6170 send_resp(dut, conn, SIGMA_ERROR,
6171 "ErrorCode,Missing SenderIP parameter");
6172 return 0;
6173 }
6174 snprintf(buf, sizeof(buf), "arping -I %s -D %s -c 4", ifname, ip);
6175 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6176 if (system(buf) != 0) {
6177 sigma_dut_print(dut, DUT_MSG_INFO, "arping DAD got a response "
6178 "for %s@%s", ip, ifname);
6179 }
6180
6181 return 1;
6182}
6183
6184
6185static int cmd_sta_send_frame_hs2_arpannounce(struct sigma_dut *dut,
6186 struct sigma_conn *conn,
6187 struct sigma_cmd *cmd,
6188 const char *ifname)
6189{
6190 char buf[200];
6191 char ip[16];
6192 int s;
6193
6194 s = socket(PF_INET, SOCK_DGRAM, 0);
6195 if (s >= 0) {
6196 struct ifreq ifr;
6197 struct sockaddr_in saddr;
6198
6199 memset(&ifr, 0, sizeof(ifr));
Peng Xub8fc5cc2017-05-10 17:27:28 -07006200 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006201 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
6202 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
6203 "%s IP address: %s",
6204 ifname, strerror(errno));
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05306205 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006206 return -1;
6207 } else {
6208 memcpy(&saddr, &ifr.ifr_addr,
6209 sizeof(struct sockaddr_in));
Peng Xub8fc5cc2017-05-10 17:27:28 -07006210 strlcpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006211 }
6212 close(s);
6213
6214 }
6215
6216 snprintf(buf, sizeof(buf), "arping -I %s -s %s %s -c 4", ifname, ip,
6217 ip);
6218 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6219 if (system(buf) != 0) {
6220 }
6221
6222 return 1;
6223}
6224
6225
6226static int cmd_sta_send_frame_hs2_arpreply(struct sigma_dut *dut,
6227 struct sigma_conn *conn,
6228 struct sigma_cmd *cmd,
6229 const char *ifname)
6230{
6231 char buf[200], addr[20];
6232 char dst[ETH_ALEN], src[ETH_ALEN];
6233 short ethtype = htons(ETH_P_ARP);
6234 char *pos;
6235 int s, res;
6236 const char *val;
6237 struct sockaddr_in taddr;
6238
6239 val = get_param(cmd, "dest");
6240 if (val)
6241 hwaddr_aton(val, (unsigned char *) dst);
6242
6243 val = get_param(cmd, "DestIP");
6244 if (val)
6245 inet_aton(val, &taddr.sin_addr);
6246
6247 if (get_wpa_status(get_station_ifname(), "address", addr,
6248 sizeof(addr)) < 0)
6249 return -2;
6250 hwaddr_aton(addr, (unsigned char *) src);
6251
6252 pos = buf;
6253 *pos++ = 0x00;
6254 *pos++ = 0x01;
6255 *pos++ = 0x08;
6256 *pos++ = 0x00;
6257 *pos++ = 0x06;
6258 *pos++ = 0x04;
6259 *pos++ = 0x00;
6260 *pos++ = 0x02;
6261 memcpy(pos, src, ETH_ALEN);
6262 pos += ETH_ALEN;
6263 memcpy(pos, &taddr.sin_addr, 4);
6264 pos += 4;
6265 memcpy(pos, dst, ETH_ALEN);
6266 pos += ETH_ALEN;
6267 memcpy(pos, &taddr.sin_addr, 4);
6268 pos += 4;
6269
6270 s = open_monitor(get_station_ifname());
6271 if (s < 0) {
6272 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
6273 "monitor socket");
6274 return 0;
6275 }
6276
6277 res = inject_eth_frame(s, buf, pos - buf, ethtype, dst, src);
6278 if (res < 0) {
6279 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
6280 "inject frame");
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05306281 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006282 return 0;
6283 }
6284
6285 close(s);
6286
6287 return 1;
6288}
6289
6290
6291static int cmd_sta_send_frame_hs2_dls_req(struct sigma_dut *dut,
6292 struct sigma_conn *conn,
6293 struct sigma_cmd *cmd,
6294 const char *intf, const char *dest)
6295{
6296 char buf[100];
6297
6298 if (if_nametoindex("sigmadut") == 0) {
6299 snprintf(buf, sizeof(buf),
6300 "iw dev %s interface add sigmadut type monitor",
6301 get_station_ifname());
6302 if (system(buf) != 0 ||
6303 if_nametoindex("sigmadut") == 0) {
6304 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
6305 "monitor interface with '%s'", buf);
6306 return -2;
6307 }
6308 }
6309
6310 if (system("ifconfig sigmadut up") != 0) {
6311 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
6312 "monitor interface up");
6313 return -2;
6314 }
6315
6316 return sta_inject_frame(dut, conn, DLS_REQ, UNPROTECTED, dest);
6317}
6318
6319
6320static int cmd_sta_send_frame_hs2(struct sigma_dut *dut,
6321 struct sigma_conn *conn,
6322 struct sigma_cmd *cmd)
6323{
6324 const char *intf = get_param(cmd, "Interface");
6325 const char *dest = get_param(cmd, "Dest");
6326 const char *type = get_param(cmd, "FrameName");
6327 const char *val;
6328 char buf[200], *pos, *end;
6329 int count, count2;
6330
6331 if (type == NULL)
6332 type = get_param(cmd, "Type");
6333
6334 if (intf == NULL || dest == NULL || type == NULL)
6335 return -1;
6336
6337 if (strcasecmp(type, "NeighAdv") == 0)
6338 return cmd_sta_send_frame_hs2_neighadv(dut, conn, cmd, intf);
6339
6340 if (strcasecmp(type, "NeighSolicitReq") == 0)
6341 return cmd_sta_send_frame_hs2_neighsolreq(dut, conn, cmd, intf);
6342
6343 if (strcasecmp(type, "ARPProbe") == 0)
6344 return cmd_sta_send_frame_hs2_arpprobe(dut, conn, cmd, intf);
6345
6346 if (strcasecmp(type, "ARPAnnounce") == 0)
6347 return cmd_sta_send_frame_hs2_arpannounce(dut, conn, cmd, intf);
6348
6349 if (strcasecmp(type, "ARPReply") == 0)
6350 return cmd_sta_send_frame_hs2_arpreply(dut, conn, cmd, intf);
6351
6352 if (strcasecmp(type, "DLS-request") == 0 ||
6353 strcasecmp(type, "DLSrequest") == 0)
6354 return cmd_sta_send_frame_hs2_dls_req(dut, conn, cmd, intf,
6355 dest);
6356
6357 if (strcasecmp(type, "ANQPQuery") != 0 &&
6358 strcasecmp(type, "Query") != 0) {
6359 send_resp(dut, conn, SIGMA_ERROR,
6360 "ErrorCode,Unsupported HS 2.0 send frame type");
6361 return 0;
6362 }
6363
6364 if (sta_scan_ap(dut, intf, dest) < 0) {
6365 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find "
6366 "the requested AP");
6367 return 0;
6368 }
6369
6370 pos = buf;
6371 end = buf + sizeof(buf);
6372 count = 0;
6373 pos += snprintf(pos, end - pos, "ANQP_GET %s ", dest);
6374
6375 val = get_param(cmd, "ANQP_CAP_LIST");
6376 if (val && atoi(val)) {
6377 pos += snprintf(pos, end - pos, "%s257", count > 0 ? "," : "");
6378 count++;
6379 }
6380
6381 val = get_param(cmd, "VENUE_NAME");
6382 if (val && atoi(val)) {
6383 pos += snprintf(pos, end - pos, "%s258", count > 0 ? "," : "");
6384 count++;
6385 }
6386
6387 val = get_param(cmd, "NETWORK_AUTH_TYPE");
6388 if (val && atoi(val)) {
6389 pos += snprintf(pos, end - pos, "%s260", count > 0 ? "," : "");
6390 count++;
6391 }
6392
6393 val = get_param(cmd, "ROAMING_CONS");
6394 if (val && atoi(val)) {
6395 pos += snprintf(pos, end - pos, "%s261", count > 0 ? "," : "");
6396 count++;
6397 }
6398
6399 val = get_param(cmd, "IP_ADDR_TYPE_AVAILABILITY");
6400 if (val && atoi(val)) {
6401 pos += snprintf(pos, end - pos, "%s262", count > 0 ? "," : "");
6402 count++;
6403 }
6404
6405 val = get_param(cmd, "NAI_REALM_LIST");
6406 if (val && atoi(val)) {
6407 pos += snprintf(pos, end - pos, "%s263", count > 0 ? "," : "");
6408 count++;
6409 }
6410
6411 val = get_param(cmd, "3GPP_INFO");
6412 if (val && atoi(val)) {
6413 pos += snprintf(pos, end - pos, "%s264", count > 0 ? "," : "");
6414 count++;
6415 }
6416
6417 val = get_param(cmd, "DOMAIN_LIST");
6418 if (val && atoi(val)) {
6419 pos += snprintf(pos, end - pos, "%s268", count > 0 ? "," : "");
6420 count++;
6421 }
6422
6423 if (count && wpa_command(intf, buf)) {
6424 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,ANQP_GET failed");
6425 return 0;
6426 }
6427
6428 pos = buf;
6429 end = buf + sizeof(buf);
6430 count2 = 0;
6431 pos += snprintf(pos, end - pos, "HS20_ANQP_GET %s ", dest);
6432
6433 val = get_param(cmd, "HS_CAP_LIST");
6434 if (val && atoi(val)) {
6435 pos += snprintf(pos, end - pos, "%s2", count2 > 0 ? "," : "");
6436 count2++;
6437 }
6438
6439 val = get_param(cmd, "OPER_NAME");
6440 if (val && atoi(val)) {
6441 pos += snprintf(pos, end - pos, "%s3", count2 > 0 ? "," : "");
6442 count2++;
6443 }
6444
6445 val = get_param(cmd, "WAN_METRICS");
6446 if (!val)
6447 val = get_param(cmd, "WAN_MAT");
6448 if (!val)
6449 val = get_param(cmd, "WAN_MET");
6450 if (val && atoi(val)) {
6451 pos += snprintf(pos, end - pos, "%s4", count2 > 0 ? "," : "");
6452 count2++;
6453 }
6454
6455 val = get_param(cmd, "CONNECTION_CAPABILITY");
6456 if (val && atoi(val)) {
6457 pos += snprintf(pos, end - pos, "%s5", count2 > 0 ? "," : "");
6458 count2++;
6459 }
6460
6461 val = get_param(cmd, "OP_CLASS");
6462 if (val && atoi(val)) {
6463 pos += snprintf(pos, end - pos, "%s7", count2 > 0 ? "," : "");
6464 count2++;
6465 }
6466
6467 val = get_param(cmd, "OSU_PROVIDER_LIST");
6468 if (val && atoi(val)) {
6469 pos += snprintf(pos, end - pos, "%s8", count2 > 0 ? "," : "");
6470 count2++;
6471 }
6472
6473 if (count && count2) {
6474 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before sending out "
6475 "second query");
6476 sleep(1);
6477 }
6478
6479 if (count2 && wpa_command(intf, buf)) {
6480 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,HS20_ANQP_GET "
6481 "failed");
6482 return 0;
6483 }
6484
6485 val = get_param(cmd, "NAI_HOME_REALM_LIST");
6486 if (val) {
6487 if (count || count2) {
6488 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
6489 "sending out second query");
6490 sleep(1);
6491 }
6492
6493 if (strcmp(val, "1") == 0)
6494 val = "mail.example.com";
6495 snprintf(buf, end - pos,
6496 "HS20_GET_NAI_HOME_REALM_LIST %s realm=%s",
6497 dest, val);
6498 if (wpa_command(intf, buf)) {
6499 send_resp(dut, conn, SIGMA_ERROR,
6500 "ErrorCode,HS20_GET_NAI_HOME_REALM_LIST "
6501 "failed");
6502 return 0;
6503 }
6504 }
6505
6506 val = get_param(cmd, "ICON_REQUEST");
6507 if (val) {
6508 if (count || count2) {
6509 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
6510 "sending out second query");
6511 sleep(1);
6512 }
6513
6514 snprintf(buf, end - pos,
6515 "HS20_ICON_REQUEST %s %s", dest, val);
6516 if (wpa_command(intf, buf)) {
6517 send_resp(dut, conn, SIGMA_ERROR,
6518 "ErrorCode,HS20_ICON_REQUEST failed");
6519 return 0;
6520 }
6521 }
6522
6523 return 1;
6524}
6525
6526
6527static int ath_sta_send_frame_vht(struct sigma_dut *dut,
6528 struct sigma_conn *conn,
6529 struct sigma_cmd *cmd)
6530{
6531 const char *val;
6532 char *ifname;
6533 char buf[100];
6534 int chwidth, nss;
6535
6536 val = get_param(cmd, "framename");
6537 if (!val)
6538 return -1;
6539 sigma_dut_print(dut, DUT_MSG_DEBUG, "framename is %s", val);
6540
6541 /* Command sequence to generate Op mode notification */
6542 if (val && strcasecmp(val, "Op_md_notif_frm") == 0) {
6543 ifname = get_station_ifname();
6544
6545 /* Disable STBC */
6546 snprintf(buf, sizeof(buf),
6547 "iwpriv %s tx_stbc 0", ifname);
6548 if (system(buf) != 0) {
6549 sigma_dut_print(dut, DUT_MSG_ERROR,
6550 "iwpriv tx_stbc 0 failed!");
6551 }
6552
6553 /* Extract Channel width */
6554 val = get_param(cmd, "Channel_width");
6555 if (val) {
6556 switch (atoi(val)) {
6557 case 20:
6558 chwidth = 0;
6559 break;
6560 case 40:
6561 chwidth = 1;
6562 break;
6563 case 80:
6564 chwidth = 2;
6565 break;
6566 case 160:
6567 chwidth = 3;
6568 break;
6569 default:
6570 chwidth = 2;
6571 break;
6572 }
6573
6574 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
6575 ifname, chwidth);
6576 if (system(buf) != 0) {
6577 sigma_dut_print(dut, DUT_MSG_ERROR,
6578 "iwpriv chwidth failed!");
6579 }
6580 }
6581
6582 /* Extract NSS */
6583 val = get_param(cmd, "NSS");
6584 if (val) {
6585 switch (atoi(val)) {
6586 case 1:
6587 nss = 1;
6588 break;
6589 case 2:
6590 nss = 3;
6591 break;
6592 case 3:
6593 nss = 7;
6594 break;
6595 default:
6596 /* We do not support NSS > 3 */
6597 nss = 3;
6598 break;
6599 }
6600 snprintf(buf, sizeof(buf),
6601 "iwpriv %s rxchainmask %d", ifname, nss);
6602 if (system(buf) != 0) {
6603 sigma_dut_print(dut, DUT_MSG_ERROR,
6604 "iwpriv rxchainmask failed!");
6605 }
6606 }
6607
6608 /* Opmode notify */
6609 snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", ifname);
6610 if (system(buf) != 0) {
6611 sigma_dut_print(dut, DUT_MSG_ERROR,
6612 "iwpriv opmode_notify failed!");
6613 } else {
6614 sigma_dut_print(dut, DUT_MSG_INFO,
6615 "Sent out the notify frame!");
6616 }
6617 }
6618
6619 return 1;
6620}
6621
6622
6623static int cmd_sta_send_frame_vht(struct sigma_dut *dut,
6624 struct sigma_conn *conn,
6625 struct sigma_cmd *cmd)
6626{
6627 switch (get_driver_type()) {
6628 case DRIVER_ATHEROS:
6629 return ath_sta_send_frame_vht(dut, conn, cmd);
6630 default:
6631 send_resp(dut, conn, SIGMA_ERROR,
6632 "errorCode,Unsupported sta_set_frame(VHT) with the current driver");
6633 return 0;
6634 }
6635}
6636
6637
Lior David0fe101e2017-03-09 16:09:50 +02006638#ifdef __linux__
6639int wil6210_send_frame_60g(struct sigma_dut *dut, struct sigma_conn *conn,
6640 struct sigma_cmd *cmd)
6641{
6642 const char *frame_name = get_param(cmd, "framename");
6643 const char *mac = get_param(cmd, "dest_mac");
6644
6645 if (!frame_name || !mac) {
6646 sigma_dut_print(dut, DUT_MSG_ERROR,
6647 "framename and dest_mac must be provided");
6648 return -1;
6649 }
6650
6651 if (strcasecmp(frame_name, "brp") == 0) {
6652 const char *l_rx = get_param(cmd, "L-RX");
6653 int l_rx_i;
6654
6655 if (!l_rx) {
6656 sigma_dut_print(dut, DUT_MSG_ERROR,
6657 "L-RX must be provided");
6658 return -1;
6659 }
6660 l_rx_i = atoi(l_rx);
6661
6662 sigma_dut_print(dut, DUT_MSG_INFO,
6663 "dev_send_frame: BRP-RX, dest_mac %s, L-RX %s",
6664 mac, l_rx);
6665 if (l_rx_i != 16) {
6666 sigma_dut_print(dut, DUT_MSG_ERROR,
6667 "unsupported L-RX: %s", l_rx);
6668 return -1;
6669 }
6670
6671 if (wil6210_send_brp_rx(dut, mac, l_rx_i))
6672 return -1;
6673 } else if (strcasecmp(frame_name, "ssw") == 0) {
6674 sigma_dut_print(dut, DUT_MSG_INFO,
6675 "dev_send_frame: SLS, dest_mac %s", mac);
6676 if (wil6210_send_sls(dut, mac))
6677 return -1;
6678 } else {
6679 sigma_dut_print(dut, DUT_MSG_ERROR,
6680 "unsupported frame type: %s", frame_name);
6681 return -1;
6682 }
6683
6684 return 1;
6685}
6686#endif /* __linux__ */
6687
6688
6689static int cmd_sta_send_frame_60g(struct sigma_dut *dut,
6690 struct sigma_conn *conn,
6691 struct sigma_cmd *cmd)
6692{
6693 switch (get_driver_type()) {
6694#ifdef __linux__
6695 case DRIVER_WIL6210:
6696 return wil6210_send_frame_60g(dut, conn, cmd);
6697#endif /* __linux__ */
6698 default:
6699 send_resp(dut, conn, SIGMA_ERROR,
6700 "errorCode,Unsupported sta_set_frame(60G) with the current driver");
6701 return 0;
6702 }
6703}
6704
6705
Ashwini Patildb59b3c2017-04-13 15:19:23 +05306706static int mbo_send_anqp_query(struct sigma_dut *dut, struct sigma_conn *conn,
6707 const char *intf, struct sigma_cmd *cmd)
6708{
6709 const char *val, *addr;
6710 char buf[100];
6711
6712 addr = get_param(cmd, "DestMac");
6713 if (!addr) {
6714 send_resp(dut, conn, SIGMA_INVALID,
6715 "ErrorCode,AP MAC address is missing");
6716 return 0;
6717 }
6718
6719 val = get_param(cmd, "ANQPQuery_ID");
6720 if (!val) {
6721 send_resp(dut, conn, SIGMA_INVALID,
6722 "ErrorCode,Missing ANQPQuery_ID");
6723 return 0;
6724 }
6725
6726 if (strcasecmp(val, "NeighborReportReq") == 0) {
6727 snprintf(buf, sizeof(buf), "ANQP_GET %s 272", addr);
6728 } else if (strcasecmp(val, "QueryListWithCellPref") == 0) {
6729 snprintf(buf, sizeof(buf), "ANQP_GET %s 272,mbo:2", addr);
6730 } else {
6731 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid ANQPQuery_ID: %s",
6732 val);
6733 send_resp(dut, conn, SIGMA_INVALID,
6734 "ErrorCode,Invalid ANQPQuery_ID");
6735 return 0;
6736 }
6737
Ashwini Patild174f2c2017-04-13 16:49:46 +05306738 /* Set gas_address3 field to IEEE 802.11-2012 standard compliant form
6739 * (Address3 = Wildcard BSSID when sent to not-associated AP;
6740 * if associated, AP BSSID).
6741 */
6742 if (wpa_command(intf, "SET gas_address3 1") < 0) {
6743 send_resp(dut, conn, SIGMA_ERROR,
6744 "ErrorCode,Failed to set gas_address3");
6745 return 0;
6746 }
6747
Ashwini Patildb59b3c2017-04-13 15:19:23 +05306748 if (wpa_command(intf, buf) < 0) {
6749 send_resp(dut, conn, SIGMA_ERROR,
6750 "ErrorCode,Failed to send ANQP query");
6751 return 0;
6752 }
6753
6754 return 1;
6755}
6756
6757
6758static int mbo_cmd_sta_send_frame(struct sigma_dut *dut,
6759 struct sigma_conn *conn,
6760 const char *intf,
6761 struct sigma_cmd *cmd)
6762{
6763 const char *val = get_param(cmd, "FrameName");
6764
6765 if (val && strcasecmp(val, "ANQPQuery") == 0)
6766 return mbo_send_anqp_query(dut, conn, intf, cmd);
6767
6768 return 2;
6769}
6770
6771
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006772int cmd_sta_send_frame(struct sigma_dut *dut, struct sigma_conn *conn,
6773 struct sigma_cmd *cmd)
6774{
6775 const char *intf = get_param(cmd, "Interface");
6776 const char *val;
6777 enum send_frame_type frame;
6778 enum send_frame_protection protected;
6779 char buf[100];
6780 unsigned char addr[ETH_ALEN];
6781 int res;
6782
6783 val = get_param(cmd, "program");
6784 if (val == NULL)
6785 val = get_param(cmd, "frame");
6786 if (val && strcasecmp(val, "TDLS") == 0)
6787 return cmd_sta_send_frame_tdls(dut, conn, cmd);
6788 if (val && (strcasecmp(val, "HS2") == 0 ||
6789 strcasecmp(val, "HS2-R2") == 0))
6790 return cmd_sta_send_frame_hs2(dut, conn, cmd);
6791 if (val && strcasecmp(val, "VHT") == 0)
6792 return cmd_sta_send_frame_vht(dut, conn, cmd);
priyadharshini gowthamand66913a2016-07-29 15:11:17 -07006793 if (val && strcasecmp(val, "LOC") == 0)
6794 return loc_cmd_sta_send_frame(dut, conn, cmd);
Lior David0fe101e2017-03-09 16:09:50 +02006795 if (val && strcasecmp(val, "60GHz") == 0)
6796 return cmd_sta_send_frame_60g(dut, conn, cmd);
Ashwini Patildb59b3c2017-04-13 15:19:23 +05306797 if (val && strcasecmp(val, "MBO") == 0) {
6798 res = mbo_cmd_sta_send_frame(dut, conn, intf, cmd);
6799 if (res != 2)
6800 return res;
6801 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006802
6803 val = get_param(cmd, "TD_DISC");
6804 if (val) {
6805 if (hwaddr_aton(val, addr) < 0)
6806 return -1;
6807 snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", val);
6808 if (wpa_command(intf, buf) < 0) {
6809 send_resp(dut, conn, SIGMA_ERROR,
6810 "ErrorCode,Failed to send TDLS discovery");
6811 return 0;
6812 }
6813 return 1;
6814 }
6815
6816 val = get_param(cmd, "TD_Setup");
6817 if (val) {
6818 if (hwaddr_aton(val, addr) < 0)
6819 return -1;
6820 snprintf(buf, sizeof(buf), "TDLS_SETUP %s", val);
6821 if (wpa_command(intf, buf) < 0) {
6822 send_resp(dut, conn, SIGMA_ERROR,
6823 "ErrorCode,Failed to start TDLS setup");
6824 return 0;
6825 }
6826 return 1;
6827 }
6828
6829 val = get_param(cmd, "TD_TearDown");
6830 if (val) {
6831 if (hwaddr_aton(val, addr) < 0)
6832 return -1;
6833 snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", val);
6834 if (wpa_command(intf, buf) < 0) {
6835 send_resp(dut, conn, SIGMA_ERROR,
6836 "ErrorCode,Failed to tear down TDLS link");
6837 return 0;
6838 }
6839 return 1;
6840 }
6841
6842 val = get_param(cmd, "TD_ChannelSwitch");
6843 if (val) {
6844 /* TODO */
6845 send_resp(dut, conn, SIGMA_ERROR,
6846 "ErrorCode,TD_ChannelSwitch not yet supported");
6847 return 0;
6848 }
6849
6850 val = get_param(cmd, "TD_NF");
6851 if (val) {
6852 /* TODO */
6853 send_resp(dut, conn, SIGMA_ERROR,
6854 "ErrorCode,TD_NF not yet supported");
6855 return 0;
6856 }
6857
6858 val = get_param(cmd, "PMFFrameType");
6859 if (val == NULL)
6860 val = get_param(cmd, "FrameName");
6861 if (val == NULL)
6862 val = get_param(cmd, "Type");
6863 if (val == NULL)
6864 return -1;
6865 if (strcasecmp(val, "disassoc") == 0)
6866 frame = DISASSOC;
6867 else if (strcasecmp(val, "deauth") == 0)
6868 frame = DEAUTH;
6869 else if (strcasecmp(val, "saquery") == 0)
6870 frame = SAQUERY;
6871 else if (strcasecmp(val, "auth") == 0)
6872 frame = AUTH;
6873 else if (strcasecmp(val, "assocreq") == 0)
6874 frame = ASSOCREQ;
6875 else if (strcasecmp(val, "reassocreq") == 0)
6876 frame = REASSOCREQ;
6877 else if (strcasecmp(val, "neigreq") == 0) {
6878 sigma_dut_print(dut, DUT_MSG_INFO, "Got neighbor request");
6879
6880 val = get_param(cmd, "ssid");
6881 if (val == NULL)
6882 return -1;
6883
6884 res = send_neighbor_request(dut, intf, val);
6885 if (res) {
6886 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
6887 "Failed to send neighbor report request");
6888 return 0;
6889 }
6890
6891 return 1;
Ashwini Patil5acd7382017-04-13 15:55:04 +05306892 } else if (strcasecmp(val, "transmgmtquery") == 0 ||
6893 strcasecmp(val, "BTMQuery") == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006894 sigma_dut_print(dut, DUT_MSG_DEBUG,
6895 "Got Transition Management Query");
6896
Ashwini Patil5acd7382017-04-13 15:55:04 +05306897 res = send_trans_mgmt_query(dut, intf, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006898 if (res) {
6899 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
6900 "Failed to send Transition Management Query");
6901 return 0;
6902 }
6903
6904 return 1;
6905 } else {
6906 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6907 "PMFFrameType");
6908 return 0;
6909 }
6910
6911 val = get_param(cmd, "PMFProtected");
6912 if (val == NULL)
6913 val = get_param(cmd, "Protected");
6914 if (val == NULL)
6915 return -1;
6916 if (strcasecmp(val, "Correct-key") == 0 ||
6917 strcasecmp(val, "CorrectKey") == 0)
6918 protected = CORRECT_KEY;
6919 else if (strcasecmp(val, "IncorrectKey") == 0)
6920 protected = INCORRECT_KEY;
6921 else if (strcasecmp(val, "Unprotected") == 0)
6922 protected = UNPROTECTED;
6923 else {
6924 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6925 "PMFProtected");
6926 return 0;
6927 }
6928
6929 if (protected != UNPROTECTED &&
6930 (frame == AUTH || frame == ASSOCREQ || frame == REASSOCREQ)) {
6931 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Impossible "
6932 "PMFProtected for auth/assocreq/reassocreq");
6933 return 0;
6934 }
6935
6936 if (if_nametoindex("sigmadut") == 0) {
6937 snprintf(buf, sizeof(buf),
6938 "iw dev %s interface add sigmadut type monitor",
6939 get_station_ifname());
6940 if (system(buf) != 0 ||
6941 if_nametoindex("sigmadut") == 0) {
6942 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
6943 "monitor interface with '%s'", buf);
6944 return -2;
6945 }
6946 }
6947
6948 if (system("ifconfig sigmadut up") != 0) {
6949 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
6950 "monitor interface up");
6951 return -2;
6952 }
6953
6954 return sta_inject_frame(dut, conn, frame, protected, NULL);
6955}
6956
6957
6958static int cmd_sta_set_parameter_hs2(struct sigma_dut *dut,
6959 struct sigma_conn *conn,
6960 struct sigma_cmd *cmd,
6961 const char *ifname)
6962{
6963 char buf[200];
6964 const char *val;
6965
6966 val = get_param(cmd, "ClearARP");
6967 if (val && atoi(val) == 1) {
6968 snprintf(buf, sizeof(buf), "ip neigh flush dev %s", ifname);
6969 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6970 if (system(buf) != 0) {
6971 send_resp(dut, conn, SIGMA_ERROR,
6972 "errorCode,Failed to clear ARP cache");
6973 return 0;
6974 }
6975 }
6976
6977 return 1;
6978}
6979
6980
6981int cmd_sta_set_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
6982 struct sigma_cmd *cmd)
6983{
6984 const char *intf = get_param(cmd, "Interface");
6985 const char *val;
6986
6987 if (intf == NULL)
6988 return -1;
6989
6990 val = get_param(cmd, "program");
6991 if (val && (strcasecmp(val, "HS2") == 0 ||
6992 strcasecmp(val, "HS2-R2") == 0))
6993 return cmd_sta_set_parameter_hs2(dut, conn, cmd, intf);
6994
6995 return -1;
6996}
6997
6998
6999static int cmd_sta_set_macaddr(struct sigma_dut *dut, struct sigma_conn *conn,
7000 struct sigma_cmd *cmd)
7001{
7002 const char *intf = get_param(cmd, "Interface");
7003 const char *mac = get_param(cmd, "MAC");
7004
7005 if (intf == NULL || mac == NULL)
7006 return -1;
7007
7008 sigma_dut_print(dut, DUT_MSG_INFO, "Change local MAC address for "
7009 "interface %s to %s", intf, mac);
7010
7011 if (dut->set_macaddr) {
7012 char buf[128];
7013 int res;
7014 if (strcasecmp(mac, "default") == 0) {
7015 res = snprintf(buf, sizeof(buf), "%s",
7016 dut->set_macaddr);
7017 dut->tmp_mac_addr = 0;
7018 } else {
7019 res = snprintf(buf, sizeof(buf), "%s %s",
7020 dut->set_macaddr, mac);
7021 dut->tmp_mac_addr = 1;
7022 }
7023 if (res < 0 || res >= (int) sizeof(buf))
7024 return -1;
7025 if (system(buf) != 0) {
7026 send_resp(dut, conn, SIGMA_ERROR,
7027 "errorCode,Failed to set MAC "
7028 "address");
7029 return 0;
7030 }
7031 return 1;
7032 }
7033
7034 if (strcasecmp(mac, "default") == 0)
7035 return 1;
7036
7037 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
7038 "command");
7039 return 0;
7040}
7041
7042
7043static int iwpriv_tdlsoffchnmode(struct sigma_dut *dut,
7044 struct sigma_conn *conn, const char *intf,
7045 int val)
7046{
7047 char buf[200];
7048 int res;
7049
7050 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchnmode %d",
7051 intf, val);
7052 if (res < 0 || res >= (int) sizeof(buf))
7053 return -1;
7054 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7055 if (system(buf) != 0) {
7056 send_resp(dut, conn, SIGMA_ERROR,
7057 "errorCode,Failed to configure offchannel mode");
7058 return 0;
7059 }
7060
7061 return 1;
7062}
7063
7064
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007065static int off_chan_val(enum sec_ch_offset off)
7066{
7067 switch (off) {
7068 case SEC_CH_NO:
7069 return 0;
7070 case SEC_CH_40ABOVE:
7071 return 40;
7072 case SEC_CH_40BELOW:
7073 return -40;
7074 }
7075
7076 return 0;
7077}
7078
7079
7080static int iwpriv_set_offchan(struct sigma_dut *dut, struct sigma_conn *conn,
7081 const char *intf, int off_ch_num,
7082 enum sec_ch_offset sec)
7083{
7084 char buf[200];
7085 int res;
7086
7087 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchan %d",
7088 intf, off_ch_num);
7089 if (res < 0 || res >= (int) sizeof(buf))
7090 return -1;
7091 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7092 if (system(buf) != 0) {
7093 send_resp(dut, conn, SIGMA_ERROR,
7094 "errorCode,Failed to set offchan");
7095 return 0;
7096 }
7097
7098 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsecchnoffst %d",
7099 intf, off_chan_val(sec));
7100 if (res < 0 || res >= (int) sizeof(buf))
7101 return -1;
7102 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7103 if (system(buf) != 0) {
7104 send_resp(dut, conn, SIGMA_ERROR,
7105 "errorCode,Failed to set sec chan offset");
7106 return 0;
7107 }
7108
7109 return 1;
7110}
7111
7112
7113static int tdls_set_offchannel_offset(struct sigma_dut *dut,
7114 struct sigma_conn *conn,
7115 const char *intf, int off_ch_num,
7116 enum sec_ch_offset sec)
7117{
7118 char buf[200];
7119 int res;
7120
7121 res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNEL %d",
7122 off_ch_num);
7123 if (res < 0 || res >= (int) sizeof(buf))
7124 return -1;
7125 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7126
7127 if (wpa_command(intf, buf) < 0) {
7128 send_resp(dut, conn, SIGMA_ERROR,
7129 "ErrorCode,Failed to set offchan");
7130 return 0;
7131 }
7132 res = snprintf(buf, sizeof(buf), "DRIVER TDLSSECONDARYCHANNELOFFSET %d",
7133 off_chan_val(sec));
7134 if (res < 0 || res >= (int) sizeof(buf))
7135 return -1;
7136
7137 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7138
7139 if (wpa_command(intf, buf) < 0) {
7140 send_resp(dut, conn, SIGMA_ERROR,
7141 "ErrorCode,Failed to set sec chan offset");
7142 return 0;
7143 }
7144
7145 return 1;
7146}
7147
7148
7149static int tdls_set_offchannel_mode(struct sigma_dut *dut,
7150 struct sigma_conn *conn,
7151 const char *intf, int val)
7152{
7153 char buf[200];
7154 int res;
7155
7156 res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNELMODE %d",
7157 val);
7158 if (res < 0 || res >= (int) sizeof(buf))
7159 return -1;
7160 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7161
7162 if (wpa_command(intf, buf) < 0) {
7163 send_resp(dut, conn, SIGMA_ERROR,
7164 "ErrorCode,Failed to configure offchannel mode");
7165 return 0;
7166 }
7167
7168 return 1;
7169}
7170
7171
7172static int cmd_sta_set_rfeature_tdls(const char *intf, struct sigma_dut *dut,
7173 struct sigma_conn *conn,
7174 struct sigma_cmd *cmd)
7175{
7176 const char *val;
7177 enum {
7178 CHSM_NOT_SET,
7179 CHSM_ENABLE,
7180 CHSM_DISABLE,
7181 CHSM_REJREQ,
7182 CHSM_UNSOLRESP
7183 } chsm = CHSM_NOT_SET;
7184 int off_ch_num = -1;
7185 enum sec_ch_offset sec_ch = SEC_CH_NO;
7186 int res;
7187
7188 val = get_param(cmd, "Uapsd");
7189 if (val) {
7190 char buf[100];
7191 if (strcasecmp(val, "Enable") == 0)
7192 snprintf(buf, sizeof(buf), "SET ps 99");
7193 else if (strcasecmp(val, "Disable") == 0)
7194 snprintf(buf, sizeof(buf), "SET ps 98");
7195 else {
7196 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
7197 "Unsupported uapsd parameter value");
7198 return 0;
7199 }
7200 if (wpa_command(intf, buf)) {
7201 send_resp(dut, conn, SIGMA_ERROR,
7202 "ErrorCode,Failed to change U-APSD "
7203 "powersave mode");
7204 return 0;
7205 }
7206 }
7207
7208 val = get_param(cmd, "TPKTIMER");
7209 if (val && strcasecmp(val, "DISABLE") == 0) {
7210 if (wpa_command(intf, "SET tdls_testing 0x100")) {
7211 send_resp(dut, conn, SIGMA_ERROR,
7212 "ErrorCode,Failed to enable no TPK "
7213 "expiration test mode");
7214 return 0;
7215 }
7216 dut->no_tpk_expiration = 1;
7217 }
7218
7219 val = get_param(cmd, "ChSwitchMode");
7220 if (val) {
7221 if (strcasecmp(val, "Enable") == 0 ||
7222 strcasecmp(val, "Initiate") == 0)
7223 chsm = CHSM_ENABLE;
7224 else if (strcasecmp(val, "Disable") == 0 ||
7225 strcasecmp(val, "passive") == 0)
7226 chsm = CHSM_DISABLE;
7227 else if (strcasecmp(val, "RejReq") == 0)
7228 chsm = CHSM_REJREQ;
7229 else if (strcasecmp(val, "UnSolResp") == 0)
7230 chsm = CHSM_UNSOLRESP;
7231 else {
7232 send_resp(dut, conn, SIGMA_ERROR,
7233 "ErrorCode,Unknown ChSwitchMode value");
7234 return 0;
7235 }
7236 }
7237
7238 val = get_param(cmd, "OffChNum");
7239 if (val) {
7240 off_ch_num = atoi(val);
7241 if (off_ch_num == 0) {
7242 send_resp(dut, conn, SIGMA_ERROR,
7243 "ErrorCode,Invalid OffChNum");
7244 return 0;
7245 }
7246 }
7247
7248 val = get_param(cmd, "SecChOffset");
7249 if (val) {
7250 if (strcmp(val, "20") == 0)
7251 sec_ch = SEC_CH_NO;
7252 else if (strcasecmp(val, "40above") == 0)
7253 sec_ch = SEC_CH_40ABOVE;
7254 else if (strcasecmp(val, "40below") == 0)
7255 sec_ch = SEC_CH_40BELOW;
7256 else {
7257 send_resp(dut, conn, SIGMA_ERROR,
7258 "ErrorCode,Unknown SecChOffset value");
7259 return 0;
7260 }
7261 }
7262
7263 if (chsm == CHSM_NOT_SET) {
7264 /* no offchannel changes requested */
7265 return 1;
7266 }
7267
7268 if (strcmp(intf, get_main_ifname()) != 0 &&
7269 strcmp(intf, get_station_ifname()) != 0) {
7270 send_resp(dut, conn, SIGMA_ERROR,
7271 "ErrorCode,Unknown interface");
7272 return 0;
7273 }
7274
7275 switch (chsm) {
7276 case CHSM_NOT_SET:
Jouni Malinen280f5ba2016-08-29 21:33:10 +03007277 res = 1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007278 break;
7279 case CHSM_ENABLE:
7280 if (off_ch_num < 0) {
7281 send_resp(dut, conn, SIGMA_ERROR,
7282 "ErrorCode,Missing OffChNum argument");
7283 return 0;
7284 }
7285 if (wifi_chip_type == DRIVER_WCN) {
7286 res = tdls_set_offchannel_offset(dut, conn, intf,
7287 off_ch_num, sec_ch);
7288 } else {
7289 res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
7290 sec_ch);
7291 }
7292 if (res != 1)
7293 return res;
7294 if (wifi_chip_type == DRIVER_WCN)
7295 res = tdls_set_offchannel_mode(dut, conn, intf, 1);
7296 else
7297 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 1);
7298 break;
7299 case CHSM_DISABLE:
7300 if (wifi_chip_type == DRIVER_WCN)
7301 res = tdls_set_offchannel_mode(dut, conn, intf, 2);
7302 else
7303 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 2);
7304 break;
7305 case CHSM_REJREQ:
7306 if (wifi_chip_type == DRIVER_WCN)
7307 res = tdls_set_offchannel_mode(dut, conn, intf, 3);
7308 else
7309 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 3);
7310 break;
7311 case CHSM_UNSOLRESP:
7312 if (off_ch_num < 0) {
7313 send_resp(dut, conn, SIGMA_ERROR,
7314 "ErrorCode,Missing OffChNum argument");
7315 return 0;
7316 }
7317 if (wifi_chip_type == DRIVER_WCN) {
7318 res = tdls_set_offchannel_offset(dut, conn, intf,
7319 off_ch_num, sec_ch);
7320 } else {
7321 res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
7322 sec_ch);
7323 }
7324 if (res != 1)
7325 return res;
7326 if (wifi_chip_type == DRIVER_WCN)
7327 res = tdls_set_offchannel_mode(dut, conn, intf, 4);
7328 else
7329 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 4);
7330 break;
7331 }
7332
7333 return res;
7334}
7335
7336
7337static int ath_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
7338 struct sigma_conn *conn,
7339 struct sigma_cmd *cmd)
7340{
7341 const char *val;
7342 char *token, *result;
7343
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08007344 novap_reset(dut, intf);
7345
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007346 val = get_param(cmd, "nss_mcs_opt");
7347 if (val) {
7348 /* String (nss_operating_mode; mcs_operating_mode) */
7349 int nss, mcs;
7350 char buf[50];
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05307351 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007352
7353 token = strdup(val);
7354 if (!token)
7355 return 0;
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05307356 result = strtok_r(token, ";", &saveptr);
Pradeep Reddy POTTETI41b8c542016-06-15 16:09:46 +05307357 if (!result) {
7358 sigma_dut_print(dut, DUT_MSG_ERROR,
7359 "VHT NSS not specified");
7360 goto failed;
7361 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007362 if (strcasecmp(result, "def") != 0) {
7363 nss = atoi(result);
7364 if (nss == 4)
7365 ath_disable_txbf(dut, intf);
7366 snprintf(buf, sizeof(buf), "iwpriv %s nss %d",
7367 intf, nss);
7368 if (system(buf) != 0) {
7369 sigma_dut_print(dut, DUT_MSG_ERROR,
7370 "iwpriv nss failed");
7371 goto failed;
7372 }
7373 }
7374
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05307375 result = strtok_r(NULL, ";", &saveptr);
Pradeep Reddy POTTETI41b8c542016-06-15 16:09:46 +05307376 if (!result) {
7377 sigma_dut_print(dut, DUT_MSG_ERROR,
7378 "VHT MCS not specified");
7379 goto failed;
7380 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007381 if (strcasecmp(result, "def") == 0) {
7382 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0",
7383 intf);
7384 if (system(buf) != 0) {
7385 sigma_dut_print(dut, DUT_MSG_ERROR,
7386 "iwpriv set11NRates failed");
7387 goto failed;
7388 }
7389
7390 } else {
7391 mcs = atoi(result);
7392 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d",
7393 intf, mcs);
7394 if (system(buf) != 0) {
7395 sigma_dut_print(dut, DUT_MSG_ERROR,
7396 "iwpriv vhtmcs failed");
7397 goto failed;
7398 }
7399 }
7400 /* Channel width gets messed up, fix this */
7401 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
7402 intf, dut->chwidth);
7403 if (system(buf) != 0) {
7404 sigma_dut_print(dut, DUT_MSG_ERROR,
7405 "iwpriv chwidth failed");
7406 }
7407 }
7408
7409 return 1;
7410failed:
7411 free(token);
7412 return 0;
7413}
7414
7415
7416static int cmd_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
7417 struct sigma_conn *conn,
7418 struct sigma_cmd *cmd)
7419{
7420 switch (get_driver_type()) {
7421 case DRIVER_ATHEROS:
7422 return ath_sta_set_rfeature_vht(intf, dut, conn, cmd);
7423 default:
7424 send_resp(dut, conn, SIGMA_ERROR,
7425 "errorCode,Unsupported sta_set_rfeature(VHT) with the current driver");
7426 return 0;
7427 }
7428}
7429
7430
Ashwini Patil5acd7382017-04-13 15:55:04 +05307431static int btm_query_candidate_list(struct sigma_dut *dut,
7432 struct sigma_conn *conn,
7433 struct sigma_cmd *cmd)
7434{
7435 const char *bssid, *info, *op_class, *ch, *phy_type, *pref;
7436 int len, ret;
7437 char buf[10];
7438
7439 /*
7440 * Neighbor Report elements format:
7441 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
7442 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
7443 * eg: neighbor=aa:bb:cc:dd:ee:ff,17,81,6,1,030101
7444 */
7445
7446 bssid = get_param(cmd, "Nebor_BSSID");
7447 if (!bssid) {
7448 send_resp(dut, conn, SIGMA_INVALID,
7449 "errorCode,Nebor_BSSID is missing");
7450 return 0;
7451 }
7452
7453 info = get_param(cmd, "Nebor_Bssid_Info");
7454 if (!info) {
7455 sigma_dut_print(dut, DUT_MSG_INFO,
7456 "Using default value for Nebor_Bssid_Info: %s",
7457 DEFAULT_NEIGHBOR_BSSID_INFO);
7458 info = DEFAULT_NEIGHBOR_BSSID_INFO;
7459 }
7460
7461 op_class = get_param(cmd, "Nebor_Op_Class");
7462 if (!op_class) {
7463 send_resp(dut, conn, SIGMA_INVALID,
7464 "errorCode,Nebor_Op_Class is missing");
7465 return 0;
7466 }
7467
7468 ch = get_param(cmd, "Nebor_Op_Ch");
7469 if (!ch) {
7470 send_resp(dut, conn, SIGMA_INVALID,
7471 "errorCode,Nebor_Op_Ch is missing");
7472 return 0;
7473 }
7474
7475 phy_type = get_param(cmd, "Nebor_Phy_Type");
7476 if (!phy_type) {
7477 sigma_dut_print(dut, DUT_MSG_INFO,
7478 "Using default value for Nebor_Phy_Type: %s",
7479 DEFAULT_NEIGHBOR_PHY_TYPE);
7480 phy_type = DEFAULT_NEIGHBOR_PHY_TYPE;
7481 }
7482
7483 /* Parse optional subelements */
7484 buf[0] = '\0';
7485 pref = get_param(cmd, "Nebor_Pref");
7486 if (pref) {
7487 /* hexdump for preferrence subelement */
7488 ret = snprintf(buf, sizeof(buf), ",0301%02x", atoi(pref));
7489 if (ret < 0 || ret >= (int) sizeof(buf)) {
7490 sigma_dut_print(dut, DUT_MSG_ERROR,
7491 "snprintf failed for optional subelement ret: %d",
7492 ret);
7493 send_resp(dut, conn, SIGMA_ERROR,
7494 "errorCode,snprintf failed for subelement");
7495 return 0;
7496 }
7497 }
7498
7499 if (!dut->btm_query_cand_list) {
7500 dut->btm_query_cand_list = calloc(1, NEIGHBOR_REPORT_SIZE);
7501 if (!dut->btm_query_cand_list) {
7502 send_resp(dut, conn, SIGMA_ERROR,
7503 "errorCode,Failed to allocate memory for btm_query_cand_list");
7504 return 0;
7505 }
7506 }
7507
7508 len = strlen(dut->btm_query_cand_list);
7509 ret = snprintf(dut->btm_query_cand_list + len,
7510 NEIGHBOR_REPORT_SIZE - len, " neighbor=%s,%s,%s,%s,%s%s",
7511 bssid, info, op_class, ch, phy_type, buf);
7512 if (ret < 0 || ret >= NEIGHBOR_REPORT_SIZE - len) {
7513 sigma_dut_print(dut, DUT_MSG_ERROR,
7514 "snprintf failed for neighbor report list ret: %d",
7515 ret);
7516 send_resp(dut, conn, SIGMA_ERROR,
7517 "errorCode,snprintf failed for neighbor report");
7518 free(dut->btm_query_cand_list);
7519 dut->btm_query_cand_list = NULL;
7520 return 0;
7521 }
7522
7523 return 1;
7524}
7525
7526
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007527static int cmd_sta_set_rfeature(struct sigma_dut *dut, struct sigma_conn *conn,
7528 struct sigma_cmd *cmd)
7529{
7530 const char *intf = get_param(cmd, "Interface");
7531 const char *prog = get_param(cmd, "Prog");
Ashwini Patil68d02cd2017-01-10 15:39:16 +05307532 const char *val;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007533
7534 if (intf == NULL || prog == NULL)
7535 return -1;
7536
Ashwini Patil5acd7382017-04-13 15:55:04 +05307537 /* BSS Transition candidate list for BTM query */
7538 val = get_param(cmd, "Nebor_BSSID");
7539 if (val && btm_query_candidate_list(dut, conn, cmd) == 0)
7540 return 0;
7541
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007542 if (strcasecmp(prog, "TDLS") == 0)
7543 return cmd_sta_set_rfeature_tdls(intf, dut, conn, cmd);
7544
7545 if (strcasecmp(prog, "VHT") == 0)
7546 return cmd_sta_set_rfeature_vht(intf, dut, conn, cmd);
7547
Ashwini Patil68d02cd2017-01-10 15:39:16 +05307548 if (strcasecmp(prog, "MBO") == 0) {
7549 val = get_param(cmd, "Cellular_Data_Cap");
7550 if (val &&
7551 mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
7552 return 0;
Ashwini Patil00402582017-04-13 12:29:39 +05307553
7554 val = get_param(cmd, "Ch_Pref");
7555 if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
7556 return 0;
7557
Ashwini Patil68d02cd2017-01-10 15:39:16 +05307558 return 1;
7559 }
7560
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007561 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported Prog");
7562 return 0;
7563}
7564
7565
7566static int cmd_sta_set_radio(struct sigma_dut *dut, struct sigma_conn *conn,
7567 struct sigma_cmd *cmd)
7568{
7569 const char *intf = get_param(cmd, "Interface");
7570 const char *mode = get_param(cmd, "Mode");
7571 int res;
7572
7573 if (intf == NULL || mode == NULL)
7574 return -1;
7575
7576 if (strcasecmp(mode, "On") == 0)
7577 res = wpa_command(intf, "SET radio_disabled 0");
7578 else if (strcasecmp(mode, "Off") == 0)
7579 res = wpa_command(intf, "SET radio_disabled 1");
7580 else
7581 return -1;
7582
7583 if (res) {
7584 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
7585 "radio mode");
7586 return 0;
7587 }
7588
7589 return 1;
7590}
7591
7592
7593static int cmd_sta_set_pwrsave(struct sigma_dut *dut, struct sigma_conn *conn,
7594 struct sigma_cmd *cmd)
7595{
7596 const char *intf = get_param(cmd, "Interface");
7597 const char *mode = get_param(cmd, "Mode");
7598 int res;
7599
7600 if (intf == NULL || mode == NULL)
7601 return -1;
7602
7603 if (strcasecmp(mode, "On") == 0)
7604 res = set_ps(intf, dut, 1);
7605 else if (strcasecmp(mode, "Off") == 0)
7606 res = set_ps(intf, dut, 0);
7607 else
7608 return -1;
7609
7610 if (res) {
7611 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
7612 "power save mode");
7613 return 0;
7614 }
7615
7616 return 1;
7617}
7618
7619
7620static int cmd_sta_bssid_pool(struct sigma_dut *dut, struct sigma_conn *conn,
7621 struct sigma_cmd *cmd)
7622{
7623 const char *intf = get_param(cmd, "Interface");
7624 const char *val, *bssid;
7625 int res;
7626 char *buf;
7627 size_t buf_len;
7628
7629 val = get_param(cmd, "BSSID_FILTER");
7630 if (val == NULL)
7631 return -1;
7632
7633 bssid = get_param(cmd, "BSSID_List");
7634 if (atoi(val) == 0 || bssid == NULL) {
7635 /* Disable BSSID filter */
7636 if (wpa_command(intf, "SET bssid_filter ")) {
7637 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed "
7638 "to disable BSSID filter");
7639 return 0;
7640 }
7641
7642 return 1;
7643 }
7644
7645 buf_len = 100 + strlen(bssid);
7646 buf = malloc(buf_len);
7647 if (buf == NULL)
7648 return -1;
7649
7650 snprintf(buf, buf_len, "SET bssid_filter %s", bssid);
7651 res = wpa_command(intf, buf);
7652 free(buf);
7653 if (res) {
7654 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to enable "
7655 "BSSID filter");
7656 return 0;
7657 }
7658
7659 return 1;
7660}
7661
7662
7663static int cmd_sta_reset_parm(struct sigma_dut *dut, struct sigma_conn *conn,
7664 struct sigma_cmd *cmd)
7665{
7666 const char *intf = get_param(cmd, "Interface");
7667 const char *val;
7668
7669 /* TODO: ARP */
7670
7671 val = get_param(cmd, "HS2_CACHE_PROFILE");
7672 if (val && strcasecmp(val, "All") == 0)
7673 hs2_clear_credentials(intf);
7674
7675 return 1;
7676}
7677
7678
7679static int cmd_sta_get_key(struct sigma_dut *dut, struct sigma_conn *conn,
7680 struct sigma_cmd *cmd)
7681{
7682 const char *intf = get_param(cmd, "Interface");
7683 const char *key_type = get_param(cmd, "KeyType");
7684 char buf[100], resp[200];
7685
7686 if (key_type == NULL)
7687 return -1;
7688
7689 if (strcasecmp(key_type, "GTK") == 0) {
7690 if (wpa_command_resp(intf, "GET gtk", buf, sizeof(buf)) < 0 ||
7691 strncmp(buf, "FAIL", 4) == 0) {
7692 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7693 "not fetch current GTK");
7694 return 0;
7695 }
7696 snprintf(resp, sizeof(resp), "KeyValue,%s", buf);
7697 send_resp(dut, conn, SIGMA_COMPLETE, resp);
7698 return 0;
7699 } else {
7700 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
7701 "KeyType");
7702 return 0;
7703 }
7704
7705 return 1;
7706}
7707
7708
7709static int hs2_set_policy(struct sigma_dut *dut)
7710{
7711#ifdef ANDROID
7712 system("ip rule del prio 23000");
7713 if (system("ip rule add from all lookup main prio 23000") != 0) {
7714 sigma_dut_print(dut, DUT_MSG_ERROR,
7715 "Failed to run:ip rule add from all lookup main prio");
7716 return -1;
7717 }
7718 if (system("ip route flush cache") != 0) {
7719 sigma_dut_print(dut, DUT_MSG_ERROR,
7720 "Failed to run ip route flush cache");
7721 return -1;
7722 }
7723 return 1;
7724#else /* ANDROID */
7725 return 0;
7726#endif /* ANDROID */
7727}
7728
7729
7730static int cmd_sta_hs2_associate(struct sigma_dut *dut,
7731 struct sigma_conn *conn,
7732 struct sigma_cmd *cmd)
7733{
7734 const char *intf = get_param(cmd, "Interface");
7735 const char *val = get_param(cmd, "Ignore_blacklist");
7736 struct wpa_ctrl *ctrl;
7737 int res;
7738 char bssid[20], ssid[40], resp[100], buf[100], blacklisted[100];
7739 int tries = 0;
7740 int ignore_blacklist = 0;
7741 const char *events[] = {
7742 "CTRL-EVENT-CONNECTED",
7743 "INTERWORKING-BLACKLISTED",
7744 "INTERWORKING-NO-MATCH",
7745 NULL
7746 };
7747
7748 start_sta_mode(dut);
7749
7750 blacklisted[0] = '\0';
7751 if (val && atoi(val))
7752 ignore_blacklist = 1;
7753
7754try_again:
7755 ctrl = open_wpa_mon(intf);
7756 if (ctrl == NULL) {
7757 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
7758 "wpa_supplicant monitor connection");
7759 return -2;
7760 }
7761
7762 tries++;
7763 if (wpa_command(intf, "INTERWORKING_SELECT auto")) {
7764 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start "
7765 "Interworking connection");
7766 wpa_ctrl_detach(ctrl);
7767 wpa_ctrl_close(ctrl);
7768 return 0;
7769 }
7770
7771 buf[0] = '\0';
7772 while (1) {
7773 char *pos;
7774 res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
7775 pos = strstr(buf, "INTERWORKING-BLACKLISTED");
7776 if (!pos)
7777 break;
7778 pos += 25;
7779 sigma_dut_print(dut, DUT_MSG_DEBUG, "Found blacklisted AP: %s",
7780 pos);
7781 if (!blacklisted[0])
7782 memcpy(blacklisted, pos, strlen(pos) + 1);
7783 }
7784
7785 if (ignore_blacklist && blacklisted[0]) {
7786 char *end;
7787 end = strchr(blacklisted, ' ');
7788 if (end)
7789 *end = '\0';
7790 sigma_dut_print(dut, DUT_MSG_DEBUG, "Try to connect to a blacklisted network: %s",
7791 blacklisted);
7792 snprintf(buf, sizeof(buf), "INTERWORKING_CONNECT %s",
7793 blacklisted);
7794 if (wpa_command(intf, buf)) {
7795 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start Interworking connection to blacklisted network");
7796 wpa_ctrl_detach(ctrl);
7797 wpa_ctrl_close(ctrl);
7798 return 0;
7799 }
7800 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
7801 buf, sizeof(buf));
7802 }
7803
7804 wpa_ctrl_detach(ctrl);
7805 wpa_ctrl_close(ctrl);
7806
7807 if (res < 0) {
7808 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
7809 "connect");
7810 return 0;
7811 }
7812
7813 if (strstr(buf, "INTERWORKING-NO-MATCH") ||
7814 strstr(buf, "INTERWORKING-BLACKLISTED")) {
7815 if (tries < 2) {
7816 sigma_dut_print(dut, DUT_MSG_INFO, "No match found - try again to verify no APs were missed in the scan");
7817 goto try_again;
7818 }
7819 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,No network with "
7820 "matching credentials found");
7821 return 0;
7822 }
7823
7824 if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
7825 get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
7826 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
7827 "get current BSSID/SSID");
7828 return 0;
7829 }
7830
7831 snprintf(resp, sizeof(resp), "SSID,%s,BSSID,%s", ssid, bssid);
7832 send_resp(dut, conn, SIGMA_COMPLETE, resp);
7833 hs2_set_policy(dut);
7834 return 0;
7835}
7836
7837
7838static int sta_add_credential_uname_pwd(struct sigma_dut *dut,
7839 struct sigma_conn *conn,
7840 const char *ifname,
7841 struct sigma_cmd *cmd)
7842{
7843 const char *val;
7844 int id;
7845
7846 id = add_cred(ifname);
7847 if (id < 0)
7848 return -2;
7849 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
7850
7851 val = get_param(cmd, "prefer");
7852 if (val && atoi(val) > 0)
7853 set_cred(ifname, id, "priority", "1");
7854
7855 val = get_param(cmd, "REALM");
7856 if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
7857 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7858 "realm");
7859 return 0;
7860 }
7861
7862 val = get_param(cmd, "HOME_FQDN");
7863 if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
7864 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7865 "home_fqdn");
7866 return 0;
7867 }
7868
7869 val = get_param(cmd, "Username");
7870 if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
7871 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7872 "username");
7873 return 0;
7874 }
7875
7876 val = get_param(cmd, "Password");
7877 if (val && set_cred_quoted(ifname, id, "password", val) < 0) {
7878 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7879 "password");
7880 return 0;
7881 }
7882
7883 val = get_param(cmd, "ROOT_CA");
7884 if (val) {
7885 char fname[200];
7886 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
7887#ifdef __linux__
7888 if (!file_exists(fname)) {
7889 char msg[300];
7890 snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
7891 "file (%s) not found", fname);
7892 send_resp(dut, conn, SIGMA_ERROR, msg);
7893 return 0;
7894 }
7895#endif /* __linux__ */
7896 if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
7897 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7898 "not set root CA");
7899 return 0;
7900 }
7901 }
7902
7903 return 1;
7904}
7905
7906
7907static int update_devdetail_imsi(struct sigma_dut *dut, const char *imsi)
7908{
7909 FILE *in, *out;
7910 char buf[500];
7911 int found = 0;
7912
7913 in = fopen("devdetail.xml", "r");
7914 if (in == NULL)
7915 return -1;
7916 out = fopen("devdetail.xml.tmp", "w");
7917 if (out == NULL) {
7918 fclose(in);
7919 return -1;
7920 }
7921
7922 while (fgets(buf, sizeof(buf), in)) {
7923 char *pos = strstr(buf, "<IMSI>");
7924 if (pos) {
7925 sigma_dut_print(dut, DUT_MSG_INFO, "Updated DevDetail IMSI to %s",
7926 imsi);
7927 pos += 6;
7928 *pos = '\0';
7929 fprintf(out, "%s%s</IMSI>\n", buf, imsi);
7930 found++;
7931 } else {
7932 fprintf(out, "%s", buf);
7933 }
7934 }
7935
7936 fclose(out);
7937 fclose(in);
7938 if (found)
7939 rename("devdetail.xml.tmp", "devdetail.xml");
7940 else
7941 unlink("devdetail.xml.tmp");
7942
7943 return 0;
7944}
7945
7946
7947static int sta_add_credential_sim(struct sigma_dut *dut,
7948 struct sigma_conn *conn,
7949 const char *ifname, struct sigma_cmd *cmd)
7950{
7951 const char *val, *imsi = NULL;
7952 int id;
7953 char buf[200];
7954 int res;
7955 const char *pos;
7956 size_t mnc_len;
7957 char plmn_mcc[4];
7958 char plmn_mnc[4];
7959
7960 id = add_cred(ifname);
7961 if (id < 0)
7962 return -2;
7963 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
7964
7965 val = get_param(cmd, "prefer");
7966 if (val && atoi(val) > 0)
7967 set_cred(ifname, id, "priority", "1");
7968
7969 val = get_param(cmd, "PLMN_MCC");
7970 if (val == NULL) {
7971 send_resp(dut, conn, SIGMA_ERROR,
7972 "errorCode,Missing PLMN_MCC");
7973 return 0;
7974 }
7975 if (strlen(val) != 3) {
7976 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MCC");
7977 return 0;
7978 }
7979 snprintf(plmn_mcc, sizeof(plmn_mcc), "%s", val);
7980
7981 val = get_param(cmd, "PLMN_MNC");
7982 if (val == NULL) {
7983 send_resp(dut, conn, SIGMA_ERROR,
7984 "errorCode,Missing PLMN_MNC");
7985 return 0;
7986 }
7987 if (strlen(val) != 2 && strlen(val) != 3) {
7988 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MNC");
7989 return 0;
7990 }
7991 snprintf(plmn_mnc, sizeof(plmn_mnc), "%s", val);
7992
7993 val = get_param(cmd, "IMSI");
7994 if (val == NULL) {
7995 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing SIM "
7996 "IMSI");
7997 return 0;
7998 }
7999
8000 imsi = pos = val;
8001
8002 if (strncmp(plmn_mcc, pos, 3) != 0) {
8003 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MCC mismatch");
8004 return 0;
8005 }
8006 pos += 3;
8007
8008 mnc_len = strlen(plmn_mnc);
8009 if (mnc_len < 2) {
8010 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC not set");
8011 return 0;
8012 }
8013
8014 if (strncmp(plmn_mnc, pos, mnc_len) != 0) {
8015 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC mismatch");
8016 return 0;
8017 }
8018 pos += mnc_len;
8019
8020 res = snprintf(buf, sizeof(buf), "%s%s-%s",plmn_mcc, plmn_mnc, pos);
8021 if (res < 0 || res >= (int) sizeof(buf))
8022 return -1;
8023 if (set_cred_quoted(ifname, id, "imsi", buf) < 0) {
8024 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8025 "not set IMSI");
8026 return 0;
8027 }
8028
8029 val = get_param(cmd, "Password");
8030 if (val && set_cred_quoted(ifname, id, "milenage", val) < 0) {
8031 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8032 "not set password");
8033 return 0;
8034 }
8035
8036 if (dut->program == PROGRAM_HS2_R2) {
8037 /*
8038 * Set provisioning_sp for the test cases where SIM/USIM
8039 * provisioning is used.
8040 */
8041 if (val && set_cred_quoted(ifname, id, "provisioning_sp",
8042 "wi-fi.org") < 0) {
8043 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8044 "not set provisioning_sp");
8045 return 0;
8046 }
8047
8048 update_devdetail_imsi(dut, imsi);
8049 }
8050
8051 return 1;
8052}
8053
8054
8055static int sta_add_credential_cert(struct sigma_dut *dut,
8056 struct sigma_conn *conn,
8057 const char *ifname,
8058 struct sigma_cmd *cmd)
8059{
8060 const char *val;
8061 int id;
8062
8063 id = add_cred(ifname);
8064 if (id < 0)
8065 return -2;
8066 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
8067
8068 val = get_param(cmd, "prefer");
8069 if (val && atoi(val) > 0)
8070 set_cred(ifname, id, "priority", "1");
8071
8072 val = get_param(cmd, "REALM");
8073 if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
8074 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
8075 "realm");
8076 return 0;
8077 }
8078
8079 val = get_param(cmd, "HOME_FQDN");
8080 if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
8081 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
8082 "home_fqdn");
8083 return 0;
8084 }
8085
8086 val = get_param(cmd, "Username");
8087 if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
8088 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
8089 "username");
8090 return 0;
8091 }
8092
8093 val = get_param(cmd, "clientCertificate");
8094 if (val) {
8095 char fname[200];
8096 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
8097#ifdef __linux__
8098 if (!file_exists(fname)) {
8099 char msg[300];
8100 snprintf(msg, sizeof(msg),
8101 "ErrorCode,clientCertificate "
8102 "file (%s) not found", fname);
8103 send_resp(dut, conn, SIGMA_ERROR, msg);
8104 return 0;
8105 }
8106#endif /* __linux__ */
8107 if (set_cred_quoted(ifname, id, "client_cert", fname) < 0) {
8108 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8109 "not set client_cert");
8110 return 0;
8111 }
8112 if (set_cred_quoted(ifname, id, "private_key", fname) < 0) {
8113 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8114 "not set private_key");
8115 return 0;
8116 }
8117 }
8118
8119 val = get_param(cmd, "ROOT_CA");
8120 if (val) {
8121 char fname[200];
8122 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
8123#ifdef __linux__
8124 if (!file_exists(fname)) {
8125 char msg[300];
8126 snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
8127 "file (%s) not found", fname);
8128 send_resp(dut, conn, SIGMA_ERROR, msg);
8129 return 0;
8130 }
8131#endif /* __linux__ */
8132 if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
8133 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8134 "not set root CA");
8135 return 0;
8136 }
8137 }
8138
8139 return 1;
8140}
8141
8142
8143static int cmd_sta_add_credential(struct sigma_dut *dut,
8144 struct sigma_conn *conn,
8145 struct sigma_cmd *cmd)
8146{
8147 const char *intf = get_param(cmd, "Interface");
8148 const char *type;
8149
8150 start_sta_mode(dut);
8151
8152 type = get_param(cmd, "Type");
8153 if (!type)
8154 return -1;
8155
8156 if (strcasecmp(type, "uname_pwd") == 0)
8157 return sta_add_credential_uname_pwd(dut, conn, intf, cmd);
8158
8159 if (strcasecmp(type, "sim") == 0)
8160 return sta_add_credential_sim(dut, conn, intf, cmd);
8161
8162 if (strcasecmp(type, "cert") == 0)
8163 return sta_add_credential_cert(dut, conn, intf, cmd);
8164
8165 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported credential "
8166 "type");
8167 return 0;
8168}
8169
8170
8171static int cmd_sta_scan(struct sigma_dut *dut, struct sigma_conn *conn,
8172 struct sigma_cmd *cmd)
8173{
8174 const char *intf = get_param(cmd, "Interface");
8175 const char *val;
8176 char buf[100];
8177 int res;
8178
8179 val = get_param(cmd, "HESSID");
8180 if (val) {
8181 res = snprintf(buf, sizeof(buf), "SET hessid %s", val);
8182 if (res < 0 || res >= (int) sizeof(buf))
8183 return -1;
8184 wpa_command(intf, buf);
8185 }
8186
8187 val = get_param(cmd, "ACCS_NET_TYPE");
8188 if (val) {
8189 res = snprintf(buf, sizeof(buf), "SET access_network_type %s",
8190 val);
8191 if (res < 0 || res >= (int) sizeof(buf))
8192 return -1;
8193 wpa_command(intf, buf);
8194 }
8195
8196 if (wpa_command(intf, "SCAN")) {
8197 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not start "
8198 "scan");
8199 return 0;
8200 }
8201
8202 return 1;
8203}
8204
8205
8206static int cmd_sta_set_systime(struct sigma_dut *dut, struct sigma_conn *conn,
8207 struct sigma_cmd *cmd)
8208{
8209#ifdef __linux__
8210 struct timeval tv;
8211 struct tm tm;
8212 time_t t;
8213 const char *val;
Pradeep Reddy POTTETI429c69e2016-10-13 17:22:03 +05308214 int v;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008215
8216 wpa_command(get_station_ifname(), "PMKSA_FLUSH");
8217
8218 memset(&tm, 0, sizeof(tm));
8219 val = get_param(cmd, "seconds");
8220 if (val)
8221 tm.tm_sec = atoi(val);
8222 val = get_param(cmd, "minutes");
8223 if (val)
8224 tm.tm_min = atoi(val);
8225 val = get_param(cmd, "hours");
8226 if (val)
8227 tm.tm_hour = atoi(val);
8228 val = get_param(cmd, "date");
8229 if (val)
8230 tm.tm_mday = atoi(val);
8231 val = get_param(cmd, "month");
Pradeep Reddy POTTETI429c69e2016-10-13 17:22:03 +05308232 if (val) {
8233 v = atoi(val);
8234 if (v < 1 || v > 12) {
8235 send_resp(dut, conn, SIGMA_INVALID,
8236 "errorCode,Invalid month");
8237 return 0;
8238 }
8239 tm.tm_mon = v - 1;
8240 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008241 val = get_param(cmd, "year");
8242 if (val) {
8243 int year = atoi(val);
8244#ifdef ANDROID
8245 if (year > 2035)
8246 year = 2035; /* years beyond 2035 not supported */
8247#endif /* ANDROID */
8248 tm.tm_year = year - 1900;
8249 }
8250 t = mktime(&tm);
8251 if (t == (time_t) -1) {
8252 send_resp(dut, conn, SIGMA_ERROR,
8253 "errorCode,Invalid date or time");
8254 return 0;
8255 }
8256
8257 memset(&tv, 0, sizeof(tv));
8258 tv.tv_sec = t;
8259
8260 if (settimeofday(&tv, NULL) < 0) {
8261 sigma_dut_print(dut, DUT_MSG_INFO, "settimeofday failed: %s",
8262 strerror(errno));
8263 send_resp(dut, conn, SIGMA_ERROR,
8264 "errorCode,Failed to set time");
8265 return 0;
8266 }
8267
8268 return 1;
8269#endif /* __linux__ */
8270
8271 return -1;
8272}
8273
8274
8275static int cmd_sta_osu(struct sigma_dut *dut, struct sigma_conn *conn,
8276 struct sigma_cmd *cmd)
8277{
8278 const char *intf = get_param(cmd, "Interface");
8279 const char *name, *val;
8280 int prod_ess_assoc = 1;
8281 char buf[200], bssid[100], ssid[100];
8282 int res;
8283 struct wpa_ctrl *ctrl;
8284
8285 name = get_param(cmd, "osuFriendlyName");
8286
8287 val = get_param(cmd, "ProdESSAssoc");
8288 if (val)
8289 prod_ess_assoc = atoi(val);
8290
8291 kill_dhcp_client(dut, intf);
8292 if (start_dhcp_client(dut, intf) < 0)
8293 return -2;
8294
8295 sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger OSU");
8296 mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
8297 res = snprintf(buf, sizeof(buf),
8298 "%s %s%s%s signup osu-ca.pem",
8299 prod_ess_assoc ? "" : "-N",
8300 name ? "-O'" : "", name ? name : "",
8301 name ? "'" : "");
8302
Kanchanapally, Vidyullatha12b66762015-12-31 16:46:42 +05308303 hs2_set_policy(dut);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008304 if (run_hs20_osu(dut, buf) < 0) {
8305 FILE *f;
8306
8307 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to complete OSU");
8308
8309 f = fopen("hs20-osu-client.res", "r");
8310 if (f) {
8311 char resp[400], res[300], *pos;
8312 if (!fgets(res, sizeof(res), f))
8313 res[0] = '\0';
8314 pos = strchr(res, '\n');
8315 if (pos)
8316 *pos = '\0';
8317 fclose(f);
8318 sigma_dut_summary(dut, "hs20-osu-client provisioning failed: %s",
8319 res);
8320 snprintf(resp, sizeof(resp), "notify-send '%s'", res);
8321 if (system(resp) != 0) {
8322 }
8323 snprintf(resp, sizeof(resp),
8324 "SSID,,BSSID,,failureReason,%s", res);
8325 send_resp(dut, conn, SIGMA_COMPLETE, resp);
8326 return 0;
8327 }
8328
8329 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
8330 return 0;
8331 }
8332
8333 if (!prod_ess_assoc)
8334 goto report;
8335
8336 ctrl = open_wpa_mon(intf);
8337 if (ctrl == NULL) {
8338 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
8339 "wpa_supplicant monitor connection");
8340 return -1;
8341 }
8342
8343 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
8344 buf, sizeof(buf));
8345
8346 wpa_ctrl_detach(ctrl);
8347 wpa_ctrl_close(ctrl);
8348
8349 if (res < 0) {
8350 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to connect to "
8351 "network after OSU");
8352 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
8353 return 0;
8354 }
8355
8356report:
8357 if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
8358 get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
8359 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get BSSID/SSID");
8360 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
8361 return 0;
8362 }
8363
8364 snprintf(buf, sizeof(buf), "SSID,%s,BSSID,%s", ssid, bssid);
8365 send_resp(dut, conn, SIGMA_COMPLETE, buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008366 return 0;
8367}
8368
8369
8370static int cmd_sta_policy_update(struct sigma_dut *dut, struct sigma_conn *conn,
8371 struct sigma_cmd *cmd)
8372{
8373 const char *val;
8374 int timeout = 120;
8375
8376 val = get_param(cmd, "PolicyUpdate");
8377 if (val == NULL || atoi(val) == 0)
8378 return 1; /* No operation requested */
8379
8380 val = get_param(cmd, "Timeout");
8381 if (val)
8382 timeout = atoi(val);
8383
8384 if (timeout) {
8385 /* TODO: time out the command and return
8386 * PolicyUpdateStatus,TIMEOUT if needed. */
8387 }
8388
8389 sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger policy update");
8390 mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
8391 if (run_hs20_osu(dut, "pol_upd fqdn=wi-fi.org") < 0) {
8392 send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,FAIL");
8393 return 0;
8394 }
8395
8396 send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,SUCCESS");
8397 return 0;
8398}
8399
8400
8401static int cmd_sta_er_config(struct sigma_dut *dut, struct sigma_conn *conn,
8402 struct sigma_cmd *cmd)
8403{
8404 struct wpa_ctrl *ctrl;
8405 const char *intf = get_param(cmd, "Interface");
8406 const char *bssid = get_param(cmd, "Bssid");
8407 const char *ssid = get_param(cmd, "SSID");
8408 const char *security = get_param(cmd, "Security");
8409 const char *passphrase = get_param(cmd, "Passphrase");
8410 const char *pin = get_param(cmd, "PIN");
8411 char buf[1000];
8412 char ssid_hex[200], passphrase_hex[200];
8413 const char *keymgmt, *cipher;
8414
8415 if (intf == NULL)
8416 intf = get_main_ifname();
8417
8418 if (!bssid) {
8419 send_resp(dut, conn, SIGMA_ERROR,
8420 "ErrorCode,Missing Bssid argument");
8421 return 0;
8422 }
8423
8424 if (!ssid) {
8425 send_resp(dut, conn, SIGMA_ERROR,
8426 "ErrorCode,Missing SSID argument");
8427 return 0;
8428 }
8429
8430 if (!security) {
8431 send_resp(dut, conn, SIGMA_ERROR,
8432 "ErrorCode,Missing Security argument");
8433 return 0;
8434 }
8435
8436 if (!passphrase) {
8437 send_resp(dut, conn, SIGMA_ERROR,
8438 "ErrorCode,Missing Passphrase argument");
8439 return 0;
8440 }
8441
8442 if (!pin) {
8443 send_resp(dut, conn, SIGMA_ERROR,
8444 "ErrorCode,Missing PIN argument");
8445 return 0;
8446 }
8447
vamsi krishna8c9c1562017-05-12 15:51:46 +05308448 if (2 * strlen(ssid) >= sizeof(ssid_hex) ||
8449 2 * strlen(passphrase) >= sizeof(passphrase_hex)) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008450 send_resp(dut, conn, SIGMA_ERROR,
8451 "ErrorCode,Too long SSID/passphrase");
8452 return 0;
8453 }
8454
8455 ctrl = open_wpa_mon(intf);
8456 if (ctrl == NULL) {
8457 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
8458 "wpa_supplicant monitor connection");
8459 return -2;
8460 }
8461
8462 if (strcasecmp(security, "wpa2-psk") == 0) {
8463 keymgmt = "WPA2PSK";
8464 cipher = "CCMP";
8465 } else {
8466 wpa_ctrl_detach(ctrl);
8467 wpa_ctrl_close(ctrl);
8468 send_resp(dut, conn, SIGMA_ERROR,
8469 "ErrorCode,Unsupported Security value");
8470 return 0;
8471 }
8472
8473 ascii2hexstr(ssid, ssid_hex);
8474 ascii2hexstr(passphrase, passphrase_hex);
8475 snprintf(buf, sizeof(buf), "WPS_REG %s %s %s %s %s %s",
8476 bssid, pin, ssid_hex, keymgmt, cipher, passphrase_hex);
8477
8478 if (wpa_command(intf, buf) < 0) {
8479 wpa_ctrl_detach(ctrl);
8480 wpa_ctrl_close(ctrl);
8481 send_resp(dut, conn, SIGMA_ERROR,
8482 "ErrorCode,Failed to start registrar");
8483 return 0;
8484 }
8485
8486 snprintf(dut->er_oper_bssid, sizeof(dut->er_oper_bssid), "%s", bssid);
8487 dut->er_oper_performed = 1;
8488
8489 return wps_connection_event(dut, conn, ctrl, intf, 0);
8490}
8491
8492
8493static int cmd_sta_wps_connect_pw_token(struct sigma_dut *dut,
8494 struct sigma_conn *conn,
8495 struct sigma_cmd *cmd)
8496{
8497 struct wpa_ctrl *ctrl;
8498 const char *intf = get_param(cmd, "Interface");
8499 const char *bssid = get_param(cmd, "Bssid");
8500 char buf[100];
8501
8502 if (!bssid) {
8503 send_resp(dut, conn, SIGMA_ERROR,
8504 "ErrorCode,Missing Bssid argument");
8505 return 0;
8506 }
8507
8508 ctrl = open_wpa_mon(intf);
8509 if (ctrl == NULL) {
8510 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
8511 "wpa_supplicant monitor connection");
8512 return -2;
8513 }
8514
8515 snprintf(buf, sizeof(buf), "WPS_NFC %s", bssid);
8516
8517 if (wpa_command(intf, buf) < 0) {
8518 wpa_ctrl_detach(ctrl);
8519 wpa_ctrl_close(ctrl);
8520 send_resp(dut, conn, SIGMA_ERROR,
8521 "ErrorCode,Failed to start registrar");
8522 return 0;
8523 }
8524
8525 return wps_connection_event(dut, conn, ctrl, intf, 0);
8526}
8527
8528
8529static int req_intf(struct sigma_cmd *cmd)
8530{
8531 return get_param(cmd, "interface") == NULL ? -1 : 0;
8532}
8533
8534
8535void sta_register_cmds(void)
8536{
8537 sigma_dut_reg_cmd("sta_get_ip_config", req_intf,
8538 cmd_sta_get_ip_config);
8539 sigma_dut_reg_cmd("sta_set_ip_config", req_intf,
8540 cmd_sta_set_ip_config);
8541 sigma_dut_reg_cmd("sta_get_info", req_intf, cmd_sta_get_info);
8542 sigma_dut_reg_cmd("sta_get_mac_address", req_intf,
8543 cmd_sta_get_mac_address);
8544 sigma_dut_reg_cmd("sta_is_connected", req_intf, cmd_sta_is_connected);
8545 sigma_dut_reg_cmd("sta_verify_ip_connection", req_intf,
8546 cmd_sta_verify_ip_connection);
8547 sigma_dut_reg_cmd("sta_get_bssid", req_intf, cmd_sta_get_bssid);
8548 sigma_dut_reg_cmd("sta_set_encryption", req_intf,
8549 cmd_sta_set_encryption);
8550 sigma_dut_reg_cmd("sta_set_psk", req_intf, cmd_sta_set_psk);
8551 sigma_dut_reg_cmd("sta_set_eaptls", req_intf, cmd_sta_set_eaptls);
8552 sigma_dut_reg_cmd("sta_set_eapttls", req_intf, cmd_sta_set_eapttls);
8553 sigma_dut_reg_cmd("sta_set_eapsim", req_intf, cmd_sta_set_eapsim);
8554 sigma_dut_reg_cmd("sta_set_peap", req_intf, cmd_sta_set_peap);
8555 sigma_dut_reg_cmd("sta_set_eapfast", req_intf, cmd_sta_set_eapfast);
8556 sigma_dut_reg_cmd("sta_set_eapaka", req_intf, cmd_sta_set_eapaka);
8557 sigma_dut_reg_cmd("sta_set_eapakaprime", req_intf,
8558 cmd_sta_set_eapakaprime);
8559 sigma_dut_reg_cmd("sta_set_security", req_intf, cmd_sta_set_security);
8560 sigma_dut_reg_cmd("sta_set_uapsd", req_intf, cmd_sta_set_uapsd);
8561 /* TODO: sta_set_ibss */
8562 /* TODO: sta_set_mode */
8563 sigma_dut_reg_cmd("sta_set_wmm", req_intf, cmd_sta_set_wmm);
8564 sigma_dut_reg_cmd("sta_associate", req_intf, cmd_sta_associate);
8565 /* TODO: sta_up_load */
8566 sigma_dut_reg_cmd("sta_preset_testparameters", req_intf,
8567 cmd_sta_preset_testparameters);
8568 /* TODO: sta_set_system */
8569 sigma_dut_reg_cmd("sta_set_11n", req_intf, cmd_sta_set_11n);
8570 /* TODO: sta_set_rifs_test */
8571 sigma_dut_reg_cmd("sta_set_wireless", req_intf, cmd_sta_set_wireless);
8572 sigma_dut_reg_cmd("sta_send_addba", req_intf, cmd_sta_send_addba);
8573 /* TODO: sta_send_coexist_mgmt */
8574 sigma_dut_reg_cmd("sta_disconnect", req_intf, cmd_sta_disconnect);
8575 sigma_dut_reg_cmd("sta_reassoc", req_intf, cmd_sta_reassoc);
8576 sigma_dut_reg_cmd("sta_reassociate", req_intf, cmd_sta_reassoc);
8577 sigma_dut_reg_cmd("sta_reset_default", req_intf,
8578 cmd_sta_reset_default);
8579 sigma_dut_reg_cmd("sta_send_frame", req_intf, cmd_sta_send_frame);
8580 sigma_dut_reg_cmd("sta_set_macaddr", req_intf, cmd_sta_set_macaddr);
8581 sigma_dut_reg_cmd("sta_set_rfeature", req_intf, cmd_sta_set_rfeature);
8582 sigma_dut_reg_cmd("sta_set_radio", req_intf, cmd_sta_set_radio);
8583 sigma_dut_reg_cmd("sta_set_pwrsave", req_intf, cmd_sta_set_pwrsave);
8584 sigma_dut_reg_cmd("sta_bssid_pool", req_intf, cmd_sta_bssid_pool);
8585 sigma_dut_reg_cmd("sta_reset_parm", req_intf, cmd_sta_reset_parm);
8586 sigma_dut_reg_cmd("sta_get_key", req_intf, cmd_sta_get_key);
8587 sigma_dut_reg_cmd("sta_hs2_associate", req_intf,
8588 cmd_sta_hs2_associate);
8589 sigma_dut_reg_cmd("sta_add_credential", req_intf,
8590 cmd_sta_add_credential);
8591 sigma_dut_reg_cmd("sta_scan", req_intf, cmd_sta_scan);
8592 sigma_dut_reg_cmd("sta_set_systime", NULL, cmd_sta_set_systime);
8593 sigma_dut_reg_cmd("sta_osu", req_intf, cmd_sta_osu);
8594 sigma_dut_reg_cmd("sta_policy_update", req_intf, cmd_sta_policy_update);
8595 sigma_dut_reg_cmd("sta_er_config", NULL, cmd_sta_er_config);
8596 sigma_dut_reg_cmd("sta_wps_connect_pw_token", req_intf,
8597 cmd_sta_wps_connect_pw_token);
8598 sigma_dut_reg_cmd("sta_exec_action", req_intf, cmd_sta_exec_action);
8599 sigma_dut_reg_cmd("sta_get_events", req_intf, cmd_sta_get_events);
8600 sigma_dut_reg_cmd("sta_get_parameter", req_intf, cmd_sta_get_parameter);
8601}