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