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