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