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