blob: e2ca2d6dd267f104aae6e0b4905a39608d50a4a8 [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");
Peng Xue9fa7952017-05-09 15:59:49 -07003088 if (val && strcasecmp(val, "HS2-R2") == 0)
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003089 return cmd_sta_preset_testparameters_hs2_r2(dut, conn, intf,
3090 cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003091
priyadharshini gowthamand66913a2016-07-29 15:11:17 -07003092 if (val && strcasecmp(val, "LOC") == 0)
3093 return loc_cmd_sta_preset_testparameters(dut, conn, cmd);
3094
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003095#ifdef ANDROID_NAN
3096 if (val && strcasecmp(val, "NAN") == 0)
3097 return nan_cmd_sta_preset_testparameters(dut, conn, cmd);
3098#endif /* ANDROID_NAN */
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07003099#ifdef MIRACAST
3100 if (val && (strcasecmp(val, "WFD") == 0 ||
3101 strcasecmp(val, "DisplayR2") == 0))
3102 return miracast_preset_testparameters(dut, conn, cmd);
3103#endif /* MIRACAST */
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003104
Ashwini Patil68d02cd2017-01-10 15:39:16 +05303105 if (val && strcasecmp(val, "MBO") == 0) {
3106 val = get_param(cmd, "Cellular_Data_Cap");
3107 if (val &&
3108 mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
3109 return 0;
Ashwini Patil00402582017-04-13 12:29:39 +05303110
3111 val = get_param(cmd, "Ch_Pref");
3112 if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
3113 return 0;
3114
Ashwini Patilc63161e2017-04-13 16:30:23 +05303115 val = get_param(cmd, "BSS_Transition");
3116 if (val && mbo_set_bss_trans_req(dut, conn, intf, val) == 0)
3117 return 0;
3118
Ashwini Patila75de5a2017-04-13 16:35:05 +05303119 val = get_param(cmd, "Assoc_Disallow");
3120 if (val && mbo_set_assoc_disallow(dut, conn, intf, val) == 0)
3121 return 0;
3122
Ashwini Patil9183fdb2017-04-13 16:58:25 +05303123 val = get_param(cmd, "Roaming");
3124 if (val && mbo_set_roaming(dut, conn, intf, val) == 0)
3125 return 0;
3126
Ashwini Patil68d02cd2017-01-10 15:39:16 +05303127 return 1;
3128 }
3129
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003130#if 0
3131 val = get_param(cmd, "Supplicant");
3132 if (val && strcasecmp(val, "Default") != 0) {
3133 send_resp(dut, conn, SIGMA_ERROR,
3134 "ErrorCode,Only default(Vendor) supplicant "
3135 "supported");
3136 return 0;
3137 }
3138#endif
3139
3140 val = get_param(cmd, "RTS");
3141 if (val) {
3142 switch (get_driver_type()) {
3143 case DRIVER_ATHEROS:
3144 ath_sta_set_rts(dut, intf, val);
3145 break;
3146 default:
3147#if 0
3148 send_resp(dut, conn, SIGMA_ERROR,
3149 "ErrorCode,Setting RTS not supported");
3150 return 0;
3151#else
3152 sigma_dut_print(dut, DUT_MSG_DEBUG,
3153 "Setting RTS not supported");
3154 break;
3155#endif
3156 }
3157 }
3158
3159#if 0
3160 val = get_param(cmd, "FRGMNT");
3161 if (val) {
3162 /* TODO */
3163 send_resp(dut, conn, SIGMA_ERROR,
3164 "ErrorCode,Setting FRGMNT not supported");
3165 return 0;
3166 }
3167#endif
3168
3169#if 0
3170 val = get_param(cmd, "Preamble");
3171 if (val) {
3172 /* TODO: Long/Short */
3173 send_resp(dut, conn, SIGMA_ERROR,
3174 "ErrorCode,Setting Preamble not supported");
3175 return 0;
3176 }
3177#endif
3178
3179 val = get_param(cmd, "Mode");
3180 if (val) {
3181 if (strcmp(val, "11b") == 0 ||
3182 strcmp(val, "11g") == 0 ||
3183 strcmp(val, "11a") == 0 ||
3184 strcmp(val, "11n") == 0 ||
3185 strcmp(val, "11ng") == 0 ||
3186 strcmp(val, "11nl") == 0 ||
3187 strcmp(val, "11nl(nabg)") == 0 ||
3188 strcmp(val, "AC") == 0 ||
3189 strcmp(val, "11AC") == 0 ||
3190 strcmp(val, "11ac") == 0 ||
3191 strcmp(val, "11na") == 0 ||
3192 strcmp(val, "11an") == 0) {
3193 /* STA supports all modes by default */
3194 } else {
3195 send_resp(dut, conn, SIGMA_ERROR,
3196 "ErrorCode,Setting Mode not supported");
3197 return 0;
3198 }
3199 }
3200
3201 val = get_param(cmd, "wmm");
3202 if (val) {
3203 switch (get_driver_type()) {
3204 case DRIVER_ATHEROS:
3205 ath_sta_set_wmm(dut, intf, val);
3206 break;
3207 default:
3208 sigma_dut_print(dut, DUT_MSG_DEBUG,
3209 "Setting wmm not supported");
3210 break;
3211 }
3212 }
3213
3214 val = get_param(cmd, "Powersave");
3215 if (val) {
3216 if (strcmp(val, "0") == 0 || strcasecmp(val, "off") == 0) {
3217 if (wpa_command(get_station_ifname(),
3218 "P2P_SET ps 0") < 0)
3219 return -2;
3220 /* Make sure test modes are disabled */
3221 wpa_command(get_station_ifname(), "P2P_SET ps 98");
3222 wpa_command(get_station_ifname(), "P2P_SET ps 96");
3223 } else if (strcmp(val, "1") == 0 ||
3224 strcasecmp(val, "PSPoll") == 0 ||
3225 strcasecmp(val, "on") == 0) {
3226 /* Disable default power save mode */
3227 wpa_command(get_station_ifname(), "P2P_SET ps 0");
3228 /* Enable PS-Poll test mode */
3229 if (wpa_command(get_station_ifname(),
3230 "P2P_SET ps 97") < 0 ||
3231 wpa_command(get_station_ifname(),
3232 "P2P_SET ps 99") < 0)
3233 return -2;
3234 } else if (strcmp(val, "2") == 0 ||
3235 strcasecmp(val, "Fast") == 0) {
3236 /* TODO */
3237 send_resp(dut, conn, SIGMA_ERROR,
3238 "ErrorCode,Powersave=Fast not supported");
3239 return 0;
3240 } else if (strcmp(val, "3") == 0 ||
3241 strcasecmp(val, "PSNonPoll") == 0) {
3242 /* Make sure test modes are disabled */
3243 wpa_command(get_station_ifname(), "P2P_SET ps 98");
3244 wpa_command(get_station_ifname(), "P2P_SET ps 96");
3245
3246 /* Enable default power save mode */
3247 if (wpa_command(get_station_ifname(),
3248 "P2P_SET ps 1") < 0)
3249 return -2;
3250 } else
3251 return -1;
3252 }
3253
3254 val = get_param(cmd, "NoAck");
3255 if (val) {
3256 switch (get_driver_type()) {
3257 case DRIVER_ATHEROS:
3258 ath_sta_set_noack(dut, intf, val);
3259 break;
3260 default:
3261 send_resp(dut, conn, SIGMA_ERROR,
3262 "ErrorCode,Setting NoAck not supported");
3263 return 0;
3264 }
3265 }
3266
3267 val = get_param(cmd, "IgnoreChswitchProhibit");
3268 if (val) {
3269 /* TODO: Enabled/disabled */
3270 if (strcasecmp(val, "Enabled") == 0) {
3271 send_resp(dut, conn, SIGMA_ERROR,
3272 "ErrorCode,Enabling IgnoreChswitchProhibit "
3273 "not supported");
3274 return 0;
3275 }
3276 }
3277
3278 val = get_param(cmd, "TDLS");
3279 if (val) {
3280 if (strcasecmp(val, "Disabled") == 0) {
3281 if (wpa_command(intf, "SET tdls_disabled 1")) {
3282 send_resp(dut, conn, SIGMA_ERROR,
3283 "ErrorCode,Failed to disable TDLS");
3284 return 0;
3285 }
3286 } else if (strcasecmp(val, "Enabled") == 0) {
3287 if (wpa_command(intf, "SET tdls_disabled 0")) {
3288 send_resp(dut, conn, SIGMA_ERROR,
3289 "ErrorCode,Failed to enable TDLS");
3290 return 0;
3291 }
3292 } else {
3293 send_resp(dut, conn, SIGMA_ERROR,
3294 "ErrorCode,Unsupported TDLS value");
3295 return 0;
3296 }
3297 }
3298
3299 val = get_param(cmd, "TDLSmode");
3300 if (val) {
3301 if (strcasecmp(val, "Default") == 0) {
3302 wpa_command(intf, "SET tdls_testing 0");
3303 } else if (strcasecmp(val, "APProhibit") == 0) {
3304 if (wpa_command(intf, "SET tdls_testing 0x400")) {
3305 send_resp(dut, conn, SIGMA_ERROR,
3306 "ErrorCode,Failed to enable ignore "
3307 "APProhibit TDLS mode");
3308 return 0;
3309 }
3310 } else if (strcasecmp(val, "HiLoMac") == 0) {
3311 /* STA should respond with TDLS setup req for a TDLS
3312 * setup req */
3313 if (wpa_command(intf, "SET tdls_testing 0x80")) {
3314 send_resp(dut, conn, SIGMA_ERROR,
3315 "ErrorCode,Failed to enable HiLoMac "
3316 "TDLS mode");
3317 return 0;
3318 }
3319 } else if (strcasecmp(val, "WeakSecurity") == 0) {
3320 /*
3321 * Since all security modes are enabled by default when
3322 * Sigma control is used, there is no need to do
3323 * anything here.
3324 */
3325 } else if (strcasecmp(val, "ExistLink") == 0) {
3326 /*
3327 * Since we allow new TDLS Setup Request even if there
3328 * is an existing link, nothing needs to be done for
3329 * this.
3330 */
3331 } else {
3332 /* TODO:
3333 * ExistLink: STA should send TDLS setup req even if
3334 * direct link already exists
3335 */
3336 send_resp(dut, conn, SIGMA_ERROR,
3337 "ErrorCode,Unsupported TDLSmode value");
3338 return 0;
3339 }
3340 }
3341
3342 val = get_param(cmd, "FakePubKey");
3343 if (val && atoi(val) && wpa_command(intf, "SET wps_corrupt_pkhash 1")) {
3344 send_resp(dut, conn, SIGMA_ERROR,
3345 "ErrorCode,Failed to enable FakePubKey");
3346 return 0;
3347 }
3348
3349 return 1;
3350}
3351
3352
3353static const char * ath_get_radio_name(const char *radio_name)
3354{
3355 if (radio_name == NULL)
3356 return "wifi0";
3357 if (strcmp(radio_name, "wifi1") == 0)
3358 return "wifi1";
3359 if (strcmp(radio_name, "wifi2") == 0)
3360 return "wifi2";
3361 return "wifi0";
3362}
3363
3364
3365static void ath_sta_set_txsp_stream(struct sigma_dut *dut, const char *intf,
3366 const char *val)
3367{
3368 char buf[60];
3369 unsigned int vht_mcsmap = 0;
3370 int txchainmask = 0;
3371 const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
3372
3373 if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
3374 if (dut->testbed_flag_txsp == 1) {
3375 vht_mcsmap = 0xfffc;
3376 dut->testbed_flag_txsp = 0;
3377 } else {
3378 vht_mcsmap = 0xfffe;
3379 }
3380 txchainmask = 1;
3381 } else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
3382 if (dut->testbed_flag_txsp == 1) {
3383 vht_mcsmap = 0xfff0;
3384 dut->testbed_flag_txsp = 0;
3385 } else {
3386 vht_mcsmap = 0xfffa;
3387 }
3388 txchainmask = 3;
3389 } else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
3390 if (dut->testbed_flag_txsp == 1) {
3391 vht_mcsmap = 0xffc0;
3392 dut->testbed_flag_txsp = 0;
3393 } else {
3394 vht_mcsmap = 0xffea;
3395 }
3396 txchainmask = 7;
3397 } else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
3398 if (dut->testbed_flag_txsp == 1) {
3399 vht_mcsmap = 0xff00;
3400 dut->testbed_flag_txsp = 0;
3401 } else {
3402 vht_mcsmap = 0xffaa;
3403 }
3404 txchainmask = 15;
3405 } else {
3406 if (dut->testbed_flag_txsp == 1) {
3407 vht_mcsmap = 0xffc0;
3408 dut->testbed_flag_txsp = 0;
3409 } else {
3410 vht_mcsmap = 0xffea;
3411 }
3412 }
3413
3414 if (txchainmask) {
3415 snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
3416 basedev, txchainmask);
3417 if (system(buf) != 0) {
3418 sigma_dut_print(dut, DUT_MSG_ERROR,
3419 "iwpriv txchainmask failed");
3420 }
3421 }
3422
3423 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
3424 intf, vht_mcsmap);
3425 if (system(buf) != 0) {
3426 sigma_dut_print(dut, DUT_MSG_ERROR,
3427 "iwpriv %s vht_mcsmap 0x%04x failed",
3428 intf, vht_mcsmap);
3429 }
3430}
3431
3432
3433static void ath_sta_set_rxsp_stream(struct sigma_dut *dut, const char *intf,
3434 const char *val)
3435{
3436 char buf[60];
3437 unsigned int vht_mcsmap = 0;
3438 int rxchainmask = 0;
3439 const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
3440
3441 if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
3442 if (dut->testbed_flag_rxsp == 1) {
3443 vht_mcsmap = 0xfffc;
3444 dut->testbed_flag_rxsp = 0;
3445 } else {
3446 vht_mcsmap = 0xfffe;
3447 }
3448 rxchainmask = 1;
3449 } else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
3450 if (dut->testbed_flag_rxsp == 1) {
3451 vht_mcsmap = 0xfff0;
3452 dut->testbed_flag_rxsp = 0;
3453 } else {
3454 vht_mcsmap = 0xfffa;
3455 }
3456 rxchainmask = 3;
3457 } else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
3458 if (dut->testbed_flag_rxsp == 1) {
3459 vht_mcsmap = 0xffc0;
3460 dut->testbed_flag_rxsp = 0;
3461 } else {
3462 vht_mcsmap = 0xffea;
3463 }
3464 rxchainmask = 7;
3465 } else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
3466 if (dut->testbed_flag_rxsp == 1) {
3467 vht_mcsmap = 0xff00;
3468 dut->testbed_flag_rxsp = 0;
3469 } else {
3470 vht_mcsmap = 0xffaa;
3471 }
3472 rxchainmask = 15;
3473 } else {
3474 if (dut->testbed_flag_rxsp == 1) {
3475 vht_mcsmap = 0xffc0;
3476 dut->testbed_flag_rxsp = 0;
3477 } else {
3478 vht_mcsmap = 0xffea;
3479 }
3480 }
3481
3482 if (rxchainmask) {
3483 snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
3484 basedev, rxchainmask);
3485 if (system(buf) != 0) {
3486 sigma_dut_print(dut, DUT_MSG_ERROR,
3487 "iwpriv rxchainmask failed");
3488 }
3489 }
3490
3491 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
3492 intf, vht_mcsmap);
3493 if (system(buf) != 0) {
3494 sigma_dut_print(dut, DUT_MSG_ERROR,
3495 "iwpriv %s vht_mcsmap 0x%04x",
3496 intf, vht_mcsmap);
3497 }
3498}
3499
3500
3501void ath_set_zero_crc(struct sigma_dut *dut, const char *val)
3502{
3503 if (strcasecmp(val, "enable") == 0) {
3504 if (system("athdiag --set --address=0x2a204 --and=0xbfffffff")
3505 != 0) {
3506 sigma_dut_print(dut, DUT_MSG_ERROR,
3507 "Disable BB_VHTSIGB_CRC_CALC failed");
3508 }
3509
3510 if (system("athdiag --set --address=0x2a204 --or=0x80000000")
3511 != 0) {
3512 sigma_dut_print(dut, DUT_MSG_ERROR,
3513 "Enable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
3514 }
3515 } else {
3516 if (system("athdiag --set --address=0x2a204 --and=0x7fffffff")
3517 != 0) {
3518 sigma_dut_print(dut, DUT_MSG_ERROR,
3519 "Disable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
3520 }
3521
3522 if (system("athdiag --set --address=0x2a204 --or=0x40000000")
3523 != 0) {
3524 sigma_dut_print(dut, DUT_MSG_ERROR,
3525 "Enable BB_VHTSIGB_CRC_CALC failed");
3526 }
3527 }
3528}
3529
3530
3531static int cmd_sta_set_wireless_common(const char *intf, struct sigma_dut *dut,
3532 struct sigma_conn *conn,
3533 struct sigma_cmd *cmd)
3534{
3535 const char *val;
3536 int ampdu = -1;
3537 char buf[30];
3538
3539 val = get_param(cmd, "40_INTOLERANT");
3540 if (val) {
3541 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3542 /* TODO: iwpriv ht40intol through wpa_supplicant */
3543 send_resp(dut, conn, SIGMA_ERROR,
3544 "ErrorCode,40_INTOLERANT not supported");
3545 return 0;
3546 }
3547 }
3548
3549 val = get_param(cmd, "ADDBA_REJECT");
3550 if (val) {
3551 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3552 /* reject any ADDBA with status "decline" */
3553 ampdu = 0;
3554 } else {
3555 /* accept ADDBA */
3556 ampdu = 1;
3557 }
3558 }
3559
3560 val = get_param(cmd, "AMPDU");
3561 if (val) {
3562 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
3563 /* enable AMPDU Aggregation */
3564 if (ampdu == 0) {
3565 send_resp(dut, conn, SIGMA_ERROR,
3566 "ErrorCode,Mismatch in "
3567 "addba_reject/ampdu - "
3568 "not supported");
3569 return 0;
3570 }
3571 ampdu = 1;
3572 } else {
3573 /* disable AMPDU Aggregation */
3574 if (ampdu == 1) {
3575 send_resp(dut, conn, SIGMA_ERROR,
3576 "ErrorCode,Mismatch in "
3577 "addba_reject/ampdu - "
3578 "not supported");
3579 return 0;
3580 }
3581 ampdu = 0;
3582 }
3583 }
3584
3585 if (ampdu >= 0) {
3586 sigma_dut_print(dut, DUT_MSG_DEBUG, "%s A-MPDU aggregation",
3587 ampdu ? "Enabling" : "Disabling");
3588 snprintf(buf, sizeof(buf), "SET ampdu %d", ampdu);
Deepak Dhamdhere80356cb2016-03-28 16:48:32 -07003589 if (wpa_command(intf, buf) < 0 &&
3590 iwpriv_sta_set_ampdu(dut, intf, ampdu) < 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003591 send_resp(dut, conn, SIGMA_ERROR,
3592 "ErrorCode,set aggr failed");
3593 return 0;
3594 }
3595 }
3596
3597 val = get_param(cmd, "AMSDU");
3598 if (val) {
3599 switch (get_driver_type()) {
3600 case DRIVER_ATHEROS:
3601 ath_sta_set_amsdu(dut, intf, val);
3602 break;
3603 default:
3604 if (strcmp(val, "1") == 0 ||
3605 strcasecmp(val, "Enable") == 0) {
3606 /* Enable AMSDU Aggregation */
3607 send_resp(dut, conn, SIGMA_ERROR,
3608 "ErrorCode,AMSDU aggregation not supported");
3609 return 0;
3610 }
3611 break;
3612 }
3613 }
3614
3615 val = get_param(cmd, "STBC_RX");
3616 if (val) {
3617 switch (get_driver_type()) {
3618 case DRIVER_ATHEROS:
3619 ath_sta_set_stbc(dut, intf, val);
3620 break;
Pradeep Reddy POTTETI4a1f6b32016-11-23 13:15:21 +05303621 case DRIVER_WCN:
3622 wcn_sta_set_stbc(dut, intf, val);
3623 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003624 default:
3625 send_resp(dut, conn, SIGMA_ERROR,
3626 "ErrorCode,STBC_RX not supported");
3627 return 0;
3628 }
3629 }
3630
3631 val = get_param(cmd, "WIDTH");
3632 if (val) {
3633 switch (get_driver_type()) {
3634 case DRIVER_WCN:
3635 if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
3636 send_resp(dut, conn, SIGMA_ERROR,
3637 "ErrorCode,Failed to set WIDTH");
3638 return 0;
3639 }
3640 break;
3641 case DRIVER_ATHEROS:
3642 if (ath_set_width(dut, conn, intf, val) < 0)
3643 return 0;
3644 break;
3645 default:
3646 sigma_dut_print(dut, DUT_MSG_ERROR,
3647 "Setting WIDTH not supported");
3648 break;
3649 }
3650 }
3651
3652 val = get_param(cmd, "SMPS");
3653 if (val) {
3654 /* TODO: Dynamic/0, Static/1, No Limit/2 */
3655 send_resp(dut, conn, SIGMA_ERROR,
3656 "ErrorCode,SMPS not supported");
3657 return 0;
3658 }
3659
3660 val = get_param(cmd, "TXSP_STREAM");
3661 if (val) {
3662 switch (get_driver_type()) {
3663 case DRIVER_WCN:
3664 if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
3665 send_resp(dut, conn, SIGMA_ERROR,
3666 "ErrorCode,Failed to set TXSP_STREAM");
3667 return 0;
3668 }
3669 break;
3670 case DRIVER_ATHEROS:
3671 ath_sta_set_txsp_stream(dut, intf, val);
3672 break;
3673 default:
3674 sigma_dut_print(dut, DUT_MSG_ERROR,
3675 "Setting TXSP_STREAM not supported");
3676 break;
3677 }
3678 }
3679
3680 val = get_param(cmd, "RXSP_STREAM");
3681 if (val) {
3682 switch (get_driver_type()) {
3683 case DRIVER_WCN:
3684 if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
3685 send_resp(dut, conn, SIGMA_ERROR,
3686 "ErrorCode,Failed to set RXSP_STREAM");
3687 return 0;
3688 }
3689 break;
3690 case DRIVER_ATHEROS:
3691 ath_sta_set_rxsp_stream(dut, intf, val);
3692 break;
3693 default:
3694 sigma_dut_print(dut, DUT_MSG_ERROR,
3695 "Setting RXSP_STREAM not supported");
3696 break;
3697 }
3698 }
3699
3700 val = get_param(cmd, "DYN_BW_SGNL");
3701 if (val) {
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003702 switch (get_driver_type()) {
3703 case DRIVER_WCN:
Peng Xuc59afd32016-11-21 15:01:11 -08003704 if (strcasecmp(val, "enable") == 0) {
3705 snprintf(buf, sizeof(buf),
3706 "iwpriv %s cwmenable 1", intf);
3707 if (system(buf) != 0) {
3708 sigma_dut_print(dut, DUT_MSG_ERROR,
3709 "iwpriv cwmenable 1 failed");
3710 return 0;
3711 }
3712 } else if (strcasecmp(val, "disable") == 0) {
3713 snprintf(buf, sizeof(buf),
3714 "iwpriv %s cwmenable 0", intf);
3715 if (system(buf) != 0) {
3716 sigma_dut_print(dut, DUT_MSG_ERROR,
3717 "iwpriv cwmenable 0 failed");
3718 return 0;
3719 }
3720 } else {
3721 sigma_dut_print(dut, DUT_MSG_ERROR,
3722 "Unsupported DYN_BW_SGL");
3723 }
3724
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003725 snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
3726 if (system(buf) != 0) {
3727 sigma_dut_print(dut, DUT_MSG_ERROR,
3728 "Failed to set cts_cbw in DYN_BW_SGNL");
3729 return 0;
3730 }
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003731 break;
3732 case DRIVER_ATHEROS:
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08003733 novap_reset(dut, intf);
Priyadharshini Gowthaman818afef2015-11-09 13:28:15 -08003734 ath_config_dyn_bw_sig(dut, intf, val);
3735 break;
3736 default:
3737 sigma_dut_print(dut, DUT_MSG_ERROR,
3738 "Failed to set DYN_BW_SGNL");
3739 break;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003740 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003741 }
3742
3743 val = get_param(cmd, "RTS_FORCE");
3744 if (val) {
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08003745 novap_reset(dut, intf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003746 if (strcasecmp(val, "Enable") == 0) {
3747 snprintf(buf, sizeof(buf), "iwconfig %s rts 64", intf);
Priyadharshini Gowthamanabdb2122015-11-17 11:52:19 +02003748 if (system(buf) != 0) {
3749 sigma_dut_print(dut, DUT_MSG_ERROR,
3750 "Failed to set RTS_FORCE 64");
3751 }
priyadharshini gowthaman270870e2015-12-09 10:10:23 -08003752 snprintf(buf, sizeof(buf),
3753 "wifitool %s beeliner_fw_test 100 1", intf);
3754 if (system(buf) != 0) {
3755 sigma_dut_print(dut, DUT_MSG_ERROR,
3756 "wifitool beeliner_fw_test 100 1 failed");
3757 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003758 } else if (strcasecmp(val, "Disable") == 0) {
3759 snprintf(buf, sizeof(buf), "iwconfig %s rts 2347",
3760 intf);
Priyadharshini Gowthamanabdb2122015-11-17 11:52:19 +02003761 if (system(buf) != 0) {
3762 sigma_dut_print(dut, DUT_MSG_ERROR,
3763 "Failed to set RTS_FORCE 2347");
3764 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003765 } else {
3766 send_resp(dut, conn, SIGMA_ERROR,
3767 "ErrorCode,RTS_FORCE value not supported");
3768 return 0;
3769 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02003770 }
3771
3772 val = get_param(cmd, "CTS_WIDTH");
3773 if (val) {
3774 switch (get_driver_type()) {
3775 case DRIVER_WCN:
3776 if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
3777 send_resp(dut, conn, SIGMA_ERROR,
3778 "ErrorCode,Failed to set CTS_WIDTH");
3779 return 0;
3780 }
3781 break;
3782 case DRIVER_ATHEROS:
3783 ath_set_cts_width(dut, intf, val);
3784 break;
3785 default:
3786 sigma_dut_print(dut, DUT_MSG_ERROR,
3787 "Setting CTS_WIDTH not supported");
3788 break;
3789 }
3790 }
3791
3792 val = get_param(cmd, "BW_SGNL");
3793 if (val) {
3794 if (strcasecmp(val, "Enable") == 0) {
3795 snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1",
3796 intf);
3797 } else if (strcasecmp(val, "Disable") == 0) {
3798 /* TODO: Disable */
3799 buf[0] = '\0';
3800 } else {
3801 send_resp(dut, conn, SIGMA_ERROR,
3802 "ErrorCode,BW_SGNL value not supported");
3803 return 0;
3804 }
3805
3806 if (buf[0] != '\0' && system(buf) != 0) {
3807 sigma_dut_print(dut, DUT_MSG_ERROR,
3808 "Failed to set BW_SGNL");
3809 }
3810 }
3811
3812 val = get_param(cmd, "Band");
3813 if (val) {
3814 if (strcmp(val, "2.4") == 0 || strcmp(val, "5") == 0) {
3815 /* STA supports all bands by default */
3816 } else {
3817 send_resp(dut, conn, SIGMA_ERROR,
3818 "ErrorCode,Unsupported Band");
3819 return 0;
3820 }
3821 }
3822
3823 val = get_param(cmd, "zero_crc");
3824 if (val) {
3825 switch (get_driver_type()) {
3826 case DRIVER_ATHEROS:
3827 ath_set_zero_crc(dut, val);
3828 break;
3829 default:
3830 break;
3831 }
3832 }
3833
3834 return 1;
3835}
3836
3837
3838static int sta_set_60g_common(struct sigma_dut *dut, struct sigma_conn *conn,
3839 struct sigma_cmd *cmd)
3840{
3841 const char *val;
3842 char buf[100];
3843
3844 val = get_param(cmd, "MSDUSize");
3845 if (val) {
3846 int mtu;
3847
3848 dut->amsdu_size = atoi(val);
3849 if (dut->amsdu_size > IEEE80211_MAX_DATA_LEN_DMG ||
3850 dut->amsdu_size < IEEE80211_SNAP_LEN_DMG) {
3851 sigma_dut_print(dut, DUT_MSG_ERROR,
3852 "MSDUSize %d is above max %d or below min %d",
3853 dut->amsdu_size,
3854 IEEE80211_MAX_DATA_LEN_DMG,
3855 IEEE80211_SNAP_LEN_DMG);
3856 dut->amsdu_size = 0;
3857 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3858 }
3859
3860 mtu = dut->amsdu_size - IEEE80211_SNAP_LEN_DMG;
3861 sigma_dut_print(dut, DUT_MSG_DEBUG,
3862 "Setting amsdu_size to %d", mtu);
3863 snprintf(buf, sizeof(buf), "ifconfig %s mtu %d",
3864 get_station_ifname(), mtu);
3865
3866 if (system(buf) != 0) {
3867 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set %s",
3868 buf);
3869 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3870 }
3871 }
3872
3873 val = get_param(cmd, "BAckRcvBuf");
3874 if (val) {
3875 dut->back_rcv_buf = atoi(val);
3876 if (dut->back_rcv_buf == 0) {
3877 sigma_dut_print(dut, DUT_MSG_ERROR,
3878 "Failed to convert %s or value is 0",
3879 val);
3880 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3881 }
3882
3883 sigma_dut_print(dut, DUT_MSG_DEBUG,
3884 "Setting BAckRcvBuf to %s", val);
3885 }
3886
3887 return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
3888}
3889
3890
3891static int sta_pcp_start(struct sigma_dut *dut, struct sigma_conn *conn,
3892 struct sigma_cmd *cmd)
3893{
3894 int net_id;
3895 char *ifname;
3896 const char *val;
3897 char buf[100];
3898
3899 dut->mode = SIGMA_MODE_STATION;
3900 ifname = get_main_ifname();
3901 if (wpa_command(ifname, "PING") != 0) {
3902 sigma_dut_print(dut, DUT_MSG_ERROR, "Supplicant not running");
3903 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3904 }
3905
3906 wpa_command(ifname, "FLUSH");
3907 net_id = add_network_common(dut, conn, ifname, cmd);
3908 if (net_id < 0) {
3909 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add network");
3910 return net_id;
3911 }
3912
3913 /* TODO: mode=2 for the AP; in the future, replace for mode PCP */
3914 if (set_network(ifname, net_id, "mode", "2") < 0) {
3915 sigma_dut_print(dut, DUT_MSG_ERROR,
3916 "Failed to set supplicant network mode");
3917 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3918 }
3919
3920 sigma_dut_print(dut, DUT_MSG_DEBUG,
3921 "Supplicant set network with mode 2");
3922
3923 val = get_param(cmd, "Security");
3924 if (val && strcasecmp(val, "OPEN") == 0) {
3925 dut->ap_key_mgmt = AP_OPEN;
3926 if (set_network(ifname, net_id, "key_mgmt", "NONE") < 0) {
3927 sigma_dut_print(dut, DUT_MSG_ERROR,
3928 "Failed to set supplicant to %s security",
3929 val);
3930 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3931 }
3932 } else if (val && strcasecmp(val, "WPA2-PSK") == 0) {
3933 dut->ap_key_mgmt = AP_WPA2_PSK;
3934 if (set_network(ifname, net_id, "key_mgmt", "WPA-PSK") < 0) {
3935 sigma_dut_print(dut, DUT_MSG_ERROR,
3936 "Failed to set supplicant to %s security",
3937 val);
3938 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3939 }
3940
3941 if (set_network(ifname, net_id, "proto", "RSN") < 0) {
3942 sigma_dut_print(dut, DUT_MSG_ERROR,
3943 "Failed to set supplicant to proto RSN");
3944 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3945 }
3946 } else if (val) {
3947 sigma_dut_print(dut, DUT_MSG_ERROR,
3948 "Requested Security %s is not supported on 60GHz",
3949 val);
3950 return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
3951 }
3952
3953 val = get_param(cmd, "Encrypt");
3954 if (val && strcasecmp(val, "AES-GCMP") == 0) {
3955 if (set_network(ifname, net_id, "pairwise", "GCMP") < 0) {
3956 sigma_dut_print(dut, DUT_MSG_ERROR,
3957 "Failed to set supplicant to pairwise GCMP");
3958 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3959 }
3960 if (set_network(ifname, net_id, "group", "GCMP") < 0) {
3961 sigma_dut_print(dut, DUT_MSG_ERROR,
3962 "Failed to set supplicant to group GCMP");
3963 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3964 }
3965 } else if (val) {
3966 sigma_dut_print(dut, DUT_MSG_ERROR,
3967 "Requested Encrypt %s is not supported on 60 GHz",
3968 val);
3969 return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
3970 }
3971
3972 val = get_param(cmd, "PSK");
3973 if (val && set_network_quoted(ifname, net_id, "psk", val) < 0) {
3974 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set psk %s",
3975 val);
3976 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3977 }
3978
3979 /* Convert 60G channel to freq */
3980 switch (dut->ap_channel) {
3981 case 1:
3982 val = "58320";
3983 break;
3984 case 2:
3985 val = "60480";
3986 break;
3987 case 3:
3988 val = "62640";
3989 break;
3990 default:
3991 sigma_dut_print(dut, DUT_MSG_ERROR,
3992 "Failed to configure channel %d. Not supported",
3993 dut->ap_channel);
3994 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
3995 }
3996
3997 if (set_network(ifname, net_id, "frequency", val) < 0) {
3998 sigma_dut_print(dut, DUT_MSG_ERROR,
3999 "Failed to set supplicant network frequency");
4000 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
4001 }
4002
4003 sigma_dut_print(dut, DUT_MSG_DEBUG,
4004 "Supplicant set network with frequency");
4005
4006 snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", net_id);
4007 if (wpa_command(ifname, buf) < 0) {
4008 sigma_dut_print(dut, DUT_MSG_INFO,
4009 "Failed to select network id %d on %s",
4010 net_id, ifname);
4011 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
4012 }
4013
4014 sigma_dut_print(dut, DUT_MSG_DEBUG, "Selected network");
4015
4016 return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
4017}
4018
4019
Lior David67543f52017-01-03 19:04:22 +02004020static int wil6210_set_abft_len(struct sigma_dut *dut, int abft_len)
4021{
4022 char buf[128], fname[128];
4023 FILE *f;
4024
4025 if (wil6210_get_debugfs_dir(dut, buf, sizeof(buf))) {
4026 sigma_dut_print(dut, DUT_MSG_ERROR,
4027 "failed to get wil6210 debugfs dir");
4028 return -1;
4029 }
4030
4031 snprintf(fname, sizeof(fname), "%s/abft_len", buf);
4032 f = fopen(fname, "w");
4033 if (!f) {
4034 sigma_dut_print(dut, DUT_MSG_ERROR,
4035 "failed to open: %s", fname);
4036 return -1;
4037 }
4038
4039 fprintf(f, "%d\n", abft_len);
4040 fclose(f);
4041
4042 return 0;
4043}
4044
4045
4046static int sta_set_60g_abft_len(struct sigma_dut *dut, struct sigma_conn *conn,
4047 int abft_len)
4048{
4049 switch (get_driver_type()) {
4050 case DRIVER_WIL6210:
4051 return wil6210_set_abft_len(dut, abft_len);
4052 default:
4053 sigma_dut_print(dut, DUT_MSG_ERROR,
4054 "set abft_len not supported");
4055 return -1;
4056 }
4057}
4058
4059
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004060static int sta_set_60g_pcp(struct sigma_dut *dut, struct sigma_conn *conn,
4061 struct sigma_cmd *cmd)
4062{
4063 const char *val;
Lior David67543f52017-01-03 19:04:22 +02004064 unsigned int abft_len = 1; /* default is one slot */
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004065
4066 if (dut->dev_role != DEVROLE_PCP) {
4067 send_resp(dut, conn, SIGMA_INVALID,
4068 "ErrorCode,Invalid DevRole");
4069 return 0;
4070 }
4071
4072 val = get_param(cmd, "SSID");
4073 if (val) {
4074 if (strlen(val) > sizeof(dut->ap_ssid) - 1) {
4075 send_resp(dut, conn, SIGMA_INVALID,
4076 "ErrorCode,Invalid SSID");
4077 return -1;
4078 }
4079
4080 strncpy(dut->ap_ssid, val, sizeof(dut->ap_ssid));
4081 }
4082
4083 val = get_param(cmd, "CHANNEL");
4084 if (val) {
4085 const char *pos;
4086
4087 dut->ap_channel = atoi(val);
4088 pos = strchr(val, ';');
4089 if (pos) {
4090 pos++;
4091 dut->ap_channel_1 = atoi(pos);
4092 }
4093 }
4094
4095 switch (dut->ap_channel) {
4096 case 1:
4097 case 2:
4098 case 3:
4099 break;
4100 default:
4101 sigma_dut_print(dut, DUT_MSG_ERROR,
4102 "Channel %d is not supported", dut->ap_channel);
4103 send_resp(dut, conn, SIGMA_ERROR,
4104 "Requested channel is not supported");
4105 return -1;
4106 }
4107
4108 val = get_param(cmd, "BCNINT");
4109 if (val)
4110 dut->ap_bcnint = atoi(val);
4111
4112
4113 val = get_param(cmd, "ExtSchIE");
4114 if (val) {
4115 send_resp(dut, conn, SIGMA_ERROR,
4116 "ErrorCode,ExtSchIE is not supported yet");
4117 return -1;
4118 }
4119
4120 val = get_param(cmd, "AllocType");
4121 if (val) {
4122 send_resp(dut, conn, SIGMA_ERROR,
4123 "ErrorCode,AllocType is not supported yet");
4124 return -1;
4125 }
4126
4127 val = get_param(cmd, "PercentBI");
4128 if (val) {
4129 send_resp(dut, conn, SIGMA_ERROR,
4130 "ErrorCode,PercentBI is not supported yet");
4131 return -1;
4132 }
4133
4134 val = get_param(cmd, "CBAPOnly");
4135 if (val) {
4136 send_resp(dut, conn, SIGMA_ERROR,
4137 "ErrorCode,CBAPOnly is not supported yet");
4138 return -1;
4139 }
4140
4141 val = get_param(cmd, "AMPDU");
4142 if (val) {
4143 if (strcasecmp(val, "Enable") == 0)
4144 dut->ap_ampdu = 1;
4145 else if (strcasecmp(val, "Disable") == 0)
4146 dut->ap_ampdu = 2;
4147 else {
4148 send_resp(dut, conn, SIGMA_ERROR,
4149 "ErrorCode,AMPDU value is not Enable nor Disabled");
4150 return -1;
4151 }
4152 }
4153
4154 val = get_param(cmd, "AMSDU");
4155 if (val) {
4156 if (strcasecmp(val, "Enable") == 0)
4157 dut->ap_amsdu = 1;
4158 else if (strcasecmp(val, "Disable") == 0)
4159 dut->ap_amsdu = 2;
4160 }
4161
4162 val = get_param(cmd, "NumMSDU");
4163 if (val) {
4164 send_resp(dut, conn, SIGMA_ERROR,
4165 "ErrorCode, NumMSDU is not supported yet");
4166 return -1;
4167 }
4168
4169 val = get_param(cmd, "ABFTLRang");
4170 if (val) {
4171 sigma_dut_print(dut, DUT_MSG_DEBUG,
Lior David67543f52017-01-03 19:04:22 +02004172 "ABFTLRang parameter %s", val);
4173 if (strcmp(val, "Gt1") == 0)
4174 abft_len = 2; /* 2 slots in this case */
4175 }
4176
4177 if (sta_set_60g_abft_len(dut, conn, abft_len)) {
4178 send_resp(dut, conn, SIGMA_ERROR,
4179 "ErrorCode, Can't set ABFT length");
4180 return -1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004181 }
4182
4183 if (sta_pcp_start(dut, conn, cmd) < 0) {
4184 send_resp(dut, conn, SIGMA_ERROR,
4185 "ErrorCode, Can't start PCP role");
4186 return -1;
4187 }
4188
4189 return sta_set_60g_common(dut, conn, cmd);
4190}
4191
4192
4193static int sta_set_60g_sta(struct sigma_dut *dut, struct sigma_conn *conn,
4194 struct sigma_cmd *cmd)
4195{
4196 const char *val = get_param(cmd, "DiscoveryMode");
4197
4198 if (dut->dev_role != DEVROLE_STA) {
4199 send_resp(dut, conn, SIGMA_INVALID,
4200 "ErrorCode,Invalid DevRole");
4201 return 0;
4202 }
4203
4204 if (val) {
4205 sigma_dut_print(dut, DUT_MSG_DEBUG, "Discovery: %s", val);
4206 /* Ignore Discovery mode till Driver expose API. */
4207#if 0
4208 if (strcasecmp(val, "1") == 0) {
4209 send_resp(dut, conn, SIGMA_INVALID,
4210 "ErrorCode,DiscoveryMode 1 not supported");
4211 return 0;
4212 }
4213
4214 if (strcasecmp(val, "0") == 0) {
4215 /* OK */
4216 } else {
4217 send_resp(dut, conn, SIGMA_INVALID,
4218 "ErrorCode,DiscoveryMode not supported");
4219 return 0;
4220 }
4221#endif
4222 }
4223
4224 if (start_sta_mode(dut) != 0)
4225 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
4226 return sta_set_60g_common(dut, conn, cmd);
4227}
4228
4229
4230static int cmd_sta_disconnect(struct sigma_dut *dut, struct sigma_conn *conn,
4231 struct sigma_cmd *cmd)
4232{
4233 const char *intf = get_param(cmd, "Interface");
4234 disconnect_station(dut);
4235 /* Try to ignore old scan results to avoid HS 2.0R2 test case failures
4236 * due to cached results. */
4237 wpa_command(intf, "SET ignore_old_scan_res 1");
4238 wpa_command(intf, "BSS_FLUSH");
4239 return 1;
4240}
4241
4242
4243static int cmd_sta_reassoc(struct sigma_dut *dut, struct sigma_conn *conn,
4244 struct sigma_cmd *cmd)
4245{
4246 const char *intf = get_param(cmd, "Interface");
4247 const char *bssid = get_param(cmd, "bssid");
4248 const char *val = get_param(cmd, "CHANNEL");
4249 struct wpa_ctrl *ctrl;
4250 char buf[100];
4251 int res;
4252 int chan = 0;
4253
4254 if (bssid == NULL) {
4255 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing bssid "
4256 "argument");
4257 return 0;
4258 }
4259
4260 if (val)
4261 chan = atoi(val);
4262
4263 if (wifi_chip_type != DRIVER_WCN && wifi_chip_type != DRIVER_AR6003) {
4264 /* The current network may be from sta_associate or
4265 * sta_hs2_associate
4266 */
4267 if (set_network(intf, dut->infra_network_id, "bssid", bssid) <
4268 0 ||
4269 set_network(intf, 0, "bssid", bssid) < 0)
4270 return -2;
4271 }
4272
4273 ctrl = open_wpa_mon(intf);
4274 if (ctrl == NULL) {
4275 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
4276 "wpa_supplicant monitor connection");
4277 return -1;
4278 }
4279
4280 if (wifi_chip_type == DRIVER_WCN) {
4281#ifdef ANDROID
4282 if (set_network(intf, dut->infra_network_id, "bssid", "any")
4283 < 0) {
4284 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
4285 "bssid to any during FASTREASSOC");
4286 return -2;
4287 }
4288 res = snprintf(buf, sizeof(buf), "DRIVER FASTREASSOC %s %d",
4289 bssid, chan);
4290 if (res > 0 && res < (int) sizeof(buf))
4291 res = wpa_command(intf, buf);
4292
4293 if (res < 0 || res >= (int) sizeof(buf)) {
4294 send_resp(dut, conn, SIGMA_ERROR,
4295 "errorCode,Failed to run DRIVER FASTREASSOC");
4296 wpa_ctrl_detach(ctrl);
4297 wpa_ctrl_close(ctrl);
4298 return 0;
4299 }
4300#else /* ANDROID */
4301 sigma_dut_print(dut, DUT_MSG_DEBUG,
4302 "Reassoc using iwpriv - skip chan=%d info",
4303 chan);
4304 snprintf(buf, sizeof(buf), "iwpriv %s reassoc", intf);
4305 if (system(buf) != 0) {
4306 sigma_dut_print(dut, DUT_MSG_ERROR, "%s failed", buf);
4307 wpa_ctrl_detach(ctrl);
4308 wpa_ctrl_close(ctrl);
4309 return 0;
4310 }
4311#endif /* ANDROID */
4312 sigma_dut_print(dut, DUT_MSG_INFO,
4313 "sta_reassoc: Run %s successful", buf);
4314 } else if (wpa_command(intf, "REASSOCIATE")) {
4315 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
4316 "request reassociation");
4317 wpa_ctrl_detach(ctrl);
4318 wpa_ctrl_close(ctrl);
4319 return 0;
4320 }
4321
4322 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
4323 buf, sizeof(buf));
4324
4325 wpa_ctrl_detach(ctrl);
4326 wpa_ctrl_close(ctrl);
4327
4328 if (res < 0) {
4329 sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
4330 return -1;
4331 }
4332
4333 return 1;
4334}
4335
4336
4337static void hs2_clear_credentials(const char *intf)
4338{
4339 wpa_command(intf, "REMOVE_CRED all");
4340}
4341
4342
Lior Davidcc88b562017-01-03 18:52:09 +02004343#ifdef __linux__
4344static int wil6210_get_aid(struct sigma_dut *dut, const char *bssid,
4345 unsigned int *aid)
4346{
Lior David0fe101e2017-03-09 16:09:50 +02004347 const char *pattern = "AID[ \t]+([0-9]+)";
Lior Davidcc88b562017-01-03 18:52:09 +02004348
Lior David0fe101e2017-03-09 16:09:50 +02004349 return wil6210_get_sta_info_field(dut, bssid, pattern, aid);
Lior Davidcc88b562017-01-03 18:52:09 +02004350}
4351#endif /* __linux__ */
4352
4353
4354static int sta_get_aid_60g(struct sigma_dut *dut, const char *bssid,
4355 unsigned int *aid)
4356{
4357 switch (get_driver_type()) {
4358#ifdef __linux__
4359 case DRIVER_WIL6210:
4360 return wil6210_get_aid(dut, bssid, aid);
4361#endif /* __linux__ */
4362 default:
4363 sigma_dut_print(dut, DUT_MSG_ERROR, "get AID not supported");
4364 return -1;
4365 }
4366}
4367
4368
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004369static int sta_get_parameter_60g(struct sigma_dut *dut, struct sigma_conn *conn,
4370 struct sigma_cmd *cmd)
4371{
4372 char buf[MAX_CMD_LEN];
4373 char bss_list[MAX_CMD_LEN];
4374 const char *parameter = get_param(cmd, "Parameter");
4375
4376 if (parameter == NULL)
4377 return -1;
4378
Lior Davidcc88b562017-01-03 18:52:09 +02004379 if (strcasecmp(parameter, "AID") == 0) {
4380 unsigned int aid = 0;
4381 char bssid[20];
4382
4383 if (get_wpa_status(get_station_ifname(), "bssid",
4384 bssid, sizeof(bssid)) < 0) {
4385 sigma_dut_print(dut, DUT_MSG_ERROR,
4386 "could not get bssid");
4387 return -2;
4388 }
4389
4390 if (sta_get_aid_60g(dut, bssid, &aid))
4391 return -2;
4392
4393 snprintf(buf, sizeof(buf), "aid,%d", aid);
4394 sigma_dut_print(dut, DUT_MSG_INFO, "%s", buf);
4395 send_resp(dut, conn, SIGMA_COMPLETE, buf);
4396 return 0;
4397 }
4398
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004399 if (strcasecmp(parameter, "DiscoveredDevList") == 0) {
4400 char *bss_line;
4401 char *bss_id = NULL;
4402 const char *ifname = get_param(cmd, "Interface");
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304403 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004404
4405 if (ifname == NULL) {
4406 sigma_dut_print(dut, DUT_MSG_INFO,
4407 "For get DiscoveredDevList need Interface name.");
4408 return -1;
4409 }
4410
4411 /*
4412 * Use "BSS RANGE=ALL MASK=0x2" which provides a list
4413 * of BSSIDs in "bssid=<BSSID>\n"
4414 */
4415 if (wpa_command_resp(ifname, "BSS RANGE=ALL MASK=0x2",
4416 bss_list,
4417 sizeof(bss_list)) < 0) {
4418 sigma_dut_print(dut, DUT_MSG_ERROR,
4419 "Failed to get bss list");
4420 return -1;
4421 }
4422
4423 sigma_dut_print(dut, DUT_MSG_DEBUG,
4424 "bss list for ifname:%s is:%s",
4425 ifname, bss_list);
4426
4427 snprintf(buf, sizeof(buf), "DeviceList");
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304428 bss_line = strtok_r(bss_list, "\n", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004429 while (bss_line) {
4430 if (sscanf(bss_line, "bssid=%ms", &bss_id) > 0 &&
4431 bss_id) {
4432 int len;
4433
4434 len = snprintf(buf + strlen(buf),
4435 sizeof(buf) - strlen(buf),
4436 ",%s", bss_id);
4437 free(bss_id);
4438 bss_id = NULL;
4439 if (len < 0) {
4440 sigma_dut_print(dut,
4441 DUT_MSG_ERROR,
4442 "Failed to read BSSID");
4443 send_resp(dut, conn, SIGMA_ERROR,
4444 "ErrorCode,Failed to read BSS ID");
4445 return 0;
4446 }
4447
4448 if ((size_t) len >= sizeof(buf) - strlen(buf)) {
4449 sigma_dut_print(dut,
4450 DUT_MSG_ERROR,
4451 "Response buf too small for list");
4452 send_resp(dut, conn,
4453 SIGMA_ERROR,
4454 "ErrorCode,Response buf too small for list");
4455 return 0;
4456 }
4457 }
4458
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304459 bss_line = strtok_r(NULL, "\n", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004460 }
4461
4462 sigma_dut_print(dut, DUT_MSG_INFO, "DiscoveredDevList is %s",
4463 buf);
4464 send_resp(dut, conn, SIGMA_COMPLETE, buf);
4465 return 0;
4466 }
4467
4468 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4469 return 0;
4470}
4471
4472
4473static int cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
4474 struct sigma_cmd *cmd)
4475{
4476 const char *program = get_param(cmd, "Program");
4477
4478 if (program == NULL)
4479 return -1;
4480
4481 if (strcasecmp(program, "P2PNFC") == 0)
4482 return p2p_cmd_sta_get_parameter(dut, conn, cmd);
4483
4484 if (strcasecmp(program, "60ghz") == 0)
4485 return sta_get_parameter_60g(dut, conn, cmd);
4486
4487#ifdef ANDROID_NAN
4488 if (strcasecmp(program, "NAN") == 0)
Amarnath Hullur Subramanyam1854ec62016-08-11 19:29:35 -07004489 return nan_cmd_sta_get_parameter(dut, conn, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004490#endif /* ANDROID_NAN */
4491
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004492#ifdef MIRACAST
4493 if (strcasecmp(program, "WFD") == 0 ||
4494 strcasecmp(program, "DisplayR2") == 0)
4495 return miracast_cmd_sta_get_parameter(dut, conn, cmd);
4496#endif /* MIRACAST */
4497
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004498 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4499 return 0;
4500}
4501
4502
4503static void sta_reset_default_ath(struct sigma_dut *dut, const char *intf,
4504 const char *type)
4505{
4506 char buf[100];
4507
4508 if (dut->program == PROGRAM_VHT) {
4509 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
4510 if (system(buf) != 0) {
4511 sigma_dut_print(dut, DUT_MSG_ERROR,
4512 "iwpriv %s chwidth failed", intf);
4513 }
4514
4515 snprintf(buf, sizeof(buf), "iwpriv %s mode 11ACVHT80", intf);
4516 if (system(buf) != 0) {
4517 sigma_dut_print(dut, DUT_MSG_ERROR,
4518 "iwpriv %s mode 11ACVHT80 failed",
4519 intf);
4520 }
4521
4522 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs -1", intf);
4523 if (system(buf) != 0) {
4524 sigma_dut_print(dut, DUT_MSG_ERROR,
4525 "iwpriv %s vhtmcs -1 failed", intf);
4526 }
4527 }
4528
4529 if (dut->program == PROGRAM_HT) {
4530 snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
4531 if (system(buf) != 0) {
4532 sigma_dut_print(dut, DUT_MSG_ERROR,
4533 "iwpriv %s chwidth failed", intf);
4534 }
4535
4536 snprintf(buf, sizeof(buf), "iwpriv %s mode 11naht40", intf);
4537 if (system(buf) != 0) {
4538 sigma_dut_print(dut, DUT_MSG_ERROR,
4539 "iwpriv %s mode 11naht40 failed",
4540 intf);
4541 }
4542
4543 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0", intf);
4544 if (system(buf) != 0) {
4545 sigma_dut_print(dut, DUT_MSG_ERROR,
4546 "iwpriv set11NRates failed");
4547 }
4548 }
4549
4550 if (dut->program == PROGRAM_VHT || dut->program == PROGRAM_HT) {
4551 snprintf(buf, sizeof(buf), "iwpriv %s powersave 0", intf);
4552 if (system(buf) != 0) {
4553 sigma_dut_print(dut, DUT_MSG_ERROR,
4554 "disabling powersave failed");
4555 }
4556
4557 /* Reset CTS width */
4558 snprintf(buf, sizeof(buf), "wifitool %s beeliner_fw_test 54 0",
4559 intf);
4560 if (system(buf) != 0) {
4561 sigma_dut_print(dut, DUT_MSG_ERROR,
4562 "wifitool %s beeliner_fw_test 54 0 failed",
4563 intf);
4564 }
4565
4566 /* Enable Dynamic Bandwidth signalling by default */
4567 snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1", intf);
4568 if (system(buf) != 0) {
4569 sigma_dut_print(dut, DUT_MSG_ERROR,
4570 "iwpriv %s cwmenable 1 failed", intf);
4571 }
4572
4573 snprintf(buf, sizeof(buf), "iwconfig %s rts 2347", intf);
4574 if (system(buf) != 0) {
4575 sigma_dut_print(dut, DUT_MSG_ERROR,
4576 "iwpriv rts failed");
4577 }
4578 }
4579
4580 if (type && strcasecmp(type, "Testbed") == 0) {
4581 dut->testbed_flag_txsp = 1;
4582 dut->testbed_flag_rxsp = 1;
4583 /* STA has to set spatial stream to 2 per Appendix H */
4584 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0xfff0", intf);
4585 if (system(buf) != 0) {
4586 sigma_dut_print(dut, DUT_MSG_ERROR,
4587 "iwpriv vht_mcsmap failed");
4588 }
4589
4590 /* Disable LDPC per Appendix H */
4591 snprintf(buf, sizeof(buf), "iwpriv %s ldpc 0", intf);
4592 if (system(buf) != 0) {
4593 sigma_dut_print(dut, DUT_MSG_ERROR,
4594 "iwpriv %s ldpc 0 failed", intf);
4595 }
4596
4597 snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
4598 if (system(buf) != 0) {
4599 sigma_dut_print(dut, DUT_MSG_ERROR,
4600 "iwpriv amsdu failed");
4601 }
4602
4603 /* TODO: Disable STBC 2x1 transmit and receive */
4604 snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc 0", intf);
4605 if (system(buf) != 0) {
4606 sigma_dut_print(dut, DUT_MSG_ERROR,
4607 "Disable tx_stbc 0 failed");
4608 }
4609
4610 snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc 0", intf);
4611 if (system(buf) != 0) {
4612 sigma_dut_print(dut, DUT_MSG_ERROR,
4613 "Disable rx_stbc 0 failed");
4614 }
4615
4616 /* STA has to disable Short GI per Appendix H */
4617 snprintf(buf, sizeof(buf), "iwpriv %s shortgi 0", intf);
4618 if (system(buf) != 0) {
4619 sigma_dut_print(dut, DUT_MSG_ERROR,
4620 "iwpriv %s shortgi 0 failed", intf);
4621 }
4622 }
4623
4624 if (type && strcasecmp(type, "DUT") == 0) {
4625 snprintf(buf, sizeof(buf), "iwpriv %s nss 3", intf);
4626 if (system(buf) != 0) {
4627 sigma_dut_print(dut, DUT_MSG_ERROR,
4628 "iwpriv %s nss 3 failed", intf);
4629 }
4630
4631 snprintf(buf, sizeof(buf), "iwpriv %s shortgi 1", intf);
4632 if (system(buf) != 0) {
4633 sigma_dut_print(dut, DUT_MSG_ERROR,
4634 "iwpriv %s shortgi 1 failed", intf);
4635 }
4636 }
4637}
4638
4639
4640static int cmd_sta_reset_default(struct sigma_dut *dut,
4641 struct sigma_conn *conn,
4642 struct sigma_cmd *cmd)
4643{
4644 int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn,
4645 struct sigma_cmd *cmd);
4646 const char *intf = get_param(cmd, "Interface");
4647 const char *type;
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004648 const char *program = get_param(cmd, "program");
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004649
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004650 if (!program)
4651 program = get_param(cmd, "prog");
4652 dut->program = sigma_program_to_enum(program);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004653 dut->device_type = STA_unknown;
4654 type = get_param(cmd, "type");
4655 if (type && strcasecmp(type, "Testbed") == 0)
4656 dut->device_type = STA_testbed;
4657 if (type && strcasecmp(type, "DUT") == 0)
4658 dut->device_type = STA_dut;
4659
4660 if (dut->program == PROGRAM_TDLS) {
4661 /* Clear TDLS testing mode */
4662 wpa_command(intf, "SET tdls_disabled 0");
4663 wpa_command(intf, "SET tdls_testing 0");
4664 dut->no_tpk_expiration = 0;
Pradeep Reddy POTTETI8ce2a232016-10-28 12:17:32 +05304665 if (get_driver_type() == DRIVER_WCN) {
4666 /* Enable the WCN driver in TDLS Explicit trigger mode
4667 */
4668 wpa_command(intf, "SET tdls_external_control 0");
4669 wpa_command(intf, "SET tdls_trigger_control 0");
4670 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004671 }
4672
Amarnath Hullur Subramanyam9c381f52017-03-17 00:04:41 -07004673#ifdef MIRACAST
4674 if (dut->program == PROGRAM_WFD ||
4675 dut->program == PROGRAM_DISPLAYR2)
4676 miracast_sta_reset_default(dut, conn, cmd);
4677#endif /* MIRACAST */
4678
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004679 switch (get_driver_type()) {
4680 case DRIVER_ATHEROS:
4681 sta_reset_default_ath(dut, intf, type);
4682 break;
4683 default:
4684 break;
4685 }
4686
4687#ifdef ANDROID_NAN
4688 if (dut->program == PROGRAM_NAN)
4689 nan_cmd_sta_reset_default(dut, conn, cmd);
4690#endif /* ANDROID_NAN */
4691
4692 if (dut->program == PROGRAM_HS2_R2) {
4693 unlink("SP/wi-fi.org/pps.xml");
4694 if (system("rm -r SP/*") != 0) {
4695 }
4696 unlink("next-client-cert.pem");
4697 unlink("next-client-key.pem");
4698 }
4699
4700 if (dut->program == PROGRAM_60GHZ) {
4701 const char *dev_role = get_param(cmd, "DevRole");
4702
4703 if (!dev_role) {
4704 send_resp(dut, conn, SIGMA_ERROR,
4705 "errorCode,Missing DevRole argument");
4706 return 0;
4707 }
4708
4709 if (strcasecmp(dev_role, "STA") == 0)
4710 dut->dev_role = DEVROLE_STA;
4711 else if (strcasecmp(dev_role, "PCP") == 0)
4712 dut->dev_role = DEVROLE_PCP;
4713 else {
4714 send_resp(dut, conn, SIGMA_ERROR,
4715 "errorCode,Unknown DevRole");
4716 return 0;
4717 }
4718
4719 if (dut->device_type == STA_unknown) {
4720 sigma_dut_print(dut, DUT_MSG_ERROR,
4721 "Device type is not STA testbed or DUT");
4722 send_resp(dut, conn, SIGMA_ERROR,
4723 "errorCode,Unknown device type");
4724 return 0;
4725 }
4726 }
4727
4728 wpa_command(intf, "WPS_ER_STOP");
4729 wpa_command(intf, "FLUSH");
4730 wpa_command(intf, "SET radio_disabled 0");
4731
4732 if (dut->tmp_mac_addr && dut->set_macaddr) {
4733 dut->tmp_mac_addr = 0;
4734 if (system(dut->set_macaddr) != 0) {
4735 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to clear "
4736 "temporary MAC address");
4737 }
4738 }
4739
4740 set_ps(intf, dut, 0);
4741
4742 if (dut->program == PROGRAM_HS2 || dut->program == PROGRAM_HS2_R2) {
4743 wpa_command(intf, "SET interworking 1");
4744 wpa_command(intf, "SET hs20 1");
4745 }
4746
4747 if (dut->program == PROGRAM_HS2_R2) {
4748 wpa_command(intf, "SET pmf 1");
4749 } else {
4750 wpa_command(intf, "SET pmf 0");
4751 }
4752
4753 hs2_clear_credentials(intf);
4754 wpa_command(intf, "SET hessid 00:00:00:00:00:00");
4755 wpa_command(intf, "SET access_network_type 15");
4756
4757 static_ip_file(0, NULL, NULL, NULL);
4758 kill_dhcp_client(dut, intf);
4759 clear_ip_addr(dut, intf);
4760
4761 dut->er_oper_performed = 0;
4762 dut->er_oper_bssid[0] = '\0';
4763
priyadharshini gowthamanad6cbba2016-10-04 10:39:58 -07004764 if (dut->program == PROGRAM_LOC) {
4765 /* Disable Interworking by default */
4766 wpa_command(get_station_ifname(), "SET interworking 0");
4767 }
4768
Ashwini Patil00402582017-04-13 12:29:39 +05304769 if (dut->program == PROGRAM_MBO) {
4770 free(dut->non_pref_ch_list);
4771 dut->non_pref_ch_list = NULL;
Ashwini Patil5acd7382017-04-13 15:55:04 +05304772 free(dut->btm_query_cand_list);
4773 dut->btm_query_cand_list = NULL;
Ashwini Patilc63161e2017-04-13 16:30:23 +05304774 wpa_command(intf, "SET reject_btm_req_reason 0");
Ashwini Patila75de5a2017-04-13 16:35:05 +05304775 wpa_command(intf, "SET ignore_assoc_disallow 0");
Ashwini Patild174f2c2017-04-13 16:49:46 +05304776 wpa_command(intf, "SET gas_address3 0");
Ashwini Patil9183fdb2017-04-13 16:58:25 +05304777 wpa_command(intf, "SET roaming 1");
Ashwini Patil00402582017-04-13 12:29:39 +05304778 }
4779
Priyadharshini Gowthamana7dfd492015-11-09 14:34:08 -08004780 if (dut->program != PROGRAM_VHT)
4781 return cmd_sta_p2p_reset(dut, conn, cmd);
4782 return 1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004783}
4784
4785
4786static int cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
4787 struct sigma_cmd *cmd)
4788{
4789 const char *program = get_param(cmd, "Program");
4790
4791 if (program == NULL)
4792 return -1;
4793#ifdef ANDROID_NAN
4794 if (strcasecmp(program, "NAN") == 0)
4795 return nan_cmd_sta_get_events(dut, conn, cmd);
4796#endif /* ANDROID_NAN */
4797 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4798 return 0;
4799}
4800
4801
4802static int cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
4803 struct sigma_cmd *cmd)
4804{
4805 const char *program = get_param(cmd, "Prog");
4806
4807 if (program == NULL)
4808 return -1;
4809#ifdef ANDROID_NAN
4810 if (strcasecmp(program, "NAN") == 0)
4811 return nan_cmd_sta_exec_action(dut, conn, cmd);
4812#endif /* ANDROID_NAN */
priyadharshini gowthamand66913a2016-07-29 15:11:17 -07004813 if (strcasecmp(program, "Loc") == 0)
4814 return loc_cmd_sta_exec_action(dut, conn, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004815 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
4816 return 0;
4817}
4818
4819
4820static int cmd_sta_set_11n(struct sigma_dut *dut, struct sigma_conn *conn,
4821 struct sigma_cmd *cmd)
4822{
4823 const char *intf = get_param(cmd, "Interface");
4824 const char *val, *mcs32, *rate;
4825
4826 val = get_param(cmd, "GREENFIELD");
4827 if (val) {
4828 if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
4829 /* Enable GD */
4830 send_resp(dut, conn, SIGMA_ERROR,
4831 "ErrorCode,GF not supported");
4832 return 0;
4833 }
4834 }
4835
4836 val = get_param(cmd, "SGI20");
4837 if (val) {
4838 switch (get_driver_type()) {
4839 case DRIVER_ATHEROS:
4840 ath_sta_set_sgi(dut, intf, val);
4841 break;
4842 default:
4843 send_resp(dut, conn, SIGMA_ERROR,
4844 "ErrorCode,SGI20 not supported");
4845 return 0;
4846 }
4847 }
4848
4849 mcs32 = get_param(cmd, "MCS32"); /* HT Duplicate Mode Enable/Disable */
4850 rate = get_param(cmd, "MCS_FIXEDRATE"); /* Fixed MCS rate (0..31) */
4851 if (mcs32 && rate) {
4852 /* TODO */
4853 send_resp(dut, conn, SIGMA_ERROR,
4854 "ErrorCode,MCS32,MCS_FIXEDRATE not supported");
4855 return 0;
4856 } else if (mcs32 && !rate) {
4857 /* TODO */
4858 send_resp(dut, conn, SIGMA_ERROR,
4859 "ErrorCode,MCS32 not supported");
4860 return 0;
4861 } else if (!mcs32 && rate) {
4862 switch (get_driver_type()) {
4863 case DRIVER_ATHEROS:
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08004864 novap_reset(dut, intf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004865 ath_sta_set_11nrates(dut, intf, rate);
4866 break;
4867 default:
4868 send_resp(dut, conn, SIGMA_ERROR,
4869 "ErrorCode,MCS32_FIXEDRATE not supported");
4870 return 0;
4871 }
4872 }
4873
4874 return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
4875}
4876
4877
4878static int cmd_sta_set_wireless_vht(struct sigma_dut *dut,
4879 struct sigma_conn *conn,
4880 struct sigma_cmd *cmd)
4881{
4882 const char *intf = get_param(cmd, "Interface");
4883 const char *val;
4884 char buf[30];
4885 int tkip = -1;
4886 int wep = -1;
4887
4888 val = get_param(cmd, "SGI80");
4889 if (val) {
4890 int sgi80;
4891
4892 sgi80 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4893 snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi80);
4894 if (system(buf) != 0) {
4895 sigma_dut_print(dut, DUT_MSG_ERROR,
4896 "iwpriv shortgi failed");
4897 }
4898 }
4899
4900 val = get_param(cmd, "TxBF");
4901 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
4902 snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfee 1", intf);
4903 if (system(buf) != 0) {
4904 sigma_dut_print(dut, DUT_MSG_ERROR,
4905 "iwpriv vhtsubfee failed");
4906 }
4907 snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfer 1", intf);
4908 if (system(buf) != 0) {
4909 sigma_dut_print(dut, DUT_MSG_ERROR,
4910 "iwpriv vhtsubfer failed");
4911 }
4912 }
4913
4914 val = get_param(cmd, "MU_TxBF");
4915 if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
4916 switch (get_driver_type()) {
4917 case DRIVER_ATHEROS:
4918 ath_sta_set_txsp_stream(dut, intf, "1SS");
4919 ath_sta_set_rxsp_stream(dut, intf, "1SS");
4920 case DRIVER_WCN:
4921 if (wcn_sta_set_sp_stream(dut, intf, "1SS") < 0) {
4922 send_resp(dut, conn, SIGMA_ERROR,
4923 "ErrorCode,Failed to set RX/TXSP_STREAM");
4924 return 0;
4925 }
4926 default:
4927 sigma_dut_print(dut, DUT_MSG_ERROR,
4928 "Setting SP_STREAM not supported");
4929 break;
4930 }
4931 snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfee 1", intf);
4932 if (system(buf) != 0) {
4933 sigma_dut_print(dut, DUT_MSG_ERROR,
4934 "iwpriv vhtmubfee failed");
4935 }
4936 snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfer 1", intf);
4937 if (system(buf) != 0) {
4938 sigma_dut_print(dut, DUT_MSG_ERROR,
4939 "iwpriv vhtmubfer failed");
4940 }
4941 }
4942
4943 val = get_param(cmd, "LDPC");
4944 if (val) {
4945 int ldpc;
4946
4947 ldpc = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4948 snprintf(buf, sizeof(buf), "iwpriv %s ldpc %d", intf, ldpc);
4949 if (system(buf) != 0) {
4950 sigma_dut_print(dut, DUT_MSG_ERROR,
4951 "iwpriv ldpc failed");
4952 }
4953 }
4954
4955 val = get_param(cmd, "opt_md_notif_ie");
4956 if (val) {
4957 char *result = NULL;
4958 char delim[] = ";";
4959 char token[30];
4960 int value, config_val = 0;
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304961 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004962
4963 strncpy(token, val, sizeof(token));
4964 token[sizeof(token) - 1] = '\0';
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05304965 result = strtok_r(token, delim, &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02004966
4967 /* Extract the NSS information */
4968 if (result) {
4969 value = atoi(result);
4970 switch (value) {
4971 case 1:
4972 config_val = 1;
4973 break;
4974 case 2:
4975 config_val = 3;
4976 break;
4977 case 3:
4978 config_val = 7;
4979 break;
4980 case 4:
4981 config_val = 15;
4982 break;
4983 default:
4984 config_val = 3;
4985 break;
4986 }
4987
4988 snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
4989 intf, config_val);
4990 if (system(buf) != 0) {
4991 sigma_dut_print(dut, DUT_MSG_ERROR,
4992 "iwpriv rxchainmask failed");
4993 }
4994
4995 snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
4996 intf, config_val);
4997 if (system(buf) != 0) {
4998 sigma_dut_print(dut, DUT_MSG_ERROR,
4999 "iwpriv txchainmask failed");
5000 }
5001 }
5002
5003 /* Extract the channel width information */
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305004 result = strtok_r(NULL, delim, &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005005 if (result) {
5006 value = atoi(result);
5007 switch (value) {
5008 case 20:
5009 config_val = 0;
5010 break;
5011 case 40:
5012 config_val = 1;
5013 break;
5014 case 80:
5015 config_val = 2;
5016 break;
5017 case 160:
5018 config_val = 3;
5019 break;
5020 default:
5021 config_val = 2;
5022 break;
5023 }
5024
5025 dut->chwidth = config_val;
5026
5027 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
5028 intf, config_val);
5029 if (system(buf) != 0) {
5030 sigma_dut_print(dut, DUT_MSG_ERROR,
5031 "iwpriv chwidth failed");
5032 }
5033 }
5034
5035 snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", intf);
5036 if (system(buf) != 0) {
5037 sigma_dut_print(dut, DUT_MSG_ERROR,
5038 "iwpriv opmode_notify failed");
5039 }
5040 }
5041
5042 val = get_param(cmd, "nss_mcs_cap");
5043 if (val) {
5044 int nss, mcs;
5045 char token[20];
5046 char *result = NULL;
5047 unsigned int vht_mcsmap = 0;
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305048 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005049
5050 strncpy(token, val, sizeof(token));
5051 token[sizeof(token) - 1] = '\0';
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305052 result = strtok_r(token, ";", &saveptr);
Pradeep Reddy POTTETIcd649a22016-01-29 12:55:59 +05305053 if (!result) {
5054 sigma_dut_print(dut, DUT_MSG_ERROR,
5055 "VHT NSS not specified");
5056 return 0;
5057 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005058 nss = atoi(result);
5059
5060 snprintf(buf, sizeof(buf), "iwpriv %s nss %d", intf, nss);
5061 if (system(buf) != 0) {
5062 sigma_dut_print(dut, DUT_MSG_ERROR,
5063 "iwpriv nss failed");
5064 }
5065
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305066 result = strtok_r(NULL, ";", &saveptr);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005067 if (result == NULL) {
5068 sigma_dut_print(dut, DUT_MSG_ERROR,
5069 "VHTMCS NOT SPECIFIED!");
5070 return 0;
5071 }
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05305072 result = strtok_r(result, "-", &saveptr);
5073 result = strtok_r(NULL, "-", &saveptr);
Pradeep Reddy POTTETIcd649a22016-01-29 12:55:59 +05305074 if (!result) {
5075 sigma_dut_print(dut, DUT_MSG_ERROR,
5076 "VHT MCS not specified");
5077 return 0;
5078 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005079 mcs = atoi(result);
5080
5081 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d", intf, mcs);
5082 if (system(buf) != 0) {
5083 sigma_dut_print(dut, DUT_MSG_ERROR,
5084 "iwpriv mcs failed");
5085 }
5086
5087 switch (nss) {
5088 case 1:
5089 switch (mcs) {
5090 case 7:
5091 vht_mcsmap = 0xfffc;
5092 break;
5093 case 8:
5094 vht_mcsmap = 0xfffd;
5095 break;
5096 case 9:
5097 vht_mcsmap = 0xfffe;
5098 break;
5099 default:
5100 vht_mcsmap = 0xfffe;
5101 break;
5102 }
5103 break;
5104 case 2:
5105 switch (mcs) {
5106 case 7:
5107 vht_mcsmap = 0xfff0;
5108 break;
5109 case 8:
5110 vht_mcsmap = 0xfff5;
5111 break;
5112 case 9:
5113 vht_mcsmap = 0xfffa;
5114 break;
5115 default:
5116 vht_mcsmap = 0xfffa;
5117 break;
5118 }
5119 break;
5120 case 3:
5121 switch (mcs) {
5122 case 7:
5123 vht_mcsmap = 0xffc0;
5124 break;
5125 case 8:
5126 vht_mcsmap = 0xffd5;
5127 break;
5128 case 9:
5129 vht_mcsmap = 0xffea;
5130 break;
5131 default:
5132 vht_mcsmap = 0xffea;
5133 break;
5134 }
5135 break;
5136 default:
5137 vht_mcsmap = 0xffea;
5138 break;
5139 }
5140 snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
5141 intf, vht_mcsmap);
5142 if (system(buf) != 0) {
5143 sigma_dut_print(dut, DUT_MSG_ERROR,
5144 "iwpriv vht_mcsmap failed");
5145 }
5146 }
5147
5148 /* UNSUPPORTED: val = get_param(cmd, "Tx_lgi_rate"); */
5149
5150 val = get_param(cmd, "Vht_tkip");
5151 if (val)
5152 tkip = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
5153
5154 val = get_param(cmd, "Vht_wep");
5155 if (val)
5156 wep = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
5157
5158 if (tkip != -1 || wep != -1) {
5159 if ((tkip == 1 && wep != 0) || (wep == 1 && tkip != 0)) {
5160 snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 1",
5161 intf);
5162 } else if ((tkip == 0 && wep != 1) || (wep == 0 && tkip != 1)) {
5163 snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 0",
5164 intf);
5165 } else {
5166 sigma_dut_print(dut, DUT_MSG_ERROR,
5167 "ErrorCode,mixed mode of VHT TKIP/WEP not supported");
5168 return 0;
5169 }
5170
5171 if (system(buf) != 0) {
5172 sigma_dut_print(dut, DUT_MSG_ERROR,
5173 "iwpriv htweptkip failed");
5174 }
5175 }
5176
5177 val = get_param(cmd, "txBandwidth");
5178 if (val) {
5179 switch (get_driver_type()) {
5180 case DRIVER_ATHEROS:
5181 if (ath_set_width(dut, conn, intf, val) < 0) {
5182 send_resp(dut, conn, SIGMA_ERROR,
5183 "ErrorCode,Failed to set txBandwidth");
5184 return 0;
5185 }
5186 break;
5187 default:
5188 sigma_dut_print(dut, DUT_MSG_ERROR,
5189 "Setting txBandwidth not supported");
5190 break;
5191 }
5192 }
5193
5194 return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
5195}
5196
5197
5198static int sta_set_wireless_60g(struct sigma_dut *dut,
5199 struct sigma_conn *conn,
5200 struct sigma_cmd *cmd)
5201{
5202 const char *dev_role = get_param(cmd, "DevRole");
5203
5204 if (!dev_role) {
5205 send_resp(dut, conn, SIGMA_INVALID,
5206 "ErrorCode,DevRole not specified");
5207 return 0;
5208 }
5209
5210 if (strcasecmp(dev_role, "PCP") == 0)
5211 return sta_set_60g_pcp(dut, conn, cmd);
5212 if (strcasecmp(dev_role, "STA") == 0)
5213 return sta_set_60g_sta(dut, conn, cmd);
5214 send_resp(dut, conn, SIGMA_INVALID,
5215 "ErrorCode,DevRole not supported");
5216 return 0;
5217}
5218
5219
5220static int cmd_sta_set_wireless(struct sigma_dut *dut, struct sigma_conn *conn,
5221 struct sigma_cmd *cmd)
5222{
5223 const char *val;
5224
5225 val = get_param(cmd, "Program");
5226 if (val) {
5227 if (strcasecmp(val, "11n") == 0)
5228 return cmd_sta_set_11n(dut, conn, cmd);
5229 if (strcasecmp(val, "VHT") == 0)
5230 return cmd_sta_set_wireless_vht(dut, conn, cmd);
5231 if (strcasecmp(val, "60ghz") == 0)
5232 return sta_set_wireless_60g(dut, conn, cmd);
5233 send_resp(dut, conn, SIGMA_ERROR,
5234 "ErrorCode,Program value not supported");
5235 } else {
5236 send_resp(dut, conn, SIGMA_ERROR,
5237 "ErrorCode,Program argument not available");
5238 }
5239
5240 return 0;
5241}
5242
5243
5244static void ath_sta_inject_frame(struct sigma_dut *dut, const char *intf,
5245 int tid)
5246{
5247 char buf[100];
5248 int tid_to_dscp [] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 };
5249
Pradeep Reddy POTTETId31d1322016-10-13 17:22:03 +05305250 if (tid < 0 ||
5251 tid >= (int) (sizeof(tid_to_dscp) / sizeof(tid_to_dscp[0]))) {
5252 sigma_dut_print(dut, DUT_MSG_ERROR, "Unsupported TID: %d", tid);
5253 return;
5254 }
5255
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005256 /*
5257 * Two ways to ensure that addba request with a
5258 * non zero TID could be sent out. EV 117296
5259 */
5260 snprintf(buf, sizeof(buf),
5261 "ping -c 8 -Q %d `arp -a | grep wlan0 | awk '{print $2}' | tr -d '()'`",
5262 tid);
5263 if (system(buf) != 0) {
5264 sigma_dut_print(dut, DUT_MSG_ERROR,
5265 "Ping did not send out");
5266 }
5267
5268 snprintf(buf, sizeof(buf),
5269 "iwconfig %s | grep Access | awk '{print $6}' > %s",
5270 intf, VI_QOS_TMP_FILE);
5271 if (system(buf) != 0)
5272 return;
5273
5274 snprintf(buf, sizeof(buf),
5275 "ifconfig %s | grep HWaddr | cut -b 39-56 >> %s",
5276 intf, VI_QOS_TMP_FILE);
5277 if (system(buf) != 0)
5278 sigma_dut_print(dut, DUT_MSG_ERROR, "HWaddr matching failed");
5279
5280 snprintf(buf,sizeof(buf), "sed -n '3,$p' %s >> %s",
5281 VI_QOS_REFFILE, VI_QOS_TMP_FILE);
5282 if (system(buf) != 0) {
5283 sigma_dut_print(dut, DUT_MSG_ERROR,
5284 "VI_QOS_TEMP_FILE generation error failed");
5285 }
5286 snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
5287 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
5288 if (system(buf) != 0) {
5289 sigma_dut_print(dut, DUT_MSG_ERROR,
5290 "VI_QOS_FILE generation failed");
5291 }
5292
5293 snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
5294 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
5295 if (system(buf) != 0) {
5296 sigma_dut_print(dut, DUT_MSG_ERROR,
5297 "VI_QOS_FILE generation failed");
5298 }
5299
5300 snprintf(buf, sizeof(buf), "ethinject %s %s", intf, VI_QOS_FILE);
5301 if (system(buf) != 0) {
5302 }
5303}
5304
5305
5306static int ath_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
5307 struct sigma_cmd *cmd)
5308{
5309 const char *intf = get_param(cmd, "Interface");
5310 const char *val;
5311 int tid = 0;
5312 char buf[100];
5313
5314 val = get_param(cmd, "TID");
5315 if (val) {
5316 tid = atoi(val);
5317 if (tid)
5318 ath_sta_inject_frame(dut, intf, tid);
5319 }
5320
5321 /* Command sequence for ADDBA request on Peregrine based devices */
5322 snprintf(buf, sizeof(buf), "iwpriv %s setaddbaoper 1", intf);
5323 if (system(buf) != 0) {
5324 sigma_dut_print(dut, DUT_MSG_ERROR,
5325 "iwpriv setaddbaoper failed");
5326 }
5327
5328 snprintf(buf, sizeof(buf), "wifitool %s senddelba 1 %d 1 4", intf, tid);
5329 if (system(buf) != 0) {
5330 sigma_dut_print(dut, DUT_MSG_ERROR,
5331 "wifitool senddelba failed");
5332 }
5333
5334 snprintf(buf, sizeof(buf), "wifitool %s sendaddba 1 %d 64", intf, tid);
5335 if (system(buf) != 0) {
5336 sigma_dut_print(dut, DUT_MSG_ERROR,
5337 "wifitool sendaddba failed");
5338 }
5339
5340 /* UNSUPPORTED: val = get_param(cmd, "Dest_mac"); */
5341
5342 return 1;
5343}
5344
5345
Lior David9981b512017-01-20 13:16:40 +02005346#ifdef __linux__
5347
5348static int wil6210_send_addba(struct sigma_dut *dut, const char *dest_mac,
5349 int agg_size)
5350{
5351 char dir[128], buf[128];
5352 FILE *f;
5353 regex_t re;
5354 regmatch_t m[2];
5355 int rc, ret = -1, vring_id, found;
5356
5357 if (wil6210_get_debugfs_dir(dut, dir, sizeof(dir))) {
5358 sigma_dut_print(dut, DUT_MSG_ERROR,
5359 "failed to get wil6210 debugfs dir");
5360 return -1;
5361 }
5362
5363 snprintf(buf, sizeof(buf), "%s/vrings", dir);
5364 f = fopen(buf, "r");
5365 if (!f) {
5366 sigma_dut_print(dut, DUT_MSG_ERROR, "failed to open: %s", buf);
5367 return -1;
5368 }
5369
5370 if (regcomp(&re, "VRING tx_[ \t]*([0-9]+)", REG_EXTENDED)) {
5371 sigma_dut_print(dut, DUT_MSG_ERROR, "regcomp failed");
5372 goto out;
5373 }
5374
5375 /* find TX VRING for the mac address */
5376 found = 0;
5377 while (fgets(buf, sizeof(buf), f)) {
5378 if (strcasestr(buf, dest_mac)) {
5379 found = 1;
5380 break;
5381 }
5382 }
5383
5384 if (!found) {
5385 sigma_dut_print(dut, DUT_MSG_ERROR,
5386 "no TX VRING for %s", dest_mac);
5387 goto out;
5388 }
5389
5390 /* extract VRING ID, "VRING tx_<id> = {" */
5391 if (!fgets(buf, sizeof(buf), f)) {
5392 sigma_dut_print(dut, DUT_MSG_ERROR,
5393 "no VRING start line for %s", dest_mac);
5394 goto out;
5395 }
5396
5397 rc = regexec(&re, buf, 2, m, 0);
5398 regfree(&re);
5399 if (rc || m[1].rm_so < 0) {
5400 sigma_dut_print(dut, DUT_MSG_ERROR,
5401 "no VRING TX ID for %s", dest_mac);
5402 goto out;
5403 }
5404 buf[m[1].rm_eo] = 0;
5405 vring_id = atoi(&buf[m[1].rm_so]);
5406
5407 /* send the addba command */
5408 fclose(f);
5409 snprintf(buf, sizeof(buf), "%s/back", dir);
5410 f = fopen(buf, "w");
5411 if (!f) {
5412 sigma_dut_print(dut, DUT_MSG_ERROR,
5413 "failed to open: %s", buf);
5414 return -1;
5415 }
5416
5417 fprintf(f, "add %d %d\n", vring_id, agg_size);
5418
5419 ret = 0;
5420
5421out:
5422 fclose(f);
5423
5424 return ret;
5425}
5426
5427
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005428static int send_addba_60g(struct sigma_dut *dut, struct sigma_conn *conn,
5429 struct sigma_cmd *cmd)
5430{
5431 const char *val;
5432 int tid = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005433
5434 val = get_param(cmd, "TID");
5435 if (val) {
5436 tid = atoi(val);
5437 if (tid != 0) {
5438 sigma_dut_print(dut, DUT_MSG_ERROR,
5439 "Ignore TID %d for send_addba use TID 0 for 60g since only 0 required on TX",
5440 tid);
5441 }
5442 }
5443
5444 val = get_param(cmd, "Dest_mac");
5445 if (!val) {
5446 sigma_dut_print(dut, DUT_MSG_ERROR,
5447 "Currently not supporting addba for 60G without Dest_mac");
5448 return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
5449 }
5450
Lior David9981b512017-01-20 13:16:40 +02005451 if (wil6210_send_addba(dut, val, dut->back_rcv_buf))
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005452 return -1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005453
5454 return 1;
5455}
5456
Lior David9981b512017-01-20 13:16:40 +02005457#endif /* __linux__ */
5458
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005459
5460static int cmd_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
5461 struct sigma_cmd *cmd)
5462{
5463 switch (get_driver_type()) {
5464 case DRIVER_ATHEROS:
5465 return ath_sta_send_addba(dut, conn, cmd);
Lior David9981b512017-01-20 13:16:40 +02005466#ifdef __linux__
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005467 case DRIVER_WIL6210:
5468 return send_addba_60g(dut, conn, cmd);
Lior David9981b512017-01-20 13:16:40 +02005469#endif /* __linux__ */
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005470 default:
5471 /*
5472 * There is no driver specific implementation for other drivers.
5473 * Ignore the command and report COMPLETE since the following
5474 * throughput test operation will end up sending ADDBA anyway.
5475 */
5476 return 1;
5477 }
5478}
5479
5480
5481int inject_eth_frame(int s, const void *data, size_t len,
5482 unsigned short ethtype, char *dst, char *src)
5483{
5484 struct iovec iov[4] = {
5485 {
5486 .iov_base = dst,
5487 .iov_len = ETH_ALEN,
5488 },
5489 {
5490 .iov_base = src,
5491 .iov_len = ETH_ALEN,
5492 },
5493 {
5494 .iov_base = &ethtype,
5495 .iov_len = sizeof(unsigned short),
5496 },
5497 {
5498 .iov_base = (void *) data,
5499 .iov_len = len,
5500 }
5501 };
5502 struct msghdr msg = {
5503 .msg_name = NULL,
5504 .msg_namelen = 0,
5505 .msg_iov = iov,
5506 .msg_iovlen = 4,
5507 .msg_control = NULL,
5508 .msg_controllen = 0,
5509 .msg_flags = 0,
5510 };
5511
5512 return sendmsg(s, &msg, 0);
5513}
5514
5515#if defined(__linux__) || defined(__QNXNTO__)
5516
5517int inject_frame(int s, const void *data, size_t len, int encrypt)
5518{
5519#define IEEE80211_RADIOTAP_F_WEP 0x04
5520#define IEEE80211_RADIOTAP_F_FRAG 0x08
5521 unsigned char rtap_hdr[] = {
5522 0x00, 0x00, /* radiotap version */
5523 0x0e, 0x00, /* radiotap length */
5524 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
5525 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
5526 0x00, /* padding */
5527 0x00, 0x00, /* RX and TX flags to indicate that */
5528 0x00, 0x00, /* this is the injected frame directly */
5529 };
5530 struct iovec iov[2] = {
5531 {
5532 .iov_base = &rtap_hdr,
5533 .iov_len = sizeof(rtap_hdr),
5534 },
5535 {
5536 .iov_base = (void *) data,
5537 .iov_len = len,
5538 }
5539 };
5540 struct msghdr msg = {
5541 .msg_name = NULL,
5542 .msg_namelen = 0,
5543 .msg_iov = iov,
5544 .msg_iovlen = 2,
5545 .msg_control = NULL,
5546 .msg_controllen = 0,
5547 .msg_flags = 0,
5548 };
5549
5550 if (encrypt)
5551 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
5552
5553 return sendmsg(s, &msg, 0);
5554}
5555
5556
5557int open_monitor(const char *ifname)
5558{
5559#ifdef __QNXNTO__
5560 struct sockaddr_dl ll;
5561 int s;
5562
5563 memset(&ll, 0, sizeof(ll));
5564 ll.sdl_family = AF_LINK;
5565 ll.sdl_index = if_nametoindex(ifname);
5566 if (ll.sdl_index == 0) {
5567 perror("if_nametoindex");
5568 return -1;
5569 }
5570 s = socket(PF_INET, SOCK_RAW, 0);
5571#else /* __QNXNTO__ */
5572 struct sockaddr_ll ll;
5573 int s;
5574
5575 memset(&ll, 0, sizeof(ll));
5576 ll.sll_family = AF_PACKET;
5577 ll.sll_ifindex = if_nametoindex(ifname);
5578 if (ll.sll_ifindex == 0) {
5579 perror("if_nametoindex");
5580 return -1;
5581 }
5582 s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
5583#endif /* __QNXNTO__ */
5584 if (s < 0) {
5585 perror("socket[PF_PACKET,SOCK_RAW]");
5586 return -1;
5587 }
5588
5589 if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
5590 perror("monitor socket bind");
5591 close(s);
5592 return -1;
5593 }
5594
5595 return s;
5596}
5597
5598
5599static int hex2num(char c)
5600{
5601 if (c >= '0' && c <= '9')
5602 return c - '0';
5603 if (c >= 'a' && c <= 'f')
5604 return c - 'a' + 10;
5605 if (c >= 'A' && c <= 'F')
5606 return c - 'A' + 10;
5607 return -1;
5608}
5609
5610
5611int hwaddr_aton(const char *txt, unsigned char *addr)
5612{
5613 int i;
5614
5615 for (i = 0; i < 6; i++) {
5616 int a, b;
5617
5618 a = hex2num(*txt++);
5619 if (a < 0)
5620 return -1;
5621 b = hex2num(*txt++);
5622 if (b < 0)
5623 return -1;
5624 *addr++ = (a << 4) | b;
5625 if (i < 5 && *txt++ != ':')
5626 return -1;
5627 }
5628
5629 return 0;
5630}
5631
5632#endif /* defined(__linux__) || defined(__QNXNTO__) */
5633
5634enum send_frame_type {
5635 DISASSOC, DEAUTH, SAQUERY, AUTH, ASSOCREQ, REASSOCREQ, DLS_REQ
5636};
5637enum send_frame_protection {
5638 CORRECT_KEY, INCORRECT_KEY, UNPROTECTED
5639};
5640
5641
5642static int sta_inject_frame(struct sigma_dut *dut, struct sigma_conn *conn,
5643 enum send_frame_type frame,
5644 enum send_frame_protection protected,
5645 const char *dest)
5646{
5647#ifdef __linux__
5648 unsigned char buf[1000], *pos;
5649 int s, res;
5650 char bssid[20], addr[20];
5651 char result[32], ssid[100];
5652 size_t ssid_len;
5653
5654 if (get_wpa_status(get_station_ifname(), "wpa_state", result,
5655 sizeof(result)) < 0 ||
5656 strncmp(result, "COMPLETED", 9) != 0) {
5657 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Not connected");
5658 return 0;
5659 }
5660
5661 if (get_wpa_status(get_station_ifname(), "bssid", bssid, sizeof(bssid))
5662 < 0) {
5663 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
5664 "current BSSID");
5665 return 0;
5666 }
5667
5668 if (get_wpa_status(get_station_ifname(), "address", addr, sizeof(addr))
5669 < 0) {
5670 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
5671 "own MAC address");
5672 return 0;
5673 }
5674
5675 if (get_wpa_status(get_station_ifname(), "ssid", ssid, sizeof(ssid))
5676 < 0) {
5677 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
5678 "current SSID");
5679 return 0;
5680 }
5681 ssid_len = strlen(ssid);
5682
5683 pos = buf;
5684
5685 /* Frame Control */
5686 switch (frame) {
5687 case DISASSOC:
5688 *pos++ = 0xa0;
5689 break;
5690 case DEAUTH:
5691 *pos++ = 0xc0;
5692 break;
5693 case SAQUERY:
5694 *pos++ = 0xd0;
5695 break;
5696 case AUTH:
5697 *pos++ = 0xb0;
5698 break;
5699 case ASSOCREQ:
5700 *pos++ = 0x00;
5701 break;
5702 case REASSOCREQ:
5703 *pos++ = 0x20;
5704 break;
5705 case DLS_REQ:
5706 *pos++ = 0xd0;
5707 break;
5708 }
5709
5710 if (protected == INCORRECT_KEY)
5711 *pos++ = 0x40; /* Set Protected field to 1 */
5712 else
5713 *pos++ = 0x00;
5714
5715 /* Duration */
5716 *pos++ = 0x00;
5717 *pos++ = 0x00;
5718
5719 /* addr1 = DA (current AP) */
5720 hwaddr_aton(bssid, pos);
5721 pos += 6;
5722 /* addr2 = SA (own address) */
5723 hwaddr_aton(addr, pos);
5724 pos += 6;
5725 /* addr3 = BSSID (current AP) */
5726 hwaddr_aton(bssid, pos);
5727 pos += 6;
5728
5729 /* Seq# (to be filled by driver/mac80211) */
5730 *pos++ = 0x00;
5731 *pos++ = 0x00;
5732
5733 if (protected == INCORRECT_KEY) {
5734 /* CCMP parameters */
5735 memcpy(pos, "\x61\x01\x00\x20\x00\x10\x00\x00", 8);
5736 pos += 8;
5737 }
5738
5739 if (protected == INCORRECT_KEY) {
5740 switch (frame) {
5741 case DEAUTH:
5742 /* Reason code (encrypted) */
5743 memcpy(pos, "\xa7\x39", 2);
5744 pos += 2;
5745 break;
5746 case DISASSOC:
5747 /* Reason code (encrypted) */
5748 memcpy(pos, "\xa7\x39", 2);
5749 pos += 2;
5750 break;
5751 case SAQUERY:
5752 /* Category|Action|TransID (encrypted) */
5753 memcpy(pos, "\x6f\xbd\xe9\x4d", 4);
5754 pos += 4;
5755 break;
5756 default:
5757 return -1;
5758 }
5759
5760 /* CCMP MIC */
5761 memcpy(pos, "\xc8\xd8\x3b\x06\x5d\xb7\x25\x68", 8);
5762 pos += 8;
5763 } else {
5764 switch (frame) {
5765 case DEAUTH:
5766 /* reason code = 8 */
5767 *pos++ = 0x08;
5768 *pos++ = 0x00;
5769 break;
5770 case DISASSOC:
5771 /* reason code = 8 */
5772 *pos++ = 0x08;
5773 *pos++ = 0x00;
5774 break;
5775 case SAQUERY:
5776 /* Category - SA Query */
5777 *pos++ = 0x08;
5778 /* SA query Action - Request */
5779 *pos++ = 0x00;
5780 /* Transaction ID */
5781 *pos++ = 0x12;
5782 *pos++ = 0x34;
5783 break;
5784 case AUTH:
5785 /* Auth Alg (Open) */
5786 *pos++ = 0x00;
5787 *pos++ = 0x00;
5788 /* Seq# */
5789 *pos++ = 0x01;
5790 *pos++ = 0x00;
5791 /* Status code */
5792 *pos++ = 0x00;
5793 *pos++ = 0x00;
5794 break;
5795 case ASSOCREQ:
5796 /* Capability Information */
5797 *pos++ = 0x31;
5798 *pos++ = 0x04;
5799 /* Listen Interval */
5800 *pos++ = 0x0a;
5801 *pos++ = 0x00;
5802 /* SSID */
5803 *pos++ = 0x00;
5804 *pos++ = ssid_len;
5805 memcpy(pos, ssid, ssid_len);
5806 pos += ssid_len;
5807 /* Supported Rates */
5808 memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
5809 10);
5810 pos += 10;
5811 /* Extended Supported Rates */
5812 memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
5813 pos += 6;
5814 /* RSN */
5815 memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
5816 "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
5817 "\x00\x00\x00\x00\x0f\xac\x06", 28);
5818 pos += 28;
5819 break;
5820 case REASSOCREQ:
5821 /* Capability Information */
5822 *pos++ = 0x31;
5823 *pos++ = 0x04;
5824 /* Listen Interval */
5825 *pos++ = 0x0a;
5826 *pos++ = 0x00;
5827 /* Current AP */
5828 hwaddr_aton(bssid, pos);
5829 pos += 6;
5830 /* SSID */
5831 *pos++ = 0x00;
5832 *pos++ = ssid_len;
5833 memcpy(pos, ssid, ssid_len);
5834 pos += ssid_len;
5835 /* Supported Rates */
5836 memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
5837 10);
5838 pos += 10;
5839 /* Extended Supported Rates */
5840 memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
5841 pos += 6;
5842 /* RSN */
5843 memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
5844 "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
5845 "\x00\x00\x00\x00\x0f\xac\x06", 28);
5846 pos += 28;
5847 break;
5848 case DLS_REQ:
5849 /* Category - DLS */
5850 *pos++ = 0x02;
5851 /* DLS Action - Request */
5852 *pos++ = 0x00;
5853 /* Destination MACAddress */
5854 if (dest)
5855 hwaddr_aton(dest, pos);
5856 else
5857 memset(pos, 0, 6);
5858 pos += 6;
5859 /* Source MACAddress */
5860 hwaddr_aton(addr, pos);
5861 pos += 6;
5862 /* Capability Information */
5863 *pos++ = 0x10; /* Privacy */
5864 *pos++ = 0x06; /* QoS */
5865 /* DLS Timeout Value */
5866 *pos++ = 0x00;
5867 *pos++ = 0x01;
5868 /* Supported rates */
5869 *pos++ = 0x01;
5870 *pos++ = 0x08;
5871 *pos++ = 0x0c; /* 6 Mbps */
5872 *pos++ = 0x12; /* 9 Mbps */
5873 *pos++ = 0x18; /* 12 Mbps */
5874 *pos++ = 0x24; /* 18 Mbps */
5875 *pos++ = 0x30; /* 24 Mbps */
5876 *pos++ = 0x48; /* 36 Mbps */
5877 *pos++ = 0x60; /* 48 Mbps */
5878 *pos++ = 0x6c; /* 54 Mbps */
5879 /* TODO: Extended Supported Rates */
5880 /* TODO: HT Capabilities */
5881 break;
5882 }
5883 }
5884
5885 s = open_monitor("sigmadut");
5886 if (s < 0) {
5887 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
5888 "monitor socket");
5889 return 0;
5890 }
5891
5892 res = inject_frame(s, buf, pos - buf, protected == CORRECT_KEY);
5893 if (res < 0) {
5894 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
5895 "inject frame");
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05305896 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005897 return 0;
5898 }
5899 if (res < pos - buf) {
5900 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Only partial "
5901 "frame sent");
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05305902 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02005903 return 0;
5904 }
5905
5906 close(s);
5907
5908 return 1;
5909#else /* __linux__ */
5910 send_resp(dut, conn, SIGMA_ERROR, "errorCode,sta_send_frame not "
5911 "yet supported");
5912 return 0;
5913#endif /* __linux__ */
5914}
5915
5916
5917static int cmd_sta_send_frame_tdls(struct sigma_dut *dut,
5918 struct sigma_conn *conn,
5919 struct sigma_cmd *cmd)
5920{
5921 const char *intf = get_param(cmd, "Interface");
5922 const char *sta, *val;
5923 unsigned char addr[ETH_ALEN];
5924 char buf[100];
5925
5926 sta = get_param(cmd, "peer");
5927 if (sta == NULL)
5928 sta = get_param(cmd, "station");
5929 if (sta == NULL) {
5930 send_resp(dut, conn, SIGMA_ERROR,
5931 "ErrorCode,Missing peer address");
5932 return 0;
5933 }
5934 if (hwaddr_aton(sta, addr) < 0) {
5935 send_resp(dut, conn, SIGMA_ERROR,
5936 "ErrorCode,Invalid peer address");
5937 return 0;
5938 }
5939
5940 val = get_param(cmd, "type");
5941 if (val == NULL)
5942 return -1;
5943
5944 if (strcasecmp(val, "DISCOVERY") == 0) {
5945 snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", sta);
5946 if (wpa_command(intf, buf) < 0) {
5947 send_resp(dut, conn, SIGMA_ERROR,
5948 "ErrorCode,Failed to send TDLS discovery");
5949 return 0;
5950 }
5951 return 1;
5952 }
5953
5954 if (strcasecmp(val, "SETUP") == 0) {
5955 int status = 0, timeout = 0;
5956
5957 val = get_param(cmd, "Status");
5958 if (val)
5959 status = atoi(val);
5960
5961 val = get_param(cmd, "Timeout");
5962 if (val)
5963 timeout = atoi(val);
5964
5965 if (status != 0 && status != 37) {
5966 send_resp(dut, conn, SIGMA_ERROR,
5967 "ErrorCode,Unsupported status value");
5968 return 0;
5969 }
5970
5971 if (timeout != 0 && timeout != 301) {
5972 send_resp(dut, conn, SIGMA_ERROR,
5973 "ErrorCode,Unsupported timeout value");
5974 return 0;
5975 }
5976
5977 if (status && timeout) {
5978 send_resp(dut, conn, SIGMA_ERROR,
5979 "ErrorCode,Unsupported timeout+status "
5980 "combination");
5981 return 0;
5982 }
5983
5984 if (status == 37 &&
5985 wpa_command(intf, "SET tdls_testing 0x200")) {
5986 send_resp(dut, conn, SIGMA_ERROR,
5987 "ErrorCode,Failed to enable "
5988 "decline setup response test mode");
5989 return 0;
5990 }
5991
5992 if (timeout == 301) {
5993 int res;
5994 if (dut->no_tpk_expiration)
5995 res = wpa_command(intf,
5996 "SET tdls_testing 0x108");
5997 else
5998 res = wpa_command(intf,
5999 "SET tdls_testing 0x8");
6000 if (res) {
6001 send_resp(dut, conn, SIGMA_ERROR,
6002 "ErrorCode,Failed to set short TPK "
6003 "lifetime");
6004 return 0;
6005 }
6006 }
6007
6008 snprintf(buf, sizeof(buf), "TDLS_SETUP %s", sta);
6009 if (wpa_command(intf, buf) < 0) {
6010 send_resp(dut, conn, SIGMA_ERROR,
6011 "ErrorCode,Failed to send TDLS setup");
6012 return 0;
6013 }
6014 return 1;
6015 }
6016
6017 if (strcasecmp(val, "TEARDOWN") == 0) {
6018 snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", sta);
6019 if (wpa_command(intf, buf) < 0) {
6020 send_resp(dut, conn, SIGMA_ERROR,
6021 "ErrorCode,Failed to send TDLS teardown");
6022 return 0;
6023 }
6024 return 1;
6025 }
6026
6027 send_resp(dut, conn, SIGMA_ERROR,
6028 "ErrorCode,Unsupported TDLS frame");
6029 return 0;
6030}
6031
6032
6033static int sta_ap_known(const char *ifname, const char *bssid)
6034{
6035 char buf[4096];
6036
6037 snprintf(buf, sizeof(buf), "BSS %s", bssid);
6038 if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
6039 return 0;
6040 if (strncmp(buf, "id=", 3) != 0)
6041 return 0;
6042 return 1;
6043}
6044
6045
6046static int sta_scan_ap(struct sigma_dut *dut, const char *ifname,
6047 const char *bssid)
6048{
6049 int res;
6050 struct wpa_ctrl *ctrl;
6051 char buf[256];
6052
6053 if (sta_ap_known(ifname, bssid))
6054 return 0;
6055 sigma_dut_print(dut, DUT_MSG_DEBUG,
6056 "AP not in BSS table - start scan");
6057
6058 ctrl = open_wpa_mon(ifname);
6059 if (ctrl == NULL) {
6060 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
6061 "wpa_supplicant monitor connection");
6062 return -1;
6063 }
6064
6065 if (wpa_command(ifname, "SCAN") < 0) {
6066 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to start scan");
6067 wpa_ctrl_detach(ctrl);
6068 wpa_ctrl_close(ctrl);
6069 return -1;
6070 }
6071
6072 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
6073 buf, sizeof(buf));
6074
6075 wpa_ctrl_detach(ctrl);
6076 wpa_ctrl_close(ctrl);
6077
6078 if (res < 0) {
6079 sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
6080 return -1;
6081 }
6082
6083 if (sta_ap_known(ifname, bssid))
6084 return 0;
6085 sigma_dut_print(dut, DUT_MSG_INFO, "AP not in BSS table");
6086 return -1;
6087}
6088
6089
6090static int cmd_sta_send_frame_hs2_neighadv(struct sigma_dut *dut,
6091 struct sigma_conn *conn,
6092 struct sigma_cmd *cmd,
6093 const char *intf)
6094{
6095 char buf[200];
6096
6097 snprintf(buf, sizeof(buf), "ndsend 2001:DB8::1 %s", intf);
6098 if (system(buf) != 0) {
6099 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to run "
6100 "ndsend");
6101 return 0;
6102 }
6103
6104 return 1;
6105}
6106
6107
6108static int cmd_sta_send_frame_hs2_neighsolreq(struct sigma_dut *dut,
6109 struct sigma_conn *conn,
6110 struct sigma_cmd *cmd,
6111 const char *intf)
6112{
6113 char buf[200];
6114 const char *ip = get_param(cmd, "SenderIP");
6115
6116 snprintf(buf, sizeof(buf), "ndisc6 -nm %s %s -r 4", ip, intf);
6117 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6118 if (system(buf) == 0) {
6119 sigma_dut_print(dut, DUT_MSG_INFO,
6120 "Neighbor Solicitation got a response "
6121 "for %s@%s", ip, intf);
6122 }
6123
6124 return 1;
6125}
6126
6127
6128static int cmd_sta_send_frame_hs2_arpprobe(struct sigma_dut *dut,
6129 struct sigma_conn *conn,
6130 struct sigma_cmd *cmd,
6131 const char *ifname)
6132{
6133 char buf[200];
6134 const char *ip = get_param(cmd, "SenderIP");
6135
6136 if (ip == NULL) {
6137 send_resp(dut, conn, SIGMA_ERROR,
6138 "ErrorCode,Missing SenderIP parameter");
6139 return 0;
6140 }
6141 snprintf(buf, sizeof(buf), "arping -I %s -D %s -c 4", ifname, ip);
6142 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6143 if (system(buf) != 0) {
6144 sigma_dut_print(dut, DUT_MSG_INFO, "arping DAD got a response "
6145 "for %s@%s", ip, ifname);
6146 }
6147
6148 return 1;
6149}
6150
6151
6152static int cmd_sta_send_frame_hs2_arpannounce(struct sigma_dut *dut,
6153 struct sigma_conn *conn,
6154 struct sigma_cmd *cmd,
6155 const char *ifname)
6156{
6157 char buf[200];
6158 char ip[16];
6159 int s;
6160
6161 s = socket(PF_INET, SOCK_DGRAM, 0);
6162 if (s >= 0) {
6163 struct ifreq ifr;
6164 struct sockaddr_in saddr;
6165
6166 memset(&ifr, 0, sizeof(ifr));
6167 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
6168 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
6169 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
6170 "%s IP address: %s",
6171 ifname, strerror(errno));
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05306172 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006173 return -1;
6174 } else {
6175 memcpy(&saddr, &ifr.ifr_addr,
6176 sizeof(struct sockaddr_in));
6177 strncpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
6178 }
6179 close(s);
6180
6181 }
6182
6183 snprintf(buf, sizeof(buf), "arping -I %s -s %s %s -c 4", ifname, ip,
6184 ip);
6185 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6186 if (system(buf) != 0) {
6187 }
6188
6189 return 1;
6190}
6191
6192
6193static int cmd_sta_send_frame_hs2_arpreply(struct sigma_dut *dut,
6194 struct sigma_conn *conn,
6195 struct sigma_cmd *cmd,
6196 const char *ifname)
6197{
6198 char buf[200], addr[20];
6199 char dst[ETH_ALEN], src[ETH_ALEN];
6200 short ethtype = htons(ETH_P_ARP);
6201 char *pos;
6202 int s, res;
6203 const char *val;
6204 struct sockaddr_in taddr;
6205
6206 val = get_param(cmd, "dest");
6207 if (val)
6208 hwaddr_aton(val, (unsigned char *) dst);
6209
6210 val = get_param(cmd, "DestIP");
6211 if (val)
6212 inet_aton(val, &taddr.sin_addr);
6213
6214 if (get_wpa_status(get_station_ifname(), "address", addr,
6215 sizeof(addr)) < 0)
6216 return -2;
6217 hwaddr_aton(addr, (unsigned char *) src);
6218
6219 pos = buf;
6220 *pos++ = 0x00;
6221 *pos++ = 0x01;
6222 *pos++ = 0x08;
6223 *pos++ = 0x00;
6224 *pos++ = 0x06;
6225 *pos++ = 0x04;
6226 *pos++ = 0x00;
6227 *pos++ = 0x02;
6228 memcpy(pos, src, ETH_ALEN);
6229 pos += ETH_ALEN;
6230 memcpy(pos, &taddr.sin_addr, 4);
6231 pos += 4;
6232 memcpy(pos, dst, ETH_ALEN);
6233 pos += ETH_ALEN;
6234 memcpy(pos, &taddr.sin_addr, 4);
6235 pos += 4;
6236
6237 s = open_monitor(get_station_ifname());
6238 if (s < 0) {
6239 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
6240 "monitor socket");
6241 return 0;
6242 }
6243
6244 res = inject_eth_frame(s, buf, pos - buf, ethtype, dst, src);
6245 if (res < 0) {
6246 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
6247 "inject frame");
Pradeep Reddy POTTETI673d85c2016-07-26 19:08:07 +05306248 close(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006249 return 0;
6250 }
6251
6252 close(s);
6253
6254 return 1;
6255}
6256
6257
6258static int cmd_sta_send_frame_hs2_dls_req(struct sigma_dut *dut,
6259 struct sigma_conn *conn,
6260 struct sigma_cmd *cmd,
6261 const char *intf, const char *dest)
6262{
6263 char buf[100];
6264
6265 if (if_nametoindex("sigmadut") == 0) {
6266 snprintf(buf, sizeof(buf),
6267 "iw dev %s interface add sigmadut type monitor",
6268 get_station_ifname());
6269 if (system(buf) != 0 ||
6270 if_nametoindex("sigmadut") == 0) {
6271 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
6272 "monitor interface with '%s'", buf);
6273 return -2;
6274 }
6275 }
6276
6277 if (system("ifconfig sigmadut up") != 0) {
6278 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
6279 "monitor interface up");
6280 return -2;
6281 }
6282
6283 return sta_inject_frame(dut, conn, DLS_REQ, UNPROTECTED, dest);
6284}
6285
6286
6287static int cmd_sta_send_frame_hs2(struct sigma_dut *dut,
6288 struct sigma_conn *conn,
6289 struct sigma_cmd *cmd)
6290{
6291 const char *intf = get_param(cmd, "Interface");
6292 const char *dest = get_param(cmd, "Dest");
6293 const char *type = get_param(cmd, "FrameName");
6294 const char *val;
6295 char buf[200], *pos, *end;
6296 int count, count2;
6297
6298 if (type == NULL)
6299 type = get_param(cmd, "Type");
6300
6301 if (intf == NULL || dest == NULL || type == NULL)
6302 return -1;
6303
6304 if (strcasecmp(type, "NeighAdv") == 0)
6305 return cmd_sta_send_frame_hs2_neighadv(dut, conn, cmd, intf);
6306
6307 if (strcasecmp(type, "NeighSolicitReq") == 0)
6308 return cmd_sta_send_frame_hs2_neighsolreq(dut, conn, cmd, intf);
6309
6310 if (strcasecmp(type, "ARPProbe") == 0)
6311 return cmd_sta_send_frame_hs2_arpprobe(dut, conn, cmd, intf);
6312
6313 if (strcasecmp(type, "ARPAnnounce") == 0)
6314 return cmd_sta_send_frame_hs2_arpannounce(dut, conn, cmd, intf);
6315
6316 if (strcasecmp(type, "ARPReply") == 0)
6317 return cmd_sta_send_frame_hs2_arpreply(dut, conn, cmd, intf);
6318
6319 if (strcasecmp(type, "DLS-request") == 0 ||
6320 strcasecmp(type, "DLSrequest") == 0)
6321 return cmd_sta_send_frame_hs2_dls_req(dut, conn, cmd, intf,
6322 dest);
6323
6324 if (strcasecmp(type, "ANQPQuery") != 0 &&
6325 strcasecmp(type, "Query") != 0) {
6326 send_resp(dut, conn, SIGMA_ERROR,
6327 "ErrorCode,Unsupported HS 2.0 send frame type");
6328 return 0;
6329 }
6330
6331 if (sta_scan_ap(dut, intf, dest) < 0) {
6332 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find "
6333 "the requested AP");
6334 return 0;
6335 }
6336
6337 pos = buf;
6338 end = buf + sizeof(buf);
6339 count = 0;
6340 pos += snprintf(pos, end - pos, "ANQP_GET %s ", dest);
6341
6342 val = get_param(cmd, "ANQP_CAP_LIST");
6343 if (val && atoi(val)) {
6344 pos += snprintf(pos, end - pos, "%s257", count > 0 ? "," : "");
6345 count++;
6346 }
6347
6348 val = get_param(cmd, "VENUE_NAME");
6349 if (val && atoi(val)) {
6350 pos += snprintf(pos, end - pos, "%s258", count > 0 ? "," : "");
6351 count++;
6352 }
6353
6354 val = get_param(cmd, "NETWORK_AUTH_TYPE");
6355 if (val && atoi(val)) {
6356 pos += snprintf(pos, end - pos, "%s260", count > 0 ? "," : "");
6357 count++;
6358 }
6359
6360 val = get_param(cmd, "ROAMING_CONS");
6361 if (val && atoi(val)) {
6362 pos += snprintf(pos, end - pos, "%s261", count > 0 ? "," : "");
6363 count++;
6364 }
6365
6366 val = get_param(cmd, "IP_ADDR_TYPE_AVAILABILITY");
6367 if (val && atoi(val)) {
6368 pos += snprintf(pos, end - pos, "%s262", count > 0 ? "," : "");
6369 count++;
6370 }
6371
6372 val = get_param(cmd, "NAI_REALM_LIST");
6373 if (val && atoi(val)) {
6374 pos += snprintf(pos, end - pos, "%s263", count > 0 ? "," : "");
6375 count++;
6376 }
6377
6378 val = get_param(cmd, "3GPP_INFO");
6379 if (val && atoi(val)) {
6380 pos += snprintf(pos, end - pos, "%s264", count > 0 ? "," : "");
6381 count++;
6382 }
6383
6384 val = get_param(cmd, "DOMAIN_LIST");
6385 if (val && atoi(val)) {
6386 pos += snprintf(pos, end - pos, "%s268", count > 0 ? "," : "");
6387 count++;
6388 }
6389
6390 if (count && wpa_command(intf, buf)) {
6391 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,ANQP_GET failed");
6392 return 0;
6393 }
6394
6395 pos = buf;
6396 end = buf + sizeof(buf);
6397 count2 = 0;
6398 pos += snprintf(pos, end - pos, "HS20_ANQP_GET %s ", dest);
6399
6400 val = get_param(cmd, "HS_CAP_LIST");
6401 if (val && atoi(val)) {
6402 pos += snprintf(pos, end - pos, "%s2", count2 > 0 ? "," : "");
6403 count2++;
6404 }
6405
6406 val = get_param(cmd, "OPER_NAME");
6407 if (val && atoi(val)) {
6408 pos += snprintf(pos, end - pos, "%s3", count2 > 0 ? "," : "");
6409 count2++;
6410 }
6411
6412 val = get_param(cmd, "WAN_METRICS");
6413 if (!val)
6414 val = get_param(cmd, "WAN_MAT");
6415 if (!val)
6416 val = get_param(cmd, "WAN_MET");
6417 if (val && atoi(val)) {
6418 pos += snprintf(pos, end - pos, "%s4", count2 > 0 ? "," : "");
6419 count2++;
6420 }
6421
6422 val = get_param(cmd, "CONNECTION_CAPABILITY");
6423 if (val && atoi(val)) {
6424 pos += snprintf(pos, end - pos, "%s5", count2 > 0 ? "," : "");
6425 count2++;
6426 }
6427
6428 val = get_param(cmd, "OP_CLASS");
6429 if (val && atoi(val)) {
6430 pos += snprintf(pos, end - pos, "%s7", count2 > 0 ? "," : "");
6431 count2++;
6432 }
6433
6434 val = get_param(cmd, "OSU_PROVIDER_LIST");
6435 if (val && atoi(val)) {
6436 pos += snprintf(pos, end - pos, "%s8", count2 > 0 ? "," : "");
6437 count2++;
6438 }
6439
6440 if (count && count2) {
6441 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before sending out "
6442 "second query");
6443 sleep(1);
6444 }
6445
6446 if (count2 && wpa_command(intf, buf)) {
6447 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,HS20_ANQP_GET "
6448 "failed");
6449 return 0;
6450 }
6451
6452 val = get_param(cmd, "NAI_HOME_REALM_LIST");
6453 if (val) {
6454 if (count || count2) {
6455 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
6456 "sending out second query");
6457 sleep(1);
6458 }
6459
6460 if (strcmp(val, "1") == 0)
6461 val = "mail.example.com";
6462 snprintf(buf, end - pos,
6463 "HS20_GET_NAI_HOME_REALM_LIST %s realm=%s",
6464 dest, val);
6465 if (wpa_command(intf, buf)) {
6466 send_resp(dut, conn, SIGMA_ERROR,
6467 "ErrorCode,HS20_GET_NAI_HOME_REALM_LIST "
6468 "failed");
6469 return 0;
6470 }
6471 }
6472
6473 val = get_param(cmd, "ICON_REQUEST");
6474 if (val) {
6475 if (count || count2) {
6476 sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
6477 "sending out second query");
6478 sleep(1);
6479 }
6480
6481 snprintf(buf, end - pos,
6482 "HS20_ICON_REQUEST %s %s", dest, val);
6483 if (wpa_command(intf, buf)) {
6484 send_resp(dut, conn, SIGMA_ERROR,
6485 "ErrorCode,HS20_ICON_REQUEST failed");
6486 return 0;
6487 }
6488 }
6489
6490 return 1;
6491}
6492
6493
6494static int ath_sta_send_frame_vht(struct sigma_dut *dut,
6495 struct sigma_conn *conn,
6496 struct sigma_cmd *cmd)
6497{
6498 const char *val;
6499 char *ifname;
6500 char buf[100];
6501 int chwidth, nss;
6502
6503 val = get_param(cmd, "framename");
6504 if (!val)
6505 return -1;
6506 sigma_dut_print(dut, DUT_MSG_DEBUG, "framename is %s", val);
6507
6508 /* Command sequence to generate Op mode notification */
6509 if (val && strcasecmp(val, "Op_md_notif_frm") == 0) {
6510 ifname = get_station_ifname();
6511
6512 /* Disable STBC */
6513 snprintf(buf, sizeof(buf),
6514 "iwpriv %s tx_stbc 0", ifname);
6515 if (system(buf) != 0) {
6516 sigma_dut_print(dut, DUT_MSG_ERROR,
6517 "iwpriv tx_stbc 0 failed!");
6518 }
6519
6520 /* Extract Channel width */
6521 val = get_param(cmd, "Channel_width");
6522 if (val) {
6523 switch (atoi(val)) {
6524 case 20:
6525 chwidth = 0;
6526 break;
6527 case 40:
6528 chwidth = 1;
6529 break;
6530 case 80:
6531 chwidth = 2;
6532 break;
6533 case 160:
6534 chwidth = 3;
6535 break;
6536 default:
6537 chwidth = 2;
6538 break;
6539 }
6540
6541 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
6542 ifname, chwidth);
6543 if (system(buf) != 0) {
6544 sigma_dut_print(dut, DUT_MSG_ERROR,
6545 "iwpriv chwidth failed!");
6546 }
6547 }
6548
6549 /* Extract NSS */
6550 val = get_param(cmd, "NSS");
6551 if (val) {
6552 switch (atoi(val)) {
6553 case 1:
6554 nss = 1;
6555 break;
6556 case 2:
6557 nss = 3;
6558 break;
6559 case 3:
6560 nss = 7;
6561 break;
6562 default:
6563 /* We do not support NSS > 3 */
6564 nss = 3;
6565 break;
6566 }
6567 snprintf(buf, sizeof(buf),
6568 "iwpriv %s rxchainmask %d", ifname, nss);
6569 if (system(buf) != 0) {
6570 sigma_dut_print(dut, DUT_MSG_ERROR,
6571 "iwpriv rxchainmask failed!");
6572 }
6573 }
6574
6575 /* Opmode notify */
6576 snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", ifname);
6577 if (system(buf) != 0) {
6578 sigma_dut_print(dut, DUT_MSG_ERROR,
6579 "iwpriv opmode_notify failed!");
6580 } else {
6581 sigma_dut_print(dut, DUT_MSG_INFO,
6582 "Sent out the notify frame!");
6583 }
6584 }
6585
6586 return 1;
6587}
6588
6589
6590static int cmd_sta_send_frame_vht(struct sigma_dut *dut,
6591 struct sigma_conn *conn,
6592 struct sigma_cmd *cmd)
6593{
6594 switch (get_driver_type()) {
6595 case DRIVER_ATHEROS:
6596 return ath_sta_send_frame_vht(dut, conn, cmd);
6597 default:
6598 send_resp(dut, conn, SIGMA_ERROR,
6599 "errorCode,Unsupported sta_set_frame(VHT) with the current driver");
6600 return 0;
6601 }
6602}
6603
6604
Lior David0fe101e2017-03-09 16:09:50 +02006605#ifdef __linux__
6606int wil6210_send_frame_60g(struct sigma_dut *dut, struct sigma_conn *conn,
6607 struct sigma_cmd *cmd)
6608{
6609 const char *frame_name = get_param(cmd, "framename");
6610 const char *mac = get_param(cmd, "dest_mac");
6611
6612 if (!frame_name || !mac) {
6613 sigma_dut_print(dut, DUT_MSG_ERROR,
6614 "framename and dest_mac must be provided");
6615 return -1;
6616 }
6617
6618 if (strcasecmp(frame_name, "brp") == 0) {
6619 const char *l_rx = get_param(cmd, "L-RX");
6620 int l_rx_i;
6621
6622 if (!l_rx) {
6623 sigma_dut_print(dut, DUT_MSG_ERROR,
6624 "L-RX must be provided");
6625 return -1;
6626 }
6627 l_rx_i = atoi(l_rx);
6628
6629 sigma_dut_print(dut, DUT_MSG_INFO,
6630 "dev_send_frame: BRP-RX, dest_mac %s, L-RX %s",
6631 mac, l_rx);
6632 if (l_rx_i != 16) {
6633 sigma_dut_print(dut, DUT_MSG_ERROR,
6634 "unsupported L-RX: %s", l_rx);
6635 return -1;
6636 }
6637
6638 if (wil6210_send_brp_rx(dut, mac, l_rx_i))
6639 return -1;
6640 } else if (strcasecmp(frame_name, "ssw") == 0) {
6641 sigma_dut_print(dut, DUT_MSG_INFO,
6642 "dev_send_frame: SLS, dest_mac %s", mac);
6643 if (wil6210_send_sls(dut, mac))
6644 return -1;
6645 } else {
6646 sigma_dut_print(dut, DUT_MSG_ERROR,
6647 "unsupported frame type: %s", frame_name);
6648 return -1;
6649 }
6650
6651 return 1;
6652}
6653#endif /* __linux__ */
6654
6655
6656static int cmd_sta_send_frame_60g(struct sigma_dut *dut,
6657 struct sigma_conn *conn,
6658 struct sigma_cmd *cmd)
6659{
6660 switch (get_driver_type()) {
6661#ifdef __linux__
6662 case DRIVER_WIL6210:
6663 return wil6210_send_frame_60g(dut, conn, cmd);
6664#endif /* __linux__ */
6665 default:
6666 send_resp(dut, conn, SIGMA_ERROR,
6667 "errorCode,Unsupported sta_set_frame(60G) with the current driver");
6668 return 0;
6669 }
6670}
6671
6672
Ashwini Patildb59b3c2017-04-13 15:19:23 +05306673static int mbo_send_anqp_query(struct sigma_dut *dut, struct sigma_conn *conn,
6674 const char *intf, struct sigma_cmd *cmd)
6675{
6676 const char *val, *addr;
6677 char buf[100];
6678
6679 addr = get_param(cmd, "DestMac");
6680 if (!addr) {
6681 send_resp(dut, conn, SIGMA_INVALID,
6682 "ErrorCode,AP MAC address is missing");
6683 return 0;
6684 }
6685
6686 val = get_param(cmd, "ANQPQuery_ID");
6687 if (!val) {
6688 send_resp(dut, conn, SIGMA_INVALID,
6689 "ErrorCode,Missing ANQPQuery_ID");
6690 return 0;
6691 }
6692
6693 if (strcasecmp(val, "NeighborReportReq") == 0) {
6694 snprintf(buf, sizeof(buf), "ANQP_GET %s 272", addr);
6695 } else if (strcasecmp(val, "QueryListWithCellPref") == 0) {
6696 snprintf(buf, sizeof(buf), "ANQP_GET %s 272,mbo:2", addr);
6697 } else {
6698 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid ANQPQuery_ID: %s",
6699 val);
6700 send_resp(dut, conn, SIGMA_INVALID,
6701 "ErrorCode,Invalid ANQPQuery_ID");
6702 return 0;
6703 }
6704
Ashwini Patild174f2c2017-04-13 16:49:46 +05306705 /* Set gas_address3 field to IEEE 802.11-2012 standard compliant form
6706 * (Address3 = Wildcard BSSID when sent to not-associated AP;
6707 * if associated, AP BSSID).
6708 */
6709 if (wpa_command(intf, "SET gas_address3 1") < 0) {
6710 send_resp(dut, conn, SIGMA_ERROR,
6711 "ErrorCode,Failed to set gas_address3");
6712 return 0;
6713 }
6714
Ashwini Patildb59b3c2017-04-13 15:19:23 +05306715 if (wpa_command(intf, buf) < 0) {
6716 send_resp(dut, conn, SIGMA_ERROR,
6717 "ErrorCode,Failed to send ANQP query");
6718 return 0;
6719 }
6720
6721 return 1;
6722}
6723
6724
6725static int mbo_cmd_sta_send_frame(struct sigma_dut *dut,
6726 struct sigma_conn *conn,
6727 const char *intf,
6728 struct sigma_cmd *cmd)
6729{
6730 const char *val = get_param(cmd, "FrameName");
6731
6732 if (val && strcasecmp(val, "ANQPQuery") == 0)
6733 return mbo_send_anqp_query(dut, conn, intf, cmd);
6734
6735 return 2;
6736}
6737
6738
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006739int cmd_sta_send_frame(struct sigma_dut *dut, struct sigma_conn *conn,
6740 struct sigma_cmd *cmd)
6741{
6742 const char *intf = get_param(cmd, "Interface");
6743 const char *val;
6744 enum send_frame_type frame;
6745 enum send_frame_protection protected;
6746 char buf[100];
6747 unsigned char addr[ETH_ALEN];
6748 int res;
6749
6750 val = get_param(cmd, "program");
6751 if (val == NULL)
6752 val = get_param(cmd, "frame");
6753 if (val && strcasecmp(val, "TDLS") == 0)
6754 return cmd_sta_send_frame_tdls(dut, conn, cmd);
6755 if (val && (strcasecmp(val, "HS2") == 0 ||
6756 strcasecmp(val, "HS2-R2") == 0))
6757 return cmd_sta_send_frame_hs2(dut, conn, cmd);
6758 if (val && strcasecmp(val, "VHT") == 0)
6759 return cmd_sta_send_frame_vht(dut, conn, cmd);
priyadharshini gowthamand66913a2016-07-29 15:11:17 -07006760 if (val && strcasecmp(val, "LOC") == 0)
6761 return loc_cmd_sta_send_frame(dut, conn, cmd);
Lior David0fe101e2017-03-09 16:09:50 +02006762 if (val && strcasecmp(val, "60GHz") == 0)
6763 return cmd_sta_send_frame_60g(dut, conn, cmd);
Ashwini Patildb59b3c2017-04-13 15:19:23 +05306764 if (val && strcasecmp(val, "MBO") == 0) {
6765 res = mbo_cmd_sta_send_frame(dut, conn, intf, cmd);
6766 if (res != 2)
6767 return res;
6768 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006769
6770 val = get_param(cmd, "TD_DISC");
6771 if (val) {
6772 if (hwaddr_aton(val, addr) < 0)
6773 return -1;
6774 snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", val);
6775 if (wpa_command(intf, buf) < 0) {
6776 send_resp(dut, conn, SIGMA_ERROR,
6777 "ErrorCode,Failed to send TDLS discovery");
6778 return 0;
6779 }
6780 return 1;
6781 }
6782
6783 val = get_param(cmd, "TD_Setup");
6784 if (val) {
6785 if (hwaddr_aton(val, addr) < 0)
6786 return -1;
6787 snprintf(buf, sizeof(buf), "TDLS_SETUP %s", val);
6788 if (wpa_command(intf, buf) < 0) {
6789 send_resp(dut, conn, SIGMA_ERROR,
6790 "ErrorCode,Failed to start TDLS setup");
6791 return 0;
6792 }
6793 return 1;
6794 }
6795
6796 val = get_param(cmd, "TD_TearDown");
6797 if (val) {
6798 if (hwaddr_aton(val, addr) < 0)
6799 return -1;
6800 snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", val);
6801 if (wpa_command(intf, buf) < 0) {
6802 send_resp(dut, conn, SIGMA_ERROR,
6803 "ErrorCode,Failed to tear down TDLS link");
6804 return 0;
6805 }
6806 return 1;
6807 }
6808
6809 val = get_param(cmd, "TD_ChannelSwitch");
6810 if (val) {
6811 /* TODO */
6812 send_resp(dut, conn, SIGMA_ERROR,
6813 "ErrorCode,TD_ChannelSwitch not yet supported");
6814 return 0;
6815 }
6816
6817 val = get_param(cmd, "TD_NF");
6818 if (val) {
6819 /* TODO */
6820 send_resp(dut, conn, SIGMA_ERROR,
6821 "ErrorCode,TD_NF not yet supported");
6822 return 0;
6823 }
6824
6825 val = get_param(cmd, "PMFFrameType");
6826 if (val == NULL)
6827 val = get_param(cmd, "FrameName");
6828 if (val == NULL)
6829 val = get_param(cmd, "Type");
6830 if (val == NULL)
6831 return -1;
6832 if (strcasecmp(val, "disassoc") == 0)
6833 frame = DISASSOC;
6834 else if (strcasecmp(val, "deauth") == 0)
6835 frame = DEAUTH;
6836 else if (strcasecmp(val, "saquery") == 0)
6837 frame = SAQUERY;
6838 else if (strcasecmp(val, "auth") == 0)
6839 frame = AUTH;
6840 else if (strcasecmp(val, "assocreq") == 0)
6841 frame = ASSOCREQ;
6842 else if (strcasecmp(val, "reassocreq") == 0)
6843 frame = REASSOCREQ;
6844 else if (strcasecmp(val, "neigreq") == 0) {
6845 sigma_dut_print(dut, DUT_MSG_INFO, "Got neighbor request");
6846
6847 val = get_param(cmd, "ssid");
6848 if (val == NULL)
6849 return -1;
6850
6851 res = send_neighbor_request(dut, intf, val);
6852 if (res) {
6853 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
6854 "Failed to send neighbor report request");
6855 return 0;
6856 }
6857
6858 return 1;
Ashwini Patil5acd7382017-04-13 15:55:04 +05306859 } else if (strcasecmp(val, "transmgmtquery") == 0 ||
6860 strcasecmp(val, "BTMQuery") == 0) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006861 sigma_dut_print(dut, DUT_MSG_DEBUG,
6862 "Got Transition Management Query");
6863
Ashwini Patil5acd7382017-04-13 15:55:04 +05306864 res = send_trans_mgmt_query(dut, intf, cmd);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006865 if (res) {
6866 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
6867 "Failed to send Transition Management Query");
6868 return 0;
6869 }
6870
6871 return 1;
6872 } else {
6873 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6874 "PMFFrameType");
6875 return 0;
6876 }
6877
6878 val = get_param(cmd, "PMFProtected");
6879 if (val == NULL)
6880 val = get_param(cmd, "Protected");
6881 if (val == NULL)
6882 return -1;
6883 if (strcasecmp(val, "Correct-key") == 0 ||
6884 strcasecmp(val, "CorrectKey") == 0)
6885 protected = CORRECT_KEY;
6886 else if (strcasecmp(val, "IncorrectKey") == 0)
6887 protected = INCORRECT_KEY;
6888 else if (strcasecmp(val, "Unprotected") == 0)
6889 protected = UNPROTECTED;
6890 else {
6891 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
6892 "PMFProtected");
6893 return 0;
6894 }
6895
6896 if (protected != UNPROTECTED &&
6897 (frame == AUTH || frame == ASSOCREQ || frame == REASSOCREQ)) {
6898 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Impossible "
6899 "PMFProtected for auth/assocreq/reassocreq");
6900 return 0;
6901 }
6902
6903 if (if_nametoindex("sigmadut") == 0) {
6904 snprintf(buf, sizeof(buf),
6905 "iw dev %s interface add sigmadut type monitor",
6906 get_station_ifname());
6907 if (system(buf) != 0 ||
6908 if_nametoindex("sigmadut") == 0) {
6909 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
6910 "monitor interface with '%s'", buf);
6911 return -2;
6912 }
6913 }
6914
6915 if (system("ifconfig sigmadut up") != 0) {
6916 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
6917 "monitor interface up");
6918 return -2;
6919 }
6920
6921 return sta_inject_frame(dut, conn, frame, protected, NULL);
6922}
6923
6924
6925static int cmd_sta_set_parameter_hs2(struct sigma_dut *dut,
6926 struct sigma_conn *conn,
6927 struct sigma_cmd *cmd,
6928 const char *ifname)
6929{
6930 char buf[200];
6931 const char *val;
6932
6933 val = get_param(cmd, "ClearARP");
6934 if (val && atoi(val) == 1) {
6935 snprintf(buf, sizeof(buf), "ip neigh flush dev %s", ifname);
6936 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
6937 if (system(buf) != 0) {
6938 send_resp(dut, conn, SIGMA_ERROR,
6939 "errorCode,Failed to clear ARP cache");
6940 return 0;
6941 }
6942 }
6943
6944 return 1;
6945}
6946
6947
6948int cmd_sta_set_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
6949 struct sigma_cmd *cmd)
6950{
6951 const char *intf = get_param(cmd, "Interface");
6952 const char *val;
6953
6954 if (intf == NULL)
6955 return -1;
6956
6957 val = get_param(cmd, "program");
6958 if (val && (strcasecmp(val, "HS2") == 0 ||
6959 strcasecmp(val, "HS2-R2") == 0))
6960 return cmd_sta_set_parameter_hs2(dut, conn, cmd, intf);
6961
6962 return -1;
6963}
6964
6965
6966static int cmd_sta_set_macaddr(struct sigma_dut *dut, struct sigma_conn *conn,
6967 struct sigma_cmd *cmd)
6968{
6969 const char *intf = get_param(cmd, "Interface");
6970 const char *mac = get_param(cmd, "MAC");
6971
6972 if (intf == NULL || mac == NULL)
6973 return -1;
6974
6975 sigma_dut_print(dut, DUT_MSG_INFO, "Change local MAC address for "
6976 "interface %s to %s", intf, mac);
6977
6978 if (dut->set_macaddr) {
6979 char buf[128];
6980 int res;
6981 if (strcasecmp(mac, "default") == 0) {
6982 res = snprintf(buf, sizeof(buf), "%s",
6983 dut->set_macaddr);
6984 dut->tmp_mac_addr = 0;
6985 } else {
6986 res = snprintf(buf, sizeof(buf), "%s %s",
6987 dut->set_macaddr, mac);
6988 dut->tmp_mac_addr = 1;
6989 }
6990 if (res < 0 || res >= (int) sizeof(buf))
6991 return -1;
6992 if (system(buf) != 0) {
6993 send_resp(dut, conn, SIGMA_ERROR,
6994 "errorCode,Failed to set MAC "
6995 "address");
6996 return 0;
6997 }
6998 return 1;
6999 }
7000
7001 if (strcasecmp(mac, "default") == 0)
7002 return 1;
7003
7004 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
7005 "command");
7006 return 0;
7007}
7008
7009
7010static int iwpriv_tdlsoffchnmode(struct sigma_dut *dut,
7011 struct sigma_conn *conn, const char *intf,
7012 int val)
7013{
7014 char buf[200];
7015 int res;
7016
7017 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchnmode %d",
7018 intf, val);
7019 if (res < 0 || res >= (int) sizeof(buf))
7020 return -1;
7021 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7022 if (system(buf) != 0) {
7023 send_resp(dut, conn, SIGMA_ERROR,
7024 "errorCode,Failed to configure offchannel mode");
7025 return 0;
7026 }
7027
7028 return 1;
7029}
7030
7031
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007032static int off_chan_val(enum sec_ch_offset off)
7033{
7034 switch (off) {
7035 case SEC_CH_NO:
7036 return 0;
7037 case SEC_CH_40ABOVE:
7038 return 40;
7039 case SEC_CH_40BELOW:
7040 return -40;
7041 }
7042
7043 return 0;
7044}
7045
7046
7047static int iwpriv_set_offchan(struct sigma_dut *dut, struct sigma_conn *conn,
7048 const char *intf, int off_ch_num,
7049 enum sec_ch_offset sec)
7050{
7051 char buf[200];
7052 int res;
7053
7054 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchan %d",
7055 intf, off_ch_num);
7056 if (res < 0 || res >= (int) sizeof(buf))
7057 return -1;
7058 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7059 if (system(buf) != 0) {
7060 send_resp(dut, conn, SIGMA_ERROR,
7061 "errorCode,Failed to set offchan");
7062 return 0;
7063 }
7064
7065 res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsecchnoffst %d",
7066 intf, off_chan_val(sec));
7067 if (res < 0 || res >= (int) sizeof(buf))
7068 return -1;
7069 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7070 if (system(buf) != 0) {
7071 send_resp(dut, conn, SIGMA_ERROR,
7072 "errorCode,Failed to set sec chan offset");
7073 return 0;
7074 }
7075
7076 return 1;
7077}
7078
7079
7080static int tdls_set_offchannel_offset(struct sigma_dut *dut,
7081 struct sigma_conn *conn,
7082 const char *intf, int off_ch_num,
7083 enum sec_ch_offset sec)
7084{
7085 char buf[200];
7086 int res;
7087
7088 res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNEL %d",
7089 off_ch_num);
7090 if (res < 0 || res >= (int) sizeof(buf))
7091 return -1;
7092 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7093
7094 if (wpa_command(intf, buf) < 0) {
7095 send_resp(dut, conn, SIGMA_ERROR,
7096 "ErrorCode,Failed to set offchan");
7097 return 0;
7098 }
7099 res = snprintf(buf, sizeof(buf), "DRIVER TDLSSECONDARYCHANNELOFFSET %d",
7100 off_chan_val(sec));
7101 if (res < 0 || res >= (int) sizeof(buf))
7102 return -1;
7103
7104 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7105
7106 if (wpa_command(intf, buf) < 0) {
7107 send_resp(dut, conn, SIGMA_ERROR,
7108 "ErrorCode,Failed to set sec chan offset");
7109 return 0;
7110 }
7111
7112 return 1;
7113}
7114
7115
7116static int tdls_set_offchannel_mode(struct sigma_dut *dut,
7117 struct sigma_conn *conn,
7118 const char *intf, int val)
7119{
7120 char buf[200];
7121 int res;
7122
7123 res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNELMODE %d",
7124 val);
7125 if (res < 0 || res >= (int) sizeof(buf))
7126 return -1;
7127 sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
7128
7129 if (wpa_command(intf, buf) < 0) {
7130 send_resp(dut, conn, SIGMA_ERROR,
7131 "ErrorCode,Failed to configure offchannel mode");
7132 return 0;
7133 }
7134
7135 return 1;
7136}
7137
7138
7139static int cmd_sta_set_rfeature_tdls(const char *intf, struct sigma_dut *dut,
7140 struct sigma_conn *conn,
7141 struct sigma_cmd *cmd)
7142{
7143 const char *val;
7144 enum {
7145 CHSM_NOT_SET,
7146 CHSM_ENABLE,
7147 CHSM_DISABLE,
7148 CHSM_REJREQ,
7149 CHSM_UNSOLRESP
7150 } chsm = CHSM_NOT_SET;
7151 int off_ch_num = -1;
7152 enum sec_ch_offset sec_ch = SEC_CH_NO;
7153 int res;
7154
7155 val = get_param(cmd, "Uapsd");
7156 if (val) {
7157 char buf[100];
7158 if (strcasecmp(val, "Enable") == 0)
7159 snprintf(buf, sizeof(buf), "SET ps 99");
7160 else if (strcasecmp(val, "Disable") == 0)
7161 snprintf(buf, sizeof(buf), "SET ps 98");
7162 else {
7163 send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
7164 "Unsupported uapsd parameter value");
7165 return 0;
7166 }
7167 if (wpa_command(intf, buf)) {
7168 send_resp(dut, conn, SIGMA_ERROR,
7169 "ErrorCode,Failed to change U-APSD "
7170 "powersave mode");
7171 return 0;
7172 }
7173 }
7174
7175 val = get_param(cmd, "TPKTIMER");
7176 if (val && strcasecmp(val, "DISABLE") == 0) {
7177 if (wpa_command(intf, "SET tdls_testing 0x100")) {
7178 send_resp(dut, conn, SIGMA_ERROR,
7179 "ErrorCode,Failed to enable no TPK "
7180 "expiration test mode");
7181 return 0;
7182 }
7183 dut->no_tpk_expiration = 1;
7184 }
7185
7186 val = get_param(cmd, "ChSwitchMode");
7187 if (val) {
7188 if (strcasecmp(val, "Enable") == 0 ||
7189 strcasecmp(val, "Initiate") == 0)
7190 chsm = CHSM_ENABLE;
7191 else if (strcasecmp(val, "Disable") == 0 ||
7192 strcasecmp(val, "passive") == 0)
7193 chsm = CHSM_DISABLE;
7194 else if (strcasecmp(val, "RejReq") == 0)
7195 chsm = CHSM_REJREQ;
7196 else if (strcasecmp(val, "UnSolResp") == 0)
7197 chsm = CHSM_UNSOLRESP;
7198 else {
7199 send_resp(dut, conn, SIGMA_ERROR,
7200 "ErrorCode,Unknown ChSwitchMode value");
7201 return 0;
7202 }
7203 }
7204
7205 val = get_param(cmd, "OffChNum");
7206 if (val) {
7207 off_ch_num = atoi(val);
7208 if (off_ch_num == 0) {
7209 send_resp(dut, conn, SIGMA_ERROR,
7210 "ErrorCode,Invalid OffChNum");
7211 return 0;
7212 }
7213 }
7214
7215 val = get_param(cmd, "SecChOffset");
7216 if (val) {
7217 if (strcmp(val, "20") == 0)
7218 sec_ch = SEC_CH_NO;
7219 else if (strcasecmp(val, "40above") == 0)
7220 sec_ch = SEC_CH_40ABOVE;
7221 else if (strcasecmp(val, "40below") == 0)
7222 sec_ch = SEC_CH_40BELOW;
7223 else {
7224 send_resp(dut, conn, SIGMA_ERROR,
7225 "ErrorCode,Unknown SecChOffset value");
7226 return 0;
7227 }
7228 }
7229
7230 if (chsm == CHSM_NOT_SET) {
7231 /* no offchannel changes requested */
7232 return 1;
7233 }
7234
7235 if (strcmp(intf, get_main_ifname()) != 0 &&
7236 strcmp(intf, get_station_ifname()) != 0) {
7237 send_resp(dut, conn, SIGMA_ERROR,
7238 "ErrorCode,Unknown interface");
7239 return 0;
7240 }
7241
7242 switch (chsm) {
7243 case CHSM_NOT_SET:
Jouni Malinen280f5ba2016-08-29 21:33:10 +03007244 res = 1;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007245 break;
7246 case CHSM_ENABLE:
7247 if (off_ch_num < 0) {
7248 send_resp(dut, conn, SIGMA_ERROR,
7249 "ErrorCode,Missing OffChNum argument");
7250 return 0;
7251 }
7252 if (wifi_chip_type == DRIVER_WCN) {
7253 res = tdls_set_offchannel_offset(dut, conn, intf,
7254 off_ch_num, sec_ch);
7255 } else {
7256 res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
7257 sec_ch);
7258 }
7259 if (res != 1)
7260 return res;
7261 if (wifi_chip_type == DRIVER_WCN)
7262 res = tdls_set_offchannel_mode(dut, conn, intf, 1);
7263 else
7264 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 1);
7265 break;
7266 case CHSM_DISABLE:
7267 if (wifi_chip_type == DRIVER_WCN)
7268 res = tdls_set_offchannel_mode(dut, conn, intf, 2);
7269 else
7270 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 2);
7271 break;
7272 case CHSM_REJREQ:
7273 if (wifi_chip_type == DRIVER_WCN)
7274 res = tdls_set_offchannel_mode(dut, conn, intf, 3);
7275 else
7276 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 3);
7277 break;
7278 case CHSM_UNSOLRESP:
7279 if (off_ch_num < 0) {
7280 send_resp(dut, conn, SIGMA_ERROR,
7281 "ErrorCode,Missing OffChNum argument");
7282 return 0;
7283 }
7284 if (wifi_chip_type == DRIVER_WCN) {
7285 res = tdls_set_offchannel_offset(dut, conn, intf,
7286 off_ch_num, sec_ch);
7287 } else {
7288 res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
7289 sec_ch);
7290 }
7291 if (res != 1)
7292 return res;
7293 if (wifi_chip_type == DRIVER_WCN)
7294 res = tdls_set_offchannel_mode(dut, conn, intf, 4);
7295 else
7296 res = iwpriv_tdlsoffchnmode(dut, conn, intf, 4);
7297 break;
7298 }
7299
7300 return res;
7301}
7302
7303
7304static int ath_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
7305 struct sigma_conn *conn,
7306 struct sigma_cmd *cmd)
7307{
7308 const char *val;
7309 char *token, *result;
7310
priyadharshini gowthamane5e25172015-12-08 14:53:48 -08007311 novap_reset(dut, intf);
7312
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007313 val = get_param(cmd, "nss_mcs_opt");
7314 if (val) {
7315 /* String (nss_operating_mode; mcs_operating_mode) */
7316 int nss, mcs;
7317 char buf[50];
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05307318 char *saveptr;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007319
7320 token = strdup(val);
7321 if (!token)
7322 return 0;
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05307323 result = strtok_r(token, ";", &saveptr);
Pradeep Reddy POTTETI41b8c542016-06-15 16:09:46 +05307324 if (!result) {
7325 sigma_dut_print(dut, DUT_MSG_ERROR,
7326 "VHT NSS not specified");
7327 goto failed;
7328 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007329 if (strcasecmp(result, "def") != 0) {
7330 nss = atoi(result);
7331 if (nss == 4)
7332 ath_disable_txbf(dut, intf);
7333 snprintf(buf, sizeof(buf), "iwpriv %s nss %d",
7334 intf, nss);
7335 if (system(buf) != 0) {
7336 sigma_dut_print(dut, DUT_MSG_ERROR,
7337 "iwpriv nss failed");
7338 goto failed;
7339 }
7340 }
7341
Pradeep Reddy POTTETIdbf7d712016-04-28 18:42:07 +05307342 result = strtok_r(NULL, ";", &saveptr);
Pradeep Reddy POTTETI41b8c542016-06-15 16:09:46 +05307343 if (!result) {
7344 sigma_dut_print(dut, DUT_MSG_ERROR,
7345 "VHT MCS not specified");
7346 goto failed;
7347 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007348 if (strcasecmp(result, "def") == 0) {
7349 snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0",
7350 intf);
7351 if (system(buf) != 0) {
7352 sigma_dut_print(dut, DUT_MSG_ERROR,
7353 "iwpriv set11NRates failed");
7354 goto failed;
7355 }
7356
7357 } else {
7358 mcs = atoi(result);
7359 snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d",
7360 intf, mcs);
7361 if (system(buf) != 0) {
7362 sigma_dut_print(dut, DUT_MSG_ERROR,
7363 "iwpriv vhtmcs failed");
7364 goto failed;
7365 }
7366 }
7367 /* Channel width gets messed up, fix this */
7368 snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
7369 intf, dut->chwidth);
7370 if (system(buf) != 0) {
7371 sigma_dut_print(dut, DUT_MSG_ERROR,
7372 "iwpriv chwidth failed");
7373 }
7374 }
7375
7376 return 1;
7377failed:
7378 free(token);
7379 return 0;
7380}
7381
7382
7383static int cmd_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
7384 struct sigma_conn *conn,
7385 struct sigma_cmd *cmd)
7386{
7387 switch (get_driver_type()) {
7388 case DRIVER_ATHEROS:
7389 return ath_sta_set_rfeature_vht(intf, dut, conn, cmd);
7390 default:
7391 send_resp(dut, conn, SIGMA_ERROR,
7392 "errorCode,Unsupported sta_set_rfeature(VHT) with the current driver");
7393 return 0;
7394 }
7395}
7396
7397
Ashwini Patil5acd7382017-04-13 15:55:04 +05307398static int btm_query_candidate_list(struct sigma_dut *dut,
7399 struct sigma_conn *conn,
7400 struct sigma_cmd *cmd)
7401{
7402 const char *bssid, *info, *op_class, *ch, *phy_type, *pref;
7403 int len, ret;
7404 char buf[10];
7405
7406 /*
7407 * Neighbor Report elements format:
7408 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
7409 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
7410 * eg: neighbor=aa:bb:cc:dd:ee:ff,17,81,6,1,030101
7411 */
7412
7413 bssid = get_param(cmd, "Nebor_BSSID");
7414 if (!bssid) {
7415 send_resp(dut, conn, SIGMA_INVALID,
7416 "errorCode,Nebor_BSSID is missing");
7417 return 0;
7418 }
7419
7420 info = get_param(cmd, "Nebor_Bssid_Info");
7421 if (!info) {
7422 sigma_dut_print(dut, DUT_MSG_INFO,
7423 "Using default value for Nebor_Bssid_Info: %s",
7424 DEFAULT_NEIGHBOR_BSSID_INFO);
7425 info = DEFAULT_NEIGHBOR_BSSID_INFO;
7426 }
7427
7428 op_class = get_param(cmd, "Nebor_Op_Class");
7429 if (!op_class) {
7430 send_resp(dut, conn, SIGMA_INVALID,
7431 "errorCode,Nebor_Op_Class is missing");
7432 return 0;
7433 }
7434
7435 ch = get_param(cmd, "Nebor_Op_Ch");
7436 if (!ch) {
7437 send_resp(dut, conn, SIGMA_INVALID,
7438 "errorCode,Nebor_Op_Ch is missing");
7439 return 0;
7440 }
7441
7442 phy_type = get_param(cmd, "Nebor_Phy_Type");
7443 if (!phy_type) {
7444 sigma_dut_print(dut, DUT_MSG_INFO,
7445 "Using default value for Nebor_Phy_Type: %s",
7446 DEFAULT_NEIGHBOR_PHY_TYPE);
7447 phy_type = DEFAULT_NEIGHBOR_PHY_TYPE;
7448 }
7449
7450 /* Parse optional subelements */
7451 buf[0] = '\0';
7452 pref = get_param(cmd, "Nebor_Pref");
7453 if (pref) {
7454 /* hexdump for preferrence subelement */
7455 ret = snprintf(buf, sizeof(buf), ",0301%02x", atoi(pref));
7456 if (ret < 0 || ret >= (int) sizeof(buf)) {
7457 sigma_dut_print(dut, DUT_MSG_ERROR,
7458 "snprintf failed for optional subelement ret: %d",
7459 ret);
7460 send_resp(dut, conn, SIGMA_ERROR,
7461 "errorCode,snprintf failed for subelement");
7462 return 0;
7463 }
7464 }
7465
7466 if (!dut->btm_query_cand_list) {
7467 dut->btm_query_cand_list = calloc(1, NEIGHBOR_REPORT_SIZE);
7468 if (!dut->btm_query_cand_list) {
7469 send_resp(dut, conn, SIGMA_ERROR,
7470 "errorCode,Failed to allocate memory for btm_query_cand_list");
7471 return 0;
7472 }
7473 }
7474
7475 len = strlen(dut->btm_query_cand_list);
7476 ret = snprintf(dut->btm_query_cand_list + len,
7477 NEIGHBOR_REPORT_SIZE - len, " neighbor=%s,%s,%s,%s,%s%s",
7478 bssid, info, op_class, ch, phy_type, buf);
7479 if (ret < 0 || ret >= NEIGHBOR_REPORT_SIZE - len) {
7480 sigma_dut_print(dut, DUT_MSG_ERROR,
7481 "snprintf failed for neighbor report list ret: %d",
7482 ret);
7483 send_resp(dut, conn, SIGMA_ERROR,
7484 "errorCode,snprintf failed for neighbor report");
7485 free(dut->btm_query_cand_list);
7486 dut->btm_query_cand_list = NULL;
7487 return 0;
7488 }
7489
7490 return 1;
7491}
7492
7493
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007494static int cmd_sta_set_rfeature(struct sigma_dut *dut, struct sigma_conn *conn,
7495 struct sigma_cmd *cmd)
7496{
7497 const char *intf = get_param(cmd, "Interface");
7498 const char *prog = get_param(cmd, "Prog");
Ashwini Patil68d02cd2017-01-10 15:39:16 +05307499 const char *val;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007500
7501 if (intf == NULL || prog == NULL)
7502 return -1;
7503
Ashwini Patil5acd7382017-04-13 15:55:04 +05307504 /* BSS Transition candidate list for BTM query */
7505 val = get_param(cmd, "Nebor_BSSID");
7506 if (val && btm_query_candidate_list(dut, conn, cmd) == 0)
7507 return 0;
7508
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007509 if (strcasecmp(prog, "TDLS") == 0)
7510 return cmd_sta_set_rfeature_tdls(intf, dut, conn, cmd);
7511
7512 if (strcasecmp(prog, "VHT") == 0)
7513 return cmd_sta_set_rfeature_vht(intf, dut, conn, cmd);
7514
Ashwini Patil68d02cd2017-01-10 15:39:16 +05307515 if (strcasecmp(prog, "MBO") == 0) {
7516 val = get_param(cmd, "Cellular_Data_Cap");
7517 if (val &&
7518 mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
7519 return 0;
Ashwini Patil00402582017-04-13 12:29:39 +05307520
7521 val = get_param(cmd, "Ch_Pref");
7522 if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
7523 return 0;
7524
Ashwini Patil68d02cd2017-01-10 15:39:16 +05307525 return 1;
7526 }
7527
Jouni Malinencd4e3c32015-10-29 12:39:56 +02007528 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported Prog");
7529 return 0;
7530}
7531
7532
7533static int cmd_sta_set_radio(struct sigma_dut *dut, struct sigma_conn *conn,
7534 struct sigma_cmd *cmd)
7535{
7536 const char *intf = get_param(cmd, "Interface");
7537 const char *mode = get_param(cmd, "Mode");
7538 int res;
7539
7540 if (intf == NULL || mode == NULL)
7541 return -1;
7542
7543 if (strcasecmp(mode, "On") == 0)
7544 res = wpa_command(intf, "SET radio_disabled 0");
7545 else if (strcasecmp(mode, "Off") == 0)
7546 res = wpa_command(intf, "SET radio_disabled 1");
7547 else
7548 return -1;
7549
7550 if (res) {
7551 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
7552 "radio mode");
7553 return 0;
7554 }
7555
7556 return 1;
7557}
7558
7559
7560static int cmd_sta_set_pwrsave(struct sigma_dut *dut, struct sigma_conn *conn,
7561 struct sigma_cmd *cmd)
7562{
7563 const char *intf = get_param(cmd, "Interface");
7564 const char *mode = get_param(cmd, "Mode");
7565 int res;
7566
7567 if (intf == NULL || mode == NULL)
7568 return -1;
7569
7570 if (strcasecmp(mode, "On") == 0)
7571 res = set_ps(intf, dut, 1);
7572 else if (strcasecmp(mode, "Off") == 0)
7573 res = set_ps(intf, dut, 0);
7574 else
7575 return -1;
7576
7577 if (res) {
7578 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
7579 "power save mode");
7580 return 0;
7581 }
7582
7583 return 1;
7584}
7585
7586
7587static int cmd_sta_bssid_pool(struct sigma_dut *dut, struct sigma_conn *conn,
7588 struct sigma_cmd *cmd)
7589{
7590 const char *intf = get_param(cmd, "Interface");
7591 const char *val, *bssid;
7592 int res;
7593 char *buf;
7594 size_t buf_len;
7595
7596 val = get_param(cmd, "BSSID_FILTER");
7597 if (val == NULL)
7598 return -1;
7599
7600 bssid = get_param(cmd, "BSSID_List");
7601 if (atoi(val) == 0 || bssid == NULL) {
7602 /* Disable BSSID filter */
7603 if (wpa_command(intf, "SET bssid_filter ")) {
7604 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed "
7605 "to disable BSSID filter");
7606 return 0;
7607 }
7608
7609 return 1;
7610 }
7611
7612 buf_len = 100 + strlen(bssid);
7613 buf = malloc(buf_len);
7614 if (buf == NULL)
7615 return -1;
7616
7617 snprintf(buf, buf_len, "SET bssid_filter %s", bssid);
7618 res = wpa_command(intf, buf);
7619 free(buf);
7620 if (res) {
7621 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to enable "
7622 "BSSID filter");
7623 return 0;
7624 }
7625
7626 return 1;
7627}
7628
7629
7630static int cmd_sta_reset_parm(struct sigma_dut *dut, struct sigma_conn *conn,
7631 struct sigma_cmd *cmd)
7632{
7633 const char *intf = get_param(cmd, "Interface");
7634 const char *val;
7635
7636 /* TODO: ARP */
7637
7638 val = get_param(cmd, "HS2_CACHE_PROFILE");
7639 if (val && strcasecmp(val, "All") == 0)
7640 hs2_clear_credentials(intf);
7641
7642 return 1;
7643}
7644
7645
7646static int cmd_sta_get_key(struct sigma_dut *dut, struct sigma_conn *conn,
7647 struct sigma_cmd *cmd)
7648{
7649 const char *intf = get_param(cmd, "Interface");
7650 const char *key_type = get_param(cmd, "KeyType");
7651 char buf[100], resp[200];
7652
7653 if (key_type == NULL)
7654 return -1;
7655
7656 if (strcasecmp(key_type, "GTK") == 0) {
7657 if (wpa_command_resp(intf, "GET gtk", buf, sizeof(buf)) < 0 ||
7658 strncmp(buf, "FAIL", 4) == 0) {
7659 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7660 "not fetch current GTK");
7661 return 0;
7662 }
7663 snprintf(resp, sizeof(resp), "KeyValue,%s", buf);
7664 send_resp(dut, conn, SIGMA_COMPLETE, resp);
7665 return 0;
7666 } else {
7667 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
7668 "KeyType");
7669 return 0;
7670 }
7671
7672 return 1;
7673}
7674
7675
7676static int hs2_set_policy(struct sigma_dut *dut)
7677{
7678#ifdef ANDROID
7679 system("ip rule del prio 23000");
7680 if (system("ip rule add from all lookup main prio 23000") != 0) {
7681 sigma_dut_print(dut, DUT_MSG_ERROR,
7682 "Failed to run:ip rule add from all lookup main prio");
7683 return -1;
7684 }
7685 if (system("ip route flush cache") != 0) {
7686 sigma_dut_print(dut, DUT_MSG_ERROR,
7687 "Failed to run ip route flush cache");
7688 return -1;
7689 }
7690 return 1;
7691#else /* ANDROID */
7692 return 0;
7693#endif /* ANDROID */
7694}
7695
7696
7697static int cmd_sta_hs2_associate(struct sigma_dut *dut,
7698 struct sigma_conn *conn,
7699 struct sigma_cmd *cmd)
7700{
7701 const char *intf = get_param(cmd, "Interface");
7702 const char *val = get_param(cmd, "Ignore_blacklist");
7703 struct wpa_ctrl *ctrl;
7704 int res;
7705 char bssid[20], ssid[40], resp[100], buf[100], blacklisted[100];
7706 int tries = 0;
7707 int ignore_blacklist = 0;
7708 const char *events[] = {
7709 "CTRL-EVENT-CONNECTED",
7710 "INTERWORKING-BLACKLISTED",
7711 "INTERWORKING-NO-MATCH",
7712 NULL
7713 };
7714
7715 start_sta_mode(dut);
7716
7717 blacklisted[0] = '\0';
7718 if (val && atoi(val))
7719 ignore_blacklist = 1;
7720
7721try_again:
7722 ctrl = open_wpa_mon(intf);
7723 if (ctrl == NULL) {
7724 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
7725 "wpa_supplicant monitor connection");
7726 return -2;
7727 }
7728
7729 tries++;
7730 if (wpa_command(intf, "INTERWORKING_SELECT auto")) {
7731 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start "
7732 "Interworking connection");
7733 wpa_ctrl_detach(ctrl);
7734 wpa_ctrl_close(ctrl);
7735 return 0;
7736 }
7737
7738 buf[0] = '\0';
7739 while (1) {
7740 char *pos;
7741 res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
7742 pos = strstr(buf, "INTERWORKING-BLACKLISTED");
7743 if (!pos)
7744 break;
7745 pos += 25;
7746 sigma_dut_print(dut, DUT_MSG_DEBUG, "Found blacklisted AP: %s",
7747 pos);
7748 if (!blacklisted[0])
7749 memcpy(blacklisted, pos, strlen(pos) + 1);
7750 }
7751
7752 if (ignore_blacklist && blacklisted[0]) {
7753 char *end;
7754 end = strchr(blacklisted, ' ');
7755 if (end)
7756 *end = '\0';
7757 sigma_dut_print(dut, DUT_MSG_DEBUG, "Try to connect to a blacklisted network: %s",
7758 blacklisted);
7759 snprintf(buf, sizeof(buf), "INTERWORKING_CONNECT %s",
7760 blacklisted);
7761 if (wpa_command(intf, buf)) {
7762 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start Interworking connection to blacklisted network");
7763 wpa_ctrl_detach(ctrl);
7764 wpa_ctrl_close(ctrl);
7765 return 0;
7766 }
7767 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
7768 buf, sizeof(buf));
7769 }
7770
7771 wpa_ctrl_detach(ctrl);
7772 wpa_ctrl_close(ctrl);
7773
7774 if (res < 0) {
7775 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
7776 "connect");
7777 return 0;
7778 }
7779
7780 if (strstr(buf, "INTERWORKING-NO-MATCH") ||
7781 strstr(buf, "INTERWORKING-BLACKLISTED")) {
7782 if (tries < 2) {
7783 sigma_dut_print(dut, DUT_MSG_INFO, "No match found - try again to verify no APs were missed in the scan");
7784 goto try_again;
7785 }
7786 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,No network with "
7787 "matching credentials found");
7788 return 0;
7789 }
7790
7791 if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
7792 get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
7793 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
7794 "get current BSSID/SSID");
7795 return 0;
7796 }
7797
7798 snprintf(resp, sizeof(resp), "SSID,%s,BSSID,%s", ssid, bssid);
7799 send_resp(dut, conn, SIGMA_COMPLETE, resp);
7800 hs2_set_policy(dut);
7801 return 0;
7802}
7803
7804
7805static int sta_add_credential_uname_pwd(struct sigma_dut *dut,
7806 struct sigma_conn *conn,
7807 const char *ifname,
7808 struct sigma_cmd *cmd)
7809{
7810 const char *val;
7811 int id;
7812
7813 id = add_cred(ifname);
7814 if (id < 0)
7815 return -2;
7816 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
7817
7818 val = get_param(cmd, "prefer");
7819 if (val && atoi(val) > 0)
7820 set_cred(ifname, id, "priority", "1");
7821
7822 val = get_param(cmd, "REALM");
7823 if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
7824 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7825 "realm");
7826 return 0;
7827 }
7828
7829 val = get_param(cmd, "HOME_FQDN");
7830 if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
7831 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7832 "home_fqdn");
7833 return 0;
7834 }
7835
7836 val = get_param(cmd, "Username");
7837 if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
7838 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7839 "username");
7840 return 0;
7841 }
7842
7843 val = get_param(cmd, "Password");
7844 if (val && set_cred_quoted(ifname, id, "password", val) < 0) {
7845 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
7846 "password");
7847 return 0;
7848 }
7849
7850 val = get_param(cmd, "ROOT_CA");
7851 if (val) {
7852 char fname[200];
7853 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
7854#ifdef __linux__
7855 if (!file_exists(fname)) {
7856 char msg[300];
7857 snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
7858 "file (%s) not found", fname);
7859 send_resp(dut, conn, SIGMA_ERROR, msg);
7860 return 0;
7861 }
7862#endif /* __linux__ */
7863 if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
7864 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7865 "not set root CA");
7866 return 0;
7867 }
7868 }
7869
7870 return 1;
7871}
7872
7873
7874static int update_devdetail_imsi(struct sigma_dut *dut, const char *imsi)
7875{
7876 FILE *in, *out;
7877 char buf[500];
7878 int found = 0;
7879
7880 in = fopen("devdetail.xml", "r");
7881 if (in == NULL)
7882 return -1;
7883 out = fopen("devdetail.xml.tmp", "w");
7884 if (out == NULL) {
7885 fclose(in);
7886 return -1;
7887 }
7888
7889 while (fgets(buf, sizeof(buf), in)) {
7890 char *pos = strstr(buf, "<IMSI>");
7891 if (pos) {
7892 sigma_dut_print(dut, DUT_MSG_INFO, "Updated DevDetail IMSI to %s",
7893 imsi);
7894 pos += 6;
7895 *pos = '\0';
7896 fprintf(out, "%s%s</IMSI>\n", buf, imsi);
7897 found++;
7898 } else {
7899 fprintf(out, "%s", buf);
7900 }
7901 }
7902
7903 fclose(out);
7904 fclose(in);
7905 if (found)
7906 rename("devdetail.xml.tmp", "devdetail.xml");
7907 else
7908 unlink("devdetail.xml.tmp");
7909
7910 return 0;
7911}
7912
7913
7914static int sta_add_credential_sim(struct sigma_dut *dut,
7915 struct sigma_conn *conn,
7916 const char *ifname, struct sigma_cmd *cmd)
7917{
7918 const char *val, *imsi = NULL;
7919 int id;
7920 char buf[200];
7921 int res;
7922 const char *pos;
7923 size_t mnc_len;
7924 char plmn_mcc[4];
7925 char plmn_mnc[4];
7926
7927 id = add_cred(ifname);
7928 if (id < 0)
7929 return -2;
7930 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
7931
7932 val = get_param(cmd, "prefer");
7933 if (val && atoi(val) > 0)
7934 set_cred(ifname, id, "priority", "1");
7935
7936 val = get_param(cmd, "PLMN_MCC");
7937 if (val == NULL) {
7938 send_resp(dut, conn, SIGMA_ERROR,
7939 "errorCode,Missing PLMN_MCC");
7940 return 0;
7941 }
7942 if (strlen(val) != 3) {
7943 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MCC");
7944 return 0;
7945 }
7946 snprintf(plmn_mcc, sizeof(plmn_mcc), "%s", val);
7947
7948 val = get_param(cmd, "PLMN_MNC");
7949 if (val == NULL) {
7950 send_resp(dut, conn, SIGMA_ERROR,
7951 "errorCode,Missing PLMN_MNC");
7952 return 0;
7953 }
7954 if (strlen(val) != 2 && strlen(val) != 3) {
7955 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MNC");
7956 return 0;
7957 }
7958 snprintf(plmn_mnc, sizeof(plmn_mnc), "%s", val);
7959
7960 val = get_param(cmd, "IMSI");
7961 if (val == NULL) {
7962 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing SIM "
7963 "IMSI");
7964 return 0;
7965 }
7966
7967 imsi = pos = val;
7968
7969 if (strncmp(plmn_mcc, pos, 3) != 0) {
7970 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MCC mismatch");
7971 return 0;
7972 }
7973 pos += 3;
7974
7975 mnc_len = strlen(plmn_mnc);
7976 if (mnc_len < 2) {
7977 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC not set");
7978 return 0;
7979 }
7980
7981 if (strncmp(plmn_mnc, pos, mnc_len) != 0) {
7982 send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC mismatch");
7983 return 0;
7984 }
7985 pos += mnc_len;
7986
7987 res = snprintf(buf, sizeof(buf), "%s%s-%s",plmn_mcc, plmn_mnc, pos);
7988 if (res < 0 || res >= (int) sizeof(buf))
7989 return -1;
7990 if (set_cred_quoted(ifname, id, "imsi", buf) < 0) {
7991 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7992 "not set IMSI");
7993 return 0;
7994 }
7995
7996 val = get_param(cmd, "Password");
7997 if (val && set_cred_quoted(ifname, id, "milenage", val) < 0) {
7998 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
7999 "not set password");
8000 return 0;
8001 }
8002
8003 if (dut->program == PROGRAM_HS2_R2) {
8004 /*
8005 * Set provisioning_sp for the test cases where SIM/USIM
8006 * provisioning is used.
8007 */
8008 if (val && set_cred_quoted(ifname, id, "provisioning_sp",
8009 "wi-fi.org") < 0) {
8010 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8011 "not set provisioning_sp");
8012 return 0;
8013 }
8014
8015 update_devdetail_imsi(dut, imsi);
8016 }
8017
8018 return 1;
8019}
8020
8021
8022static int sta_add_credential_cert(struct sigma_dut *dut,
8023 struct sigma_conn *conn,
8024 const char *ifname,
8025 struct sigma_cmd *cmd)
8026{
8027 const char *val;
8028 int id;
8029
8030 id = add_cred(ifname);
8031 if (id < 0)
8032 return -2;
8033 sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
8034
8035 val = get_param(cmd, "prefer");
8036 if (val && atoi(val) > 0)
8037 set_cred(ifname, id, "priority", "1");
8038
8039 val = get_param(cmd, "REALM");
8040 if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
8041 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
8042 "realm");
8043 return 0;
8044 }
8045
8046 val = get_param(cmd, "HOME_FQDN");
8047 if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
8048 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
8049 "home_fqdn");
8050 return 0;
8051 }
8052
8053 val = get_param(cmd, "Username");
8054 if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
8055 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
8056 "username");
8057 return 0;
8058 }
8059
8060 val = get_param(cmd, "clientCertificate");
8061 if (val) {
8062 char fname[200];
8063 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
8064#ifdef __linux__
8065 if (!file_exists(fname)) {
8066 char msg[300];
8067 snprintf(msg, sizeof(msg),
8068 "ErrorCode,clientCertificate "
8069 "file (%s) not found", fname);
8070 send_resp(dut, conn, SIGMA_ERROR, msg);
8071 return 0;
8072 }
8073#endif /* __linux__ */
8074 if (set_cred_quoted(ifname, id, "client_cert", fname) < 0) {
8075 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8076 "not set client_cert");
8077 return 0;
8078 }
8079 if (set_cred_quoted(ifname, id, "private_key", fname) < 0) {
8080 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8081 "not set private_key");
8082 return 0;
8083 }
8084 }
8085
8086 val = get_param(cmd, "ROOT_CA");
8087 if (val) {
8088 char fname[200];
8089 snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
8090#ifdef __linux__
8091 if (!file_exists(fname)) {
8092 char msg[300];
8093 snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
8094 "file (%s) not found", fname);
8095 send_resp(dut, conn, SIGMA_ERROR, msg);
8096 return 0;
8097 }
8098#endif /* __linux__ */
8099 if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
8100 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
8101 "not set root CA");
8102 return 0;
8103 }
8104 }
8105
8106 return 1;
8107}
8108
8109
8110static int cmd_sta_add_credential(struct sigma_dut *dut,
8111 struct sigma_conn *conn,
8112 struct sigma_cmd *cmd)
8113{
8114 const char *intf = get_param(cmd, "Interface");
8115 const char *type;
8116
8117 start_sta_mode(dut);
8118
8119 type = get_param(cmd, "Type");
8120 if (!type)
8121 return -1;
8122
8123 if (strcasecmp(type, "uname_pwd") == 0)
8124 return sta_add_credential_uname_pwd(dut, conn, intf, cmd);
8125
8126 if (strcasecmp(type, "sim") == 0)
8127 return sta_add_credential_sim(dut, conn, intf, cmd);
8128
8129 if (strcasecmp(type, "cert") == 0)
8130 return sta_add_credential_cert(dut, conn, intf, cmd);
8131
8132 send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported credential "
8133 "type");
8134 return 0;
8135}
8136
8137
8138static int cmd_sta_scan(struct sigma_dut *dut, struct sigma_conn *conn,
8139 struct sigma_cmd *cmd)
8140{
8141 const char *intf = get_param(cmd, "Interface");
8142 const char *val;
8143 char buf[100];
8144 int res;
8145
8146 val = get_param(cmd, "HESSID");
8147 if (val) {
8148 res = snprintf(buf, sizeof(buf), "SET hessid %s", val);
8149 if (res < 0 || res >= (int) sizeof(buf))
8150 return -1;
8151 wpa_command(intf, buf);
8152 }
8153
8154 val = get_param(cmd, "ACCS_NET_TYPE");
8155 if (val) {
8156 res = snprintf(buf, sizeof(buf), "SET access_network_type %s",
8157 val);
8158 if (res < 0 || res >= (int) sizeof(buf))
8159 return -1;
8160 wpa_command(intf, buf);
8161 }
8162
8163 if (wpa_command(intf, "SCAN")) {
8164 send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not start "
8165 "scan");
8166 return 0;
8167 }
8168
8169 return 1;
8170}
8171
8172
8173static int cmd_sta_set_systime(struct sigma_dut *dut, struct sigma_conn *conn,
8174 struct sigma_cmd *cmd)
8175{
8176#ifdef __linux__
8177 struct timeval tv;
8178 struct tm tm;
8179 time_t t;
8180 const char *val;
Pradeep Reddy POTTETI429c69e2016-10-13 17:22:03 +05308181 int v;
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008182
8183 wpa_command(get_station_ifname(), "PMKSA_FLUSH");
8184
8185 memset(&tm, 0, sizeof(tm));
8186 val = get_param(cmd, "seconds");
8187 if (val)
8188 tm.tm_sec = atoi(val);
8189 val = get_param(cmd, "minutes");
8190 if (val)
8191 tm.tm_min = atoi(val);
8192 val = get_param(cmd, "hours");
8193 if (val)
8194 tm.tm_hour = atoi(val);
8195 val = get_param(cmd, "date");
8196 if (val)
8197 tm.tm_mday = atoi(val);
8198 val = get_param(cmd, "month");
Pradeep Reddy POTTETI429c69e2016-10-13 17:22:03 +05308199 if (val) {
8200 v = atoi(val);
8201 if (v < 1 || v > 12) {
8202 send_resp(dut, conn, SIGMA_INVALID,
8203 "errorCode,Invalid month");
8204 return 0;
8205 }
8206 tm.tm_mon = v - 1;
8207 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008208 val = get_param(cmd, "year");
8209 if (val) {
8210 int year = atoi(val);
8211#ifdef ANDROID
8212 if (year > 2035)
8213 year = 2035; /* years beyond 2035 not supported */
8214#endif /* ANDROID */
8215 tm.tm_year = year - 1900;
8216 }
8217 t = mktime(&tm);
8218 if (t == (time_t) -1) {
8219 send_resp(dut, conn, SIGMA_ERROR,
8220 "errorCode,Invalid date or time");
8221 return 0;
8222 }
8223
8224 memset(&tv, 0, sizeof(tv));
8225 tv.tv_sec = t;
8226
8227 if (settimeofday(&tv, NULL) < 0) {
8228 sigma_dut_print(dut, DUT_MSG_INFO, "settimeofday failed: %s",
8229 strerror(errno));
8230 send_resp(dut, conn, SIGMA_ERROR,
8231 "errorCode,Failed to set time");
8232 return 0;
8233 }
8234
8235 return 1;
8236#endif /* __linux__ */
8237
8238 return -1;
8239}
8240
8241
8242static int cmd_sta_osu(struct sigma_dut *dut, struct sigma_conn *conn,
8243 struct sigma_cmd *cmd)
8244{
8245 const char *intf = get_param(cmd, "Interface");
8246 const char *name, *val;
8247 int prod_ess_assoc = 1;
8248 char buf[200], bssid[100], ssid[100];
8249 int res;
8250 struct wpa_ctrl *ctrl;
8251
8252 name = get_param(cmd, "osuFriendlyName");
8253
8254 val = get_param(cmd, "ProdESSAssoc");
8255 if (val)
8256 prod_ess_assoc = atoi(val);
8257
8258 kill_dhcp_client(dut, intf);
8259 if (start_dhcp_client(dut, intf) < 0)
8260 return -2;
8261
8262 sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger OSU");
8263 mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
8264 res = snprintf(buf, sizeof(buf),
8265 "%s %s%s%s signup osu-ca.pem",
8266 prod_ess_assoc ? "" : "-N",
8267 name ? "-O'" : "", name ? name : "",
8268 name ? "'" : "");
8269
Kanchanapally, Vidyullatha12b66762015-12-31 16:46:42 +05308270 hs2_set_policy(dut);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008271 if (run_hs20_osu(dut, buf) < 0) {
8272 FILE *f;
8273
8274 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to complete OSU");
8275
8276 f = fopen("hs20-osu-client.res", "r");
8277 if (f) {
8278 char resp[400], res[300], *pos;
8279 if (!fgets(res, sizeof(res), f))
8280 res[0] = '\0';
8281 pos = strchr(res, '\n');
8282 if (pos)
8283 *pos = '\0';
8284 fclose(f);
8285 sigma_dut_summary(dut, "hs20-osu-client provisioning failed: %s",
8286 res);
8287 snprintf(resp, sizeof(resp), "notify-send '%s'", res);
8288 if (system(resp) != 0) {
8289 }
8290 snprintf(resp, sizeof(resp),
8291 "SSID,,BSSID,,failureReason,%s", res);
8292 send_resp(dut, conn, SIGMA_COMPLETE, resp);
8293 return 0;
8294 }
8295
8296 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
8297 return 0;
8298 }
8299
8300 if (!prod_ess_assoc)
8301 goto report;
8302
8303 ctrl = open_wpa_mon(intf);
8304 if (ctrl == NULL) {
8305 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
8306 "wpa_supplicant monitor connection");
8307 return -1;
8308 }
8309
8310 res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
8311 buf, sizeof(buf));
8312
8313 wpa_ctrl_detach(ctrl);
8314 wpa_ctrl_close(ctrl);
8315
8316 if (res < 0) {
8317 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to connect to "
8318 "network after OSU");
8319 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
8320 return 0;
8321 }
8322
8323report:
8324 if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
8325 get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
8326 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get BSSID/SSID");
8327 send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
8328 return 0;
8329 }
8330
8331 snprintf(buf, sizeof(buf), "SSID,%s,BSSID,%s", ssid, bssid);
8332 send_resp(dut, conn, SIGMA_COMPLETE, buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +02008333 return 0;
8334}
8335
8336
8337static int cmd_sta_policy_update(struct sigma_dut *dut, struct sigma_conn *conn,
8338 struct sigma_cmd *cmd)
8339{
8340 const char *val;
8341 int timeout = 120;
8342
8343 val = get_param(cmd, "PolicyUpdate");
8344 if (val == NULL || atoi(val) == 0)
8345 return 1; /* No operation requested */
8346
8347 val = get_param(cmd, "Timeout");
8348 if (val)
8349 timeout = atoi(val);
8350
8351 if (timeout) {
8352 /* TODO: time out the command and return
8353 * PolicyUpdateStatus,TIMEOUT if needed. */
8354 }
8355
8356 sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger policy update");
8357 mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
8358 if (run_hs20_osu(dut, "pol_upd fqdn=wi-fi.org") < 0) {
8359 send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,FAIL");
8360 return 0;
8361 }
8362
8363 send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,SUCCESS");
8364 return 0;
8365}
8366
8367
8368static int cmd_sta_er_config(struct sigma_dut *dut, struct sigma_conn *conn,
8369 struct sigma_cmd *cmd)
8370{
8371 struct wpa_ctrl *ctrl;
8372 const char *intf = get_param(cmd, "Interface");
8373 const char *bssid = get_param(cmd, "Bssid");
8374 const char *ssid = get_param(cmd, "SSID");
8375 const char *security = get_param(cmd, "Security");
8376 const char *passphrase = get_param(cmd, "Passphrase");
8377 const char *pin = get_param(cmd, "PIN");
8378 char buf[1000];
8379 char ssid_hex[200], passphrase_hex[200];
8380 const char *keymgmt, *cipher;
8381
8382 if (intf == NULL)
8383 intf = get_main_ifname();
8384
8385 if (!bssid) {
8386 send_resp(dut, conn, SIGMA_ERROR,
8387 "ErrorCode,Missing Bssid argument");
8388 return 0;
8389 }
8390
8391 if (!ssid) {
8392 send_resp(dut, conn, SIGMA_ERROR,
8393 "ErrorCode,Missing SSID argument");
8394 return 0;
8395 }
8396
8397 if (!security) {
8398 send_resp(dut, conn, SIGMA_ERROR,
8399 "ErrorCode,Missing Security argument");
8400 return 0;
8401 }
8402
8403 if (!passphrase) {
8404 send_resp(dut, conn, SIGMA_ERROR,
8405 "ErrorCode,Missing Passphrase argument");
8406 return 0;
8407 }
8408
8409 if (!pin) {
8410 send_resp(dut, conn, SIGMA_ERROR,
8411 "ErrorCode,Missing PIN argument");
8412 return 0;
8413 }
8414
8415 if (strlen(ssid) >= 2 * sizeof(ssid_hex) ||
8416 strlen(passphrase) >= 2 * sizeof(passphrase_hex)) {
8417 send_resp(dut, conn, SIGMA_ERROR,
8418 "ErrorCode,Too long SSID/passphrase");
8419 return 0;
8420 }
8421
8422 ctrl = open_wpa_mon(intf);
8423 if (ctrl == NULL) {
8424 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
8425 "wpa_supplicant monitor connection");
8426 return -2;
8427 }
8428
8429 if (strcasecmp(security, "wpa2-psk") == 0) {
8430 keymgmt = "WPA2PSK";
8431 cipher = "CCMP";
8432 } else {
8433 wpa_ctrl_detach(ctrl);
8434 wpa_ctrl_close(ctrl);
8435 send_resp(dut, conn, SIGMA_ERROR,
8436 "ErrorCode,Unsupported Security value");
8437 return 0;
8438 }
8439
8440 ascii2hexstr(ssid, ssid_hex);
8441 ascii2hexstr(passphrase, passphrase_hex);
8442 snprintf(buf, sizeof(buf), "WPS_REG %s %s %s %s %s %s",
8443 bssid, pin, ssid_hex, keymgmt, cipher, passphrase_hex);
8444
8445 if (wpa_command(intf, buf) < 0) {
8446 wpa_ctrl_detach(ctrl);
8447 wpa_ctrl_close(ctrl);
8448 send_resp(dut, conn, SIGMA_ERROR,
8449 "ErrorCode,Failed to start registrar");
8450 return 0;
8451 }
8452
8453 snprintf(dut->er_oper_bssid, sizeof(dut->er_oper_bssid), "%s", bssid);
8454 dut->er_oper_performed = 1;
8455
8456 return wps_connection_event(dut, conn, ctrl, intf, 0);
8457}
8458
8459
8460static int cmd_sta_wps_connect_pw_token(struct sigma_dut *dut,
8461 struct sigma_conn *conn,
8462 struct sigma_cmd *cmd)
8463{
8464 struct wpa_ctrl *ctrl;
8465 const char *intf = get_param(cmd, "Interface");
8466 const char *bssid = get_param(cmd, "Bssid");
8467 char buf[100];
8468
8469 if (!bssid) {
8470 send_resp(dut, conn, SIGMA_ERROR,
8471 "ErrorCode,Missing Bssid argument");
8472 return 0;
8473 }
8474
8475 ctrl = open_wpa_mon(intf);
8476 if (ctrl == NULL) {
8477 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
8478 "wpa_supplicant monitor connection");
8479 return -2;
8480 }
8481
8482 snprintf(buf, sizeof(buf), "WPS_NFC %s", bssid);
8483
8484 if (wpa_command(intf, buf) < 0) {
8485 wpa_ctrl_detach(ctrl);
8486 wpa_ctrl_close(ctrl);
8487 send_resp(dut, conn, SIGMA_ERROR,
8488 "ErrorCode,Failed to start registrar");
8489 return 0;
8490 }
8491
8492 return wps_connection_event(dut, conn, ctrl, intf, 0);
8493}
8494
8495
8496static int req_intf(struct sigma_cmd *cmd)
8497{
8498 return get_param(cmd, "interface") == NULL ? -1 : 0;
8499}
8500
8501
8502void sta_register_cmds(void)
8503{
8504 sigma_dut_reg_cmd("sta_get_ip_config", req_intf,
8505 cmd_sta_get_ip_config);
8506 sigma_dut_reg_cmd("sta_set_ip_config", req_intf,
8507 cmd_sta_set_ip_config);
8508 sigma_dut_reg_cmd("sta_get_info", req_intf, cmd_sta_get_info);
8509 sigma_dut_reg_cmd("sta_get_mac_address", req_intf,
8510 cmd_sta_get_mac_address);
8511 sigma_dut_reg_cmd("sta_is_connected", req_intf, cmd_sta_is_connected);
8512 sigma_dut_reg_cmd("sta_verify_ip_connection", req_intf,
8513 cmd_sta_verify_ip_connection);
8514 sigma_dut_reg_cmd("sta_get_bssid", req_intf, cmd_sta_get_bssid);
8515 sigma_dut_reg_cmd("sta_set_encryption", req_intf,
8516 cmd_sta_set_encryption);
8517 sigma_dut_reg_cmd("sta_set_psk", req_intf, cmd_sta_set_psk);
8518 sigma_dut_reg_cmd("sta_set_eaptls", req_intf, cmd_sta_set_eaptls);
8519 sigma_dut_reg_cmd("sta_set_eapttls", req_intf, cmd_sta_set_eapttls);
8520 sigma_dut_reg_cmd("sta_set_eapsim", req_intf, cmd_sta_set_eapsim);
8521 sigma_dut_reg_cmd("sta_set_peap", req_intf, cmd_sta_set_peap);
8522 sigma_dut_reg_cmd("sta_set_eapfast", req_intf, cmd_sta_set_eapfast);
8523 sigma_dut_reg_cmd("sta_set_eapaka", req_intf, cmd_sta_set_eapaka);
8524 sigma_dut_reg_cmd("sta_set_eapakaprime", req_intf,
8525 cmd_sta_set_eapakaprime);
8526 sigma_dut_reg_cmd("sta_set_security", req_intf, cmd_sta_set_security);
8527 sigma_dut_reg_cmd("sta_set_uapsd", req_intf, cmd_sta_set_uapsd);
8528 /* TODO: sta_set_ibss */
8529 /* TODO: sta_set_mode */
8530 sigma_dut_reg_cmd("sta_set_wmm", req_intf, cmd_sta_set_wmm);
8531 sigma_dut_reg_cmd("sta_associate", req_intf, cmd_sta_associate);
8532 /* TODO: sta_up_load */
8533 sigma_dut_reg_cmd("sta_preset_testparameters", req_intf,
8534 cmd_sta_preset_testparameters);
8535 /* TODO: sta_set_system */
8536 sigma_dut_reg_cmd("sta_set_11n", req_intf, cmd_sta_set_11n);
8537 /* TODO: sta_set_rifs_test */
8538 sigma_dut_reg_cmd("sta_set_wireless", req_intf, cmd_sta_set_wireless);
8539 sigma_dut_reg_cmd("sta_send_addba", req_intf, cmd_sta_send_addba);
8540 /* TODO: sta_send_coexist_mgmt */
8541 sigma_dut_reg_cmd("sta_disconnect", req_intf, cmd_sta_disconnect);
8542 sigma_dut_reg_cmd("sta_reassoc", req_intf, cmd_sta_reassoc);
8543 sigma_dut_reg_cmd("sta_reassociate", req_intf, cmd_sta_reassoc);
8544 sigma_dut_reg_cmd("sta_reset_default", req_intf,
8545 cmd_sta_reset_default);
8546 sigma_dut_reg_cmd("sta_send_frame", req_intf, cmd_sta_send_frame);
8547 sigma_dut_reg_cmd("sta_set_macaddr", req_intf, cmd_sta_set_macaddr);
8548 sigma_dut_reg_cmd("sta_set_rfeature", req_intf, cmd_sta_set_rfeature);
8549 sigma_dut_reg_cmd("sta_set_radio", req_intf, cmd_sta_set_radio);
8550 sigma_dut_reg_cmd("sta_set_pwrsave", req_intf, cmd_sta_set_pwrsave);
8551 sigma_dut_reg_cmd("sta_bssid_pool", req_intf, cmd_sta_bssid_pool);
8552 sigma_dut_reg_cmd("sta_reset_parm", req_intf, cmd_sta_reset_parm);
8553 sigma_dut_reg_cmd("sta_get_key", req_intf, cmd_sta_get_key);
8554 sigma_dut_reg_cmd("sta_hs2_associate", req_intf,
8555 cmd_sta_hs2_associate);
8556 sigma_dut_reg_cmd("sta_add_credential", req_intf,
8557 cmd_sta_add_credential);
8558 sigma_dut_reg_cmd("sta_scan", req_intf, cmd_sta_scan);
8559 sigma_dut_reg_cmd("sta_set_systime", NULL, cmd_sta_set_systime);
8560 sigma_dut_reg_cmd("sta_osu", req_intf, cmd_sta_osu);
8561 sigma_dut_reg_cmd("sta_policy_update", req_intf, cmd_sta_policy_update);
8562 sigma_dut_reg_cmd("sta_er_config", NULL, cmd_sta_er_config);
8563 sigma_dut_reg_cmd("sta_wps_connect_pw_token", req_intf,
8564 cmd_sta_wps_connect_pw_token);
8565 sigma_dut_reg_cmd("sta_exec_action", req_intf, cmd_sta_exec_action);
8566 sigma_dut_reg_cmd("sta_get_events", req_intf, cmd_sta_get_events);
8567 sigma_dut_reg_cmd("sta_get_parameter", req_intf, cmd_sta_get_parameter);
8568}