7626 lines
181 KiB
C
7626 lines
181 KiB
C
/*
|
|
* Sigma Control API DUT (station/AP)
|
|
* Copyright (c) 2010-2011, Atheros Communications, Inc.
|
|
* Copyright (c) 2011-2015, Qualcomm Atheros, Inc.
|
|
* All Rights Reserved.
|
|
* Licensed under the Clear BSD license. See README for more details.
|
|
*/
|
|
|
|
#include "sigma_dut.h"
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
#ifdef __linux__
|
|
#include <sys/time.h>
|
|
#include <netpacket/packet.h>
|
|
#include <linux/if_ether.h>
|
|
#ifdef ANDROID
|
|
#include <cutils/properties.h>
|
|
#include <android/log.h>
|
|
#include "keystore_get.h"
|
|
#else /* ANDROID */
|
|
#include <ifaddrs.h>
|
|
#endif /* ANDROID */
|
|
#include <netdb.h>
|
|
#endif /* __linux__ */
|
|
#ifdef __QNXNTO__
|
|
#include <net/if_dl.h>
|
|
#endif /* __QNXNTO__ */
|
|
#include "wpa_ctrl.h"
|
|
#include "wpa_helpers.h"
|
|
|
|
/* Temporary files for sta_send_addba */
|
|
#define VI_QOS_TMP_FILE "/tmp/vi-qos.tmp"
|
|
#define VI_QOS_FILE "/tmp/vi-qos.txt"
|
|
#define VI_QOS_REFFILE "/etc/vi-qos.txt"
|
|
|
|
/*
|
|
* MTU for Ethernet need to take into account 8-byte SNAP header
|
|
* to be added when encapsulating Ethernet frame into 802.11
|
|
*/
|
|
#ifndef IEEE80211_MAX_DATA_LEN_DMG
|
|
#define IEEE80211_MAX_DATA_LEN_DMG 7920
|
|
#endif
|
|
#ifndef IEEE80211_SNAP_LEN_DMG
|
|
#define IEEE80211_SNAP_LEN_DMG 8
|
|
#endif
|
|
|
|
extern char *sigma_wpas_ctrl;
|
|
extern char *sigma_cert_path;
|
|
extern enum driver_type wifi_chip_type;
|
|
extern char *sigma_radio_ifname[];
|
|
|
|
|
|
#ifdef ANDROID
|
|
|
|
static int add_ipv6_rule(struct sigma_dut *dut, const char *ifname);
|
|
|
|
#define ANDROID_KEYSTORE_GET 'g'
|
|
#define ANDROID_KEYSTORE_GET_PUBKEY 'b'
|
|
|
|
static int android_keystore_get(char cmd, const char *key, unsigned char *val)
|
|
{
|
|
#ifdef ANDROID43
|
|
/* Android 4.3 changed keystore design, so need to use keystore_get() */
|
|
#ifndef KEYSTORE_MESSAGE_SIZE
|
|
#define KEYSTORE_MESSAGE_SIZE 65535
|
|
#endif /* KEYSTORE_MESSAGE_SIZE */
|
|
|
|
ssize_t len;
|
|
uint8_t *value = NULL;
|
|
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"keystore command '%c' key '%s' --> keystore_get",
|
|
cmd, key);
|
|
|
|
len = keystore_get(key, strlen(key), &value);
|
|
if (len < 0) {
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"keystore_get() failed");
|
|
return -1;
|
|
}
|
|
|
|
if (len > KEYSTORE_MESSAGE_SIZE)
|
|
len = KEYSTORE_MESSAGE_SIZE;
|
|
memcpy(val, value, len);
|
|
free(value);
|
|
return len;
|
|
#else /* ANDROID43 */
|
|
int s, res, reslen = -1, received;
|
|
size_t keylen;
|
|
unsigned char hdr[3];
|
|
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"keystore command '%c' key '%s'", cmd, key);
|
|
keylen = strlen(key);
|
|
if (keylen > KEYSTORE_MESSAGE_SIZE)
|
|
return -1;
|
|
|
|
s = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
|
|
SOCK_STREAM);
|
|
if (s < 0) {
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"could not connect to keystore");
|
|
return -1;
|
|
}
|
|
|
|
hdr[0] = cmd;
|
|
hdr[1] = keylen >> 8;
|
|
hdr[2] = keylen & 0xff;
|
|
|
|
if (send(s, hdr, sizeof(hdr), MSG_NOSIGNAL) != sizeof(hdr) ||
|
|
send(s, key, keylen, MSG_NOSIGNAL) != (int) keylen ||
|
|
shutdown(s, SHUT_WR) != 0) {
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"could not send keystore command");
|
|
goto fail;
|
|
}
|
|
|
|
if (recv(s, hdr, 1, 0) != 1)
|
|
goto fail;
|
|
if (hdr[0] != 1) {
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"unexpected keystore response %u", hdr[0]);
|
|
goto fail;
|
|
}
|
|
if (recv(s, hdr + 1, 2, 0) != 2)
|
|
goto fail;
|
|
reslen = hdr[1] * 256 + hdr[2];
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"keystore response length %d", reslen);
|
|
if (reslen > KEYSTORE_MESSAGE_SIZE) {
|
|
reslen = -1;
|
|
goto fail;
|
|
}
|
|
|
|
received = 0;
|
|
while (received < reslen) {
|
|
res = recv(s, val + received, reslen - received, 0);
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"keystore recv -> %d", res);
|
|
if (res <= 0) {
|
|
reslen = -1;
|
|
break;
|
|
}
|
|
received += res;
|
|
}
|
|
|
|
fail:
|
|
close(s);
|
|
__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
|
|
"keystore get -> %d", reslen);
|
|
return reslen;
|
|
#endif /* ANDROID43 */
|
|
}
|
|
#endif /* ANDROID */
|
|
|
|
|
|
int set_ps(const char *intf, struct sigma_dut *dut, int enabled)
|
|
{
|
|
#ifdef __linux__
|
|
char buf[100];
|
|
|
|
if (wifi_chip_type == DRIVER_WCN) {
|
|
if (enabled) {
|
|
snprintf(buf, sizeof(buf), "iwpriv wlan0 dump 906");
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to enable power save");
|
|
return -1;
|
|
}
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "iwpriv wlan0 dump 905");
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to stop power save timer");
|
|
return -1;
|
|
}
|
|
snprintf(buf, sizeof(buf), "iwpriv wlan0 dump 912");
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to disable power save");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "./iw dev %s set power_save %s",
|
|
intf, enabled ? "on" : "off");
|
|
if (system(buf) != 0) {
|
|
snprintf(buf, sizeof(buf), "iw dev %s set power_save %s",
|
|
intf, enabled ? "on" : "off");
|
|
if (system(buf) != 0)
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
#else /* __linux__ */
|
|
return -1;
|
|
#endif /* __linux__ */
|
|
}
|
|
|
|
|
|
static void static_ip_file(int proto, const char *addr, const char *mask,
|
|
const char *gw)
|
|
{
|
|
if (proto) {
|
|
FILE *f = fopen("static-ip", "w");
|
|
if (f) {
|
|
fprintf(f, "%d %s %s %s\n", proto, addr,
|
|
mask ? mask : "N/A",
|
|
gw ? gw : "N/A");
|
|
fclose(f);
|
|
}
|
|
} else {
|
|
unlink("static-ip");
|
|
}
|
|
}
|
|
|
|
|
|
static int send_neighbor_request(struct sigma_dut *dut, const char *intf,
|
|
const char *ssid)
|
|
{
|
|
#ifdef __linux__
|
|
char buf[100];
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s neighbor %s",
|
|
intf, ssid);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Request: %s", buf);
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv neighbor request failed");
|
|
return -1;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "iwpriv neighbor request send");
|
|
|
|
return 0;
|
|
#else /* __linux__ */
|
|
return -1;
|
|
#endif /* __linux__ */
|
|
}
|
|
|
|
|
|
static int send_trans_mgmt_query(struct sigma_dut *dut, const char *intf,
|
|
const char *ssid)
|
|
{
|
|
/*
|
|
* In the earlier builds we used WNM_QUERY and in later
|
|
* builds used WNM_BSS_QUERY.
|
|
*/
|
|
|
|
if (wpa_command(intf, "WNM_BSS_QUERY 0") != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"transition management query failed");
|
|
return -1;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"transition management query sent");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int is_ip_addr(const char *str)
|
|
{
|
|
const char *pos = str;
|
|
struct in_addr addr;
|
|
|
|
while (*pos) {
|
|
if (*pos != '.' && (*pos < '0' || *pos > '9'))
|
|
return 0;
|
|
pos++;
|
|
}
|
|
|
|
return inet_aton(str, &addr);
|
|
}
|
|
|
|
|
|
int is_ipv6_addr(const char *str)
|
|
{
|
|
struct sockaddr_in6 addr;
|
|
|
|
return inet_pton(AF_INET6, str, &(addr.sin6_addr));
|
|
}
|
|
|
|
|
|
int get_ip_config(struct sigma_dut *dut, const char *ifname, char *buf,
|
|
size_t buf_len)
|
|
{
|
|
char tmp[256], *pos, *pos2;
|
|
FILE *f;
|
|
char ip[16], mask[15], dns[16], sec_dns[16];
|
|
const char *str_ps;
|
|
int is_dhcp = 0;
|
|
int s;
|
|
#ifdef ANDROID
|
|
char prop[PROPERTY_VALUE_MAX];
|
|
#endif /* ANDROID */
|
|
|
|
ip[0] = '\0';
|
|
mask[0] = '\0';
|
|
dns[0] = '\0';
|
|
sec_dns[0] = '\0';
|
|
|
|
s = socket(PF_INET, SOCK_DGRAM, 0);
|
|
if (s >= 0) {
|
|
struct ifreq ifr;
|
|
struct sockaddr_in saddr;
|
|
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
|
|
"%s IP address: %s",
|
|
ifname, strerror(errno));
|
|
} else {
|
|
memcpy(&saddr, &ifr.ifr_addr,
|
|
sizeof(struct sockaddr_in));
|
|
strncpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
|
|
}
|
|
|
|
if (ioctl(s, SIOCGIFNETMASK, &ifr) == 0) {
|
|
memcpy(&saddr, &ifr.ifr_addr,
|
|
sizeof(struct sockaddr_in));
|
|
strncpy(mask, inet_ntoa(saddr.sin_addr), sizeof(mask));
|
|
}
|
|
close(s);
|
|
}
|
|
|
|
#ifdef ANDROID
|
|
snprintf(tmp, sizeof(tmp), "dhcp.%s.pid", ifname);
|
|
if (property_get(tmp, prop, NULL) != 0 && atoi(prop) > 0) {
|
|
snprintf(tmp, sizeof(tmp), "dhcp.%s.result", ifname);
|
|
if (property_get(tmp, prop, NULL) != 0 &&
|
|
strcmp(prop, "ok") == 0) {
|
|
snprintf(tmp, sizeof(tmp), "dhcp.%s.ipaddress",
|
|
ifname);
|
|
if (property_get(tmp, prop, NULL) != 0 &&
|
|
strcmp(ip, prop) == 0)
|
|
is_dhcp = 1;
|
|
}
|
|
}
|
|
|
|
snprintf(tmp, sizeof(tmp), "dhcp.%s.dns1", ifname);
|
|
if (property_get(tmp, prop, NULL) != 0) {
|
|
strncpy(dns, prop, sizeof(dns));
|
|
dns[sizeof(dns) - 1] = '\0';
|
|
} else {
|
|
if (property_get("net.dns1", prop, NULL) != 0) {
|
|
strncpy(dns, prop, sizeof(dns));
|
|
dns[sizeof(dns) - 1] = '\0';
|
|
}
|
|
}
|
|
|
|
snprintf(tmp, sizeof(tmp), "dhcp.%s.dns2", ifname);
|
|
if (property_get(tmp, prop, NULL) != 0) {
|
|
strncpy(sec_dns, prop, sizeof(sec_dns));
|
|
sec_dns[sizeof(sec_dns) - 1] = '\0';
|
|
}
|
|
#else /* ANDROID */
|
|
#ifdef __linux__
|
|
if (get_driver_type() == DRIVER_OPENWRT)
|
|
str_ps = "ps -w";
|
|
else
|
|
str_ps = "ps ax";
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s | grep dhclient | grep -v grep | grep -q %s",
|
|
str_ps, ifname);
|
|
if (system(tmp) == 0)
|
|
is_dhcp = 1;
|
|
else {
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s | grep udhcpc | grep -v grep | grep -q %s",
|
|
str_ps, ifname);
|
|
if (system(tmp) == 0)
|
|
is_dhcp = 1;
|
|
else {
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s | grep dhcpcd | grep -v grep | grep -q %s",
|
|
str_ps, ifname);
|
|
if (system(tmp) == 0)
|
|
is_dhcp = 1;
|
|
}
|
|
}
|
|
#endif /* __linux__ */
|
|
|
|
f = fopen("/etc/resolv.conf", "r");
|
|
if (f) {
|
|
while (fgets(tmp, sizeof(tmp), f)) {
|
|
if (strncmp(tmp, "nameserver", 10) != 0)
|
|
continue;
|
|
pos = tmp + 10;
|
|
while (*pos == ' ' || *pos == '\t')
|
|
pos++;
|
|
pos2 = pos;
|
|
while (*pos2) {
|
|
if (*pos2 == '\n' || *pos2 == '\r') {
|
|
*pos2 = '\0';
|
|
break;
|
|
}
|
|
pos2++;
|
|
}
|
|
if (!dns[0]) {
|
|
strncpy(dns, pos, sizeof(dns));
|
|
dns[sizeof(dns) - 1] = '\0';
|
|
} else if (!sec_dns[0]) {
|
|
strncpy(sec_dns, pos, sizeof(sec_dns));
|
|
sec_dns[sizeof(sec_dns) - 1] = '\0';
|
|
}
|
|
}
|
|
fclose(f);
|
|
}
|
|
#endif /* ANDROID */
|
|
|
|
snprintf(buf, buf_len, "dhcp,%d,ip,%s,mask,%s,primary-dns,%s",
|
|
is_dhcp, ip, mask, dns);
|
|
buf[buf_len - 1] = '\0';
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int get_ipv6_config(struct sigma_dut *dut, const char *ifname, char *buf,
|
|
size_t buf_len)
|
|
{
|
|
#ifdef __linux__
|
|
#ifdef ANDROID
|
|
char cmd[200], result[1000], *pos, *end;
|
|
FILE *f;
|
|
size_t len;
|
|
|
|
snprintf(cmd, sizeof(cmd), "ip addr show dev %s scope global", ifname);
|
|
f = popen(cmd, "r");
|
|
if (f == NULL)
|
|
return -1;
|
|
len = fread(result, 1, sizeof(result) - 1, f);
|
|
pclose(f);
|
|
if (len == 0)
|
|
return -1;
|
|
result[len] = '\0';
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "%s result: %s\n", cmd, result);
|
|
|
|
pos = strstr(result, "inet6 ");
|
|
if (pos == NULL)
|
|
return -1;
|
|
pos += 6;
|
|
end = strchr(pos, ' ');
|
|
if (end)
|
|
*end = '\0';
|
|
end = strchr(pos, '/');
|
|
if (end)
|
|
*end = '\0';
|
|
snprintf(buf, buf_len, "ip,%s", pos);
|
|
buf[buf_len - 1] = '\0';
|
|
return 0;
|
|
#else /* ANDROID */
|
|
struct ifaddrs *ifaddr, *ifa;
|
|
int res, found = 0;
|
|
char host[NI_MAXHOST];
|
|
|
|
if (getifaddrs(&ifaddr) < 0) {
|
|
perror("getifaddrs");
|
|
return -1;
|
|
}
|
|
|
|
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
|
if (strcasecmp(ifname, ifa->ifa_name) != 0)
|
|
continue;
|
|
if (ifa->ifa_addr == NULL ||
|
|
ifa->ifa_addr->sa_family != AF_INET6)
|
|
continue;
|
|
|
|
res = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
|
|
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
|
|
if (res != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "getnameinfo: %s",
|
|
gai_strerror(res));
|
|
continue;
|
|
}
|
|
if (strncmp(host, "fe80::", 6) == 0)
|
|
continue; /* skip link-local */
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "ifaddr: %s", host);
|
|
found = 1;
|
|
break;
|
|
}
|
|
|
|
freeifaddrs(ifaddr);
|
|
|
|
if (found) {
|
|
char *pos;
|
|
pos = strchr(host, '%');
|
|
if (pos)
|
|
*pos = '\0';
|
|
snprintf(buf, buf_len, "ip,%s", host);
|
|
buf[buf_len - 1] = '\0';
|
|
return 0;
|
|
}
|
|
|
|
#endif /* ANDROID */
|
|
#endif /* __linux__ */
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_ip_config(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
char buf[200];
|
|
const char *val;
|
|
int type = 1;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
/*
|
|
* UCC may assume the IP address to be available immediately after
|
|
* association without trying to run sta_get_ip_config multiple times.
|
|
* Sigma CAPI does not specify this command as a block command that
|
|
* would wait for the address to become available, but to pass tests
|
|
* more reliably, it looks like such a wait may be needed here.
|
|
*/
|
|
if (wait_ip_addr(dut, ifname, 15) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Could not get IP address "
|
|
"for sta_get_ip_config");
|
|
/*
|
|
* Try to continue anyway since many UCC tests do not really
|
|
* care about the return value from here..
|
|
*/
|
|
}
|
|
|
|
val = get_param(cmd, "Type");
|
|
if (val)
|
|
type = atoi(val);
|
|
if (type == 2 || dut->last_set_ip_config_ipv6) {
|
|
int i;
|
|
|
|
/*
|
|
* Since we do not have proper wait for IPv6 addresses, use a
|
|
* fixed two second delay here as a workaround for UCC script
|
|
* assuming IPv6 address is available when this command returns.
|
|
* Some scripts did not use Type,2 properly for IPv6, so include
|
|
* also the cases where the previous sta_set_ip_config indicated
|
|
* use of IPv6.
|
|
*/
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Wait up to extra ten seconds in sta_get_ip_config for IPv6 address");
|
|
for (i = 0; i < 10; i++) {
|
|
sleep(1);
|
|
if (get_ipv6_config(dut, ifname, buf, sizeof(buf)) == 0)
|
|
{
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Found IPv6 address");
|
|
send_resp(dut, conn, SIGMA_COMPLETE, buf);
|
|
#ifdef ANDROID
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Adding IPv6 rule on Android");
|
|
add_ipv6_rule(dut, intf);
|
|
#endif /* ANDROID */
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
if (type == 1) {
|
|
if (get_ip_config(dut, ifname, buf, sizeof(buf)) < 0)
|
|
return -2;
|
|
} else if (type == 2) {
|
|
if (get_ipv6_config(dut, ifname, buf, sizeof(buf)) < 0)
|
|
return -2;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unsupported address type");
|
|
return 0;
|
|
}
|
|
|
|
send_resp(dut, conn, SIGMA_COMPLETE, buf);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void kill_dhcp_client(struct sigma_dut *dut, const char *ifname)
|
|
{
|
|
#ifdef __linux__
|
|
char buf[200];
|
|
char path[128];
|
|
struct stat s;
|
|
|
|
#ifdef ANDROID
|
|
snprintf(path, sizeof(path), "/data/misc/dhcp/dhcpcd-%s.pid", ifname);
|
|
#else /* ANDROID */
|
|
snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid", ifname);
|
|
#endif /* ANDROID */
|
|
if (stat(path, &s) == 0) {
|
|
snprintf(buf, sizeof(buf), "kill `cat %s`", path);
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Kill previous DHCP client: %s", buf);
|
|
if (system(buf) != 0)
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to kill DHCP client");
|
|
unlink(path);
|
|
sleep(1);
|
|
} else {
|
|
snprintf(path, sizeof(path), "/var/run/dhcpcd-%s.pid", ifname);
|
|
|
|
if (stat(path, &s) == 0) {
|
|
snprintf(buf, sizeof(buf), "kill `cat %s`", path);
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Kill previous DHCP client: %s", buf);
|
|
if (system(buf) != 0)
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to kill DHCP client");
|
|
unlink(path);
|
|
sleep(1);
|
|
}
|
|
}
|
|
#endif /* __linux__ */
|
|
}
|
|
|
|
|
|
static int start_dhcp_client(struct sigma_dut *dut, const char *ifname)
|
|
{
|
|
#ifdef __linux__
|
|
char buf[200];
|
|
|
|
#ifdef ANDROID
|
|
snprintf(buf, sizeof(buf),
|
|
"/system/bin/dhcpcd -b %s", ifname);
|
|
#else /* ANDROID */
|
|
snprintf(buf, sizeof(buf),
|
|
"dhclient -nw -pf /var/run/dhclient-%s.pid %s",
|
|
ifname, ifname);
|
|
#endif /* ANDROID */
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Start DHCP client: %s", buf);
|
|
if (system(buf) != 0) {
|
|
snprintf(buf, sizeof(buf), "dhcpcd -t 0 %s &", ifname);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to start DHCP client");
|
|
#ifndef ANDROID
|
|
return -1;
|
|
#endif /* ANDROID */
|
|
}
|
|
}
|
|
#endif /* __linux__ */
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int clear_ip_addr(struct sigma_dut *dut, const char *ifname)
|
|
{
|
|
#ifdef __linux__
|
|
char buf[200];
|
|
|
|
snprintf(buf, sizeof(buf), "ip addr flush dev %s", ifname);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to clear IP addresses");
|
|
return -1;
|
|
}
|
|
#endif /* __linux__ */
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifdef ANDROID
|
|
static int add_ipv6_rule(struct sigma_dut *dut, const char *ifname)
|
|
{
|
|
char cmd[200], *result, *pos;
|
|
FILE *fp;
|
|
int len, tableid, result_len = 1000;
|
|
|
|
snprintf(cmd, sizeof(cmd), "ip -6 route list table all | grep %s",
|
|
ifname);
|
|
fp = popen(cmd, "r");
|
|
if (fp == NULL)
|
|
return -1;
|
|
|
|
result = malloc(result_len);
|
|
if (result == NULL)
|
|
return -1;
|
|
|
|
len = fread(result, 1, result_len, fp);
|
|
fclose(fp);
|
|
|
|
if (len == 0) {
|
|
free(result);
|
|
return -1;
|
|
}
|
|
|
|
pos = strstr(result, "table ");
|
|
if (pos == NULL) {
|
|
free(result);
|
|
return -1;
|
|
}
|
|
|
|
pos += strlen("table ");
|
|
tableid = atoi(pos);
|
|
if (tableid != 0) {
|
|
if (system("ip -6 rule del prio 22000") != 0) {
|
|
/* ignore any error */
|
|
}
|
|
snprintf(cmd, sizeof(cmd),
|
|
"ip -6 rule add from all lookup %d prio 22000",
|
|
tableid);
|
|
if (system(cmd) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to run %s", cmd);
|
|
free(result);
|
|
return -1;
|
|
}
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"No Valid Table Id found %s", pos);
|
|
free(result);
|
|
return -1;
|
|
}
|
|
free(result);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* ANDROID */
|
|
|
|
|
|
static int cmd_sta_set_ip_config(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
char buf[200];
|
|
const char *val, *ip, *mask, *gw;
|
|
int type = 1;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
if (if_nametoindex(ifname) == 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unknown interface");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "Type");
|
|
if (val) {
|
|
type = atoi(val);
|
|
if (type != 1 && type != 2) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported address type");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
dut->last_set_ip_config_ipv6 = 0;
|
|
|
|
val = get_param(cmd, "dhcp");
|
|
if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "true") == 0)) {
|
|
static_ip_file(0, NULL, NULL, NULL);
|
|
#ifdef __linux__
|
|
if (type == 2) {
|
|
dut->last_set_ip_config_ipv6 = 1;
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Using IPv6 "
|
|
"stateless address autoconfiguration");
|
|
#ifdef ANDROID
|
|
/*
|
|
* This sleep is required as the assignment in case of
|
|
* Android is taking time and is done by the kernel.
|
|
* The subsequent ping for IPv6 is impacting HS20 test
|
|
* case.
|
|
*/
|
|
sleep(2);
|
|
add_ipv6_rule(dut, intf);
|
|
#endif /* ANDROID */
|
|
/* Assume this happens by default */
|
|
return 1;
|
|
}
|
|
|
|
kill_dhcp_client(dut, ifname);
|
|
if (start_dhcp_client(dut, ifname) < 0)
|
|
return -2;
|
|
return 1;
|
|
#endif /* __linux__ */
|
|
return -2;
|
|
}
|
|
|
|
ip = get_param(cmd, "ip");
|
|
if (!ip) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,Missing IP address");
|
|
return 0;
|
|
}
|
|
|
|
mask = get_param(cmd, "mask");
|
|
if (!mask) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,Missing subnet mask");
|
|
return 0;
|
|
}
|
|
|
|
if (type == 2) {
|
|
int net = atoi(mask);
|
|
|
|
if ((net < 0 && net > 64) || !is_ipv6_addr(ip))
|
|
return -1;
|
|
|
|
if (dut->no_ip_addr_set) {
|
|
snprintf(buf, sizeof(buf),
|
|
"sysctl net.ipv6.conf.%s.disable_ipv6=1",
|
|
ifname);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Failed to disable IPv6 address before association");
|
|
}
|
|
} else {
|
|
snprintf(buf, sizeof(buf),
|
|
"ip -6 addr del %s/%s dev %s",
|
|
ip, mask, ifname);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
/*
|
|
* This command may fail if the address being
|
|
* deleted does not exist. Inaction here is
|
|
* intentional.
|
|
*/
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
"ip -6 addr add %s/%s dev %s",
|
|
ip, mask, ifname);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set IPv6 address");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
dut->last_set_ip_config_ipv6 = 1;
|
|
static_ip_file(6, ip, mask, NULL);
|
|
return 1;
|
|
} else if (type == 1) {
|
|
if (!is_ip_addr(ip) || !is_ip_addr(mask))
|
|
return -1;
|
|
}
|
|
|
|
kill_dhcp_client(dut, ifname);
|
|
|
|
if (!dut->no_ip_addr_set) {
|
|
snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s",
|
|
ifname, ip, mask);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set IP address");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
gw = get_param(cmd, "defaultGateway");
|
|
if (gw) {
|
|
if (!is_ip_addr(gw))
|
|
return -1;
|
|
snprintf(buf, sizeof(buf), "route add default gw %s", gw);
|
|
if (!dut->no_ip_addr_set && system(buf) != 0) {
|
|
snprintf(buf, sizeof(buf), "ip ro re default via %s",
|
|
gw);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed "
|
|
"to set default gateway");
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "primary-dns");
|
|
if (val) {
|
|
/* TODO */
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Ignored primary-dns %s "
|
|
"setting", val);
|
|
}
|
|
|
|
val = get_param(cmd, "secondary-dns");
|
|
if (val) {
|
|
/* TODO */
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Ignored secondary-dns %s "
|
|
"setting", val);
|
|
}
|
|
|
|
static_ip_file(4, ip, mask, gw);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_info(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
/* const char *intf = get_param(cmd, "Interface"); */
|
|
/* TODO: could report more details here */
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "vendor,Atheros");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_mac_address(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
/* const char *intf = get_param(cmd, "Interface"); */
|
|
char addr[20], resp[50];
|
|
|
|
if (get_wpa_status(get_station_ifname(), "address", addr, sizeof(addr))
|
|
< 0)
|
|
return -2;
|
|
|
|
snprintf(resp, sizeof(resp), "mac,%s", addr);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, resp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_is_connected(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
/* const char *intf = get_param(cmd, "Interface"); */
|
|
int connected = 0;
|
|
char result[32];
|
|
if (get_wpa_status(get_station_ifname(), "wpa_state", result,
|
|
sizeof(result)) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Could not get interface "
|
|
"%s status", get_station_ifname());
|
|
return -2;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "wpa_state=%s", result);
|
|
if (strncmp(result, "COMPLETED", 9) == 0)
|
|
connected = 1;
|
|
|
|
if (connected)
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "connected,1");
|
|
else
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "connected,0");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_verify_ip_connection(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
/* const char *intf = get_param(cmd, "Interface"); */
|
|
const char *dst, *timeout;
|
|
int wait_time = 90;
|
|
char buf[100];
|
|
int res;
|
|
|
|
dst = get_param(cmd, "destination");
|
|
if (dst == NULL || !is_ip_addr(dst))
|
|
return -1;
|
|
|
|
timeout = get_param(cmd, "timeout");
|
|
if (timeout) {
|
|
wait_time = atoi(timeout);
|
|
if (wait_time < 1)
|
|
wait_time = 1;
|
|
}
|
|
|
|
/* TODO: force renewal of IP lease if DHCP is enabled */
|
|
|
|
snprintf(buf, sizeof(buf), "ping %s -c 3 -W %d", dst, wait_time);
|
|
res = system(buf);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "ping returned: %d", res);
|
|
if (res == 0)
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "connected,1");
|
|
else if (res == 256)
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "connected,0");
|
|
else
|
|
return -2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_bssid(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
/* const char *intf = get_param(cmd, "Interface"); */
|
|
char bssid[20], resp[50];
|
|
|
|
if (get_wpa_status(get_station_ifname(), "bssid", bssid, sizeof(bssid))
|
|
< 0)
|
|
strncpy(bssid, "00:00:00:00:00:00", sizeof(bssid));
|
|
|
|
snprintf(resp, sizeof(resp), "bssid,%s", bssid);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, resp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifdef __SAMSUNG__
|
|
static int add_use_network(const char *ifname)
|
|
{
|
|
char buf[100];
|
|
|
|
snprintf(buf, sizeof(buf), "USE_NETWORK ON");
|
|
wpa_command(ifname, buf);
|
|
return 0;
|
|
}
|
|
#endif /* __SAMSUNG__ */
|
|
|
|
|
|
static int add_network_common(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
const char *ifname, struct sigma_cmd *cmd)
|
|
{
|
|
const char *ssid = get_param(cmd, "ssid");
|
|
int id;
|
|
const char *val;
|
|
|
|
if (ssid == NULL)
|
|
return -1;
|
|
|
|
start_sta_mode(dut);
|
|
|
|
#ifdef __SAMSUNG__
|
|
add_use_network(ifname);
|
|
#endif /* __SAMSUNG__ */
|
|
|
|
id = add_network(ifname);
|
|
if (id < 0)
|
|
return -2;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding network %d", id);
|
|
|
|
if (set_network_quoted(ifname, id, "ssid", ssid) < 0)
|
|
return -2;
|
|
|
|
dut->infra_network_id = id;
|
|
snprintf(dut->infra_ssid, sizeof(dut->infra_ssid), "%s", ssid);
|
|
|
|
val = get_param(cmd, "program");
|
|
if (!val)
|
|
val = get_param(cmd, "prog");
|
|
if (val && strcasecmp(val, "hs2") == 0) {
|
|
char buf[100];
|
|
snprintf(buf, sizeof(buf), "ENABLE_NETWORK %d no-connect", id);
|
|
wpa_command(ifname, buf);
|
|
|
|
val = get_param(cmd, "prefer");
|
|
if (val && atoi(val) > 0)
|
|
set_network(ifname, id, "priority", "1");
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_encryption(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ssid = get_param(cmd, "ssid");
|
|
const char *type = get_param(cmd, "encpType");
|
|
const char *ifname;
|
|
char buf[200];
|
|
int id;
|
|
|
|
if (intf == NULL || ssid == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = add_network_common(dut, conn, ifname, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
|
|
return -2;
|
|
|
|
if (type && strcasecmp(type, "wep") == 0) {
|
|
const char *val;
|
|
int i;
|
|
|
|
val = get_param(cmd, "activeKey");
|
|
if (val) {
|
|
int keyid;
|
|
keyid = atoi(val);
|
|
if (keyid < 1 || keyid > 4)
|
|
return -1;
|
|
snprintf(buf, sizeof(buf), "%d", keyid - 1);
|
|
if (set_network(ifname, id, "wep_tx_keyidx", buf) < 0)
|
|
return -2;
|
|
}
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
snprintf(buf, sizeof(buf), "key%d", i + 1);
|
|
val = get_param(cmd, buf);
|
|
if (val == NULL)
|
|
continue;
|
|
snprintf(buf, sizeof(buf), "wep_key%d", i);
|
|
if (set_network(ifname, id, buf, val) < 0)
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int set_wpa_common(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
const char *ifname, struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
int id;
|
|
|
|
id = add_network_common(dut, conn, ifname, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
val = get_param(cmd, "keyMgmtType");
|
|
if (val == NULL) {
|
|
send_resp(dut, conn, SIGMA_INVALID, "errorCode,Missing keyMgmtType");
|
|
return 0;
|
|
}
|
|
if (strcasecmp(val, "wpa") == 0 ||
|
|
strcasecmp(val, "wpa-psk") == 0) {
|
|
if (set_network(ifname, id, "proto", "WPA") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "wpa2") == 0 ||
|
|
strcasecmp(val, "wpa2-psk") == 0 ||
|
|
strcasecmp(val, "wpa2-ft") == 0 ||
|
|
strcasecmp(val, "wpa2-sha256") == 0) {
|
|
if (set_network(ifname, id, "proto", "WPA2") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "wpa2-wpa-psk") == 0) {
|
|
if (set_network(ifname, id, "proto", "WPA WPA2") < 0)
|
|
return -2;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized keyMgmtType value");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "encpType");
|
|
if (val == NULL) {
|
|
send_resp(dut, conn, SIGMA_INVALID, "errorCode,Missing encpType");
|
|
return 0;
|
|
}
|
|
if (strcasecmp(val, "tkip") == 0) {
|
|
if (set_network(ifname, id, "pairwise", "TKIP") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "aes-ccmp") == 0) {
|
|
if (set_network(ifname, id, "pairwise", "CCMP") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "aes-ccmp-tkip") == 0) {
|
|
if (set_network(ifname, id, "pairwise", "CCMP TKIP") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "aes-gcmp") == 0) {
|
|
if (set_network(ifname, id, "pairwise", "GCMP") < 0)
|
|
return -2;
|
|
if (set_network(ifname, id, "group", "GCMP") < 0)
|
|
return -2;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized encpType value");
|
|
return 0;
|
|
}
|
|
|
|
dut->sta_pmf = STA_PMF_DISABLED;
|
|
val = get_param(cmd, "PMF");
|
|
if (val) {
|
|
if (strcasecmp(val, "Required") == 0 ||
|
|
strcasecmp(val, "Forced_Required") == 0) {
|
|
dut->sta_pmf = STA_PMF_REQUIRED;
|
|
if (set_network(ifname, id, "ieee80211w", "2") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "Optional") == 0) {
|
|
dut->sta_pmf = STA_PMF_OPTIONAL;
|
|
if (set_network(ifname, id, "ieee80211w", "1") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "Disabled") == 0 ||
|
|
strcasecmp(val, "Forced_Disabled") == 0) {
|
|
dut->sta_pmf = STA_PMF_DISABLED;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized PMF value");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_psk(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname, *val, *alg;
|
|
int id;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_wpa_common(dut, conn, ifname, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
val = get_param(cmd, "keyMgmtType");
|
|
alg = get_param(cmd, "micAlg");
|
|
|
|
if (alg && strcasecmp(alg, "SHA-256") == 0) {
|
|
if (set_network(ifname, id, "key_mgmt", "WPA-PSK-SHA256") < 0)
|
|
return -2;
|
|
} else if (alg && strcasecmp(alg, "SHA-1") == 0) {
|
|
if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
|
|
return -2;
|
|
} else if ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
|
|
dut->sta_pmf == STA_PMF_REQUIRED) {
|
|
if (set_network(ifname, id, "key_mgmt",
|
|
"WPA-PSK WPA-PSK-SHA256") < 0)
|
|
return -2;
|
|
} else if (dut->sta_pmf == STA_PMF_OPTIONAL) {
|
|
if (set_network(ifname, id, "key_mgmt",
|
|
"WPA-PSK WPA-PSK-SHA256") < 0)
|
|
return -2;
|
|
} else {
|
|
if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
|
|
return -2;
|
|
}
|
|
|
|
val = get_param(cmd, "passPhrase");
|
|
if (val == NULL)
|
|
return -1;
|
|
if (set_network_quoted(ifname, id, "psk", val) < 0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int set_eap_common(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
const char *ifname, int username_identity,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val, *alg;
|
|
int id;
|
|
char buf[200];
|
|
#ifdef ANDROID
|
|
unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
|
|
int length;
|
|
#endif /* ANDROID */
|
|
|
|
id = set_wpa_common(dut, conn, ifname, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
val = get_param(cmd, "keyMgmtType");
|
|
alg = get_param(cmd, "micAlg");
|
|
|
|
if (alg && strcasecmp(alg, "SHA-256") == 0) {
|
|
if (set_network(ifname, id, "key_mgmt", "WPA-EAP-SHA256") < 0)
|
|
return -2;
|
|
} else if (alg && strcasecmp(alg, "SHA-1") == 0) {
|
|
if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
|
|
return -2;
|
|
} else if (val && strcasecmp(val, "wpa2-ft") == 0) {
|
|
if (set_network(ifname, id, "key_mgmt", "FT-EAP") < 0)
|
|
return -2;
|
|
} else if ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
|
|
dut->sta_pmf == STA_PMF_REQUIRED) {
|
|
if (set_network(ifname, id, "key_mgmt",
|
|
"WPA-EAP WPA-EAP-SHA256") < 0)
|
|
return -2;
|
|
} else if (dut->sta_pmf == STA_PMF_OPTIONAL) {
|
|
if (set_network(ifname, id, "key_mgmt",
|
|
"WPA-EAP WPA-EAP-SHA256") < 0)
|
|
return -2;
|
|
} else {
|
|
if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
|
|
return -2;
|
|
}
|
|
|
|
val = get_param(cmd, "trustedRootCA");
|
|
if (val) {
|
|
#ifdef ANDROID
|
|
snprintf(buf, sizeof(buf), "CACERT_%s", val);
|
|
length = android_keystore_get(ANDROID_KEYSTORE_GET, buf,
|
|
kvalue);
|
|
if (length > 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Use Android keystore [%s]", buf);
|
|
snprintf(buf, sizeof(buf), "keystore://CACERT_%s",
|
|
val);
|
|
goto ca_cert_selected;
|
|
}
|
|
#endif /* ANDROID */
|
|
|
|
snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
|
|
#ifdef __linux__
|
|
if (!file_exists(buf)) {
|
|
char msg[300];
|
|
snprintf(msg, sizeof(msg), "ErrorCode,trustedRootCA "
|
|
"file (%s) not found", buf);
|
|
send_resp(dut, conn, SIGMA_ERROR, msg);
|
|
return -3;
|
|
}
|
|
#endif /* __linux__ */
|
|
#ifdef ANDROID
|
|
ca_cert_selected:
|
|
#endif /* ANDROID */
|
|
if (set_network_quoted(ifname, id, "ca_cert", buf) < 0)
|
|
return -2;
|
|
}
|
|
|
|
if (username_identity) {
|
|
val = get_param(cmd, "username");
|
|
if (val) {
|
|
if (set_network_quoted(ifname, id, "identity", val) < 0)
|
|
return -2;
|
|
}
|
|
|
|
val = get_param(cmd, "password");
|
|
if (val) {
|
|
if (set_network_quoted(ifname, id, "password", val) < 0)
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_eaptls(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname, *val;
|
|
int id;
|
|
char buf[200];
|
|
#ifdef ANDROID
|
|
unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
|
|
int length;
|
|
int jb_or_newer = 0;
|
|
char prop[PROPERTY_VALUE_MAX];
|
|
#endif /* ANDROID */
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, 1, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "TLS") < 0)
|
|
return -2;
|
|
|
|
if (!get_param(cmd, "username") &&
|
|
set_network_quoted(ifname, id, "identity",
|
|
"wifi-user@wifilabs.local") < 0)
|
|
return -2;
|
|
|
|
val = get_param(cmd, "clientCertificate");
|
|
if (val == NULL)
|
|
return -1;
|
|
#ifdef ANDROID
|
|
snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
|
|
length = android_keystore_get(ANDROID_KEYSTORE_GET, buf, kvalue);
|
|
if (length < 0) {
|
|
/*
|
|
* JB started reporting keystore type mismatches, so retry with
|
|
* the GET_PUBKEY command if the generic GET fails.
|
|
*/
|
|
length = android_keystore_get(ANDROID_KEYSTORE_GET_PUBKEY,
|
|
buf, kvalue);
|
|
}
|
|
|
|
if (property_get("ro.build.version.release", prop, NULL) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Android release %s", prop);
|
|
if (strncmp(prop, "4.0", 3) != 0)
|
|
jb_or_newer = 1;
|
|
} else
|
|
jb_or_newer = 1; /* assume newer */
|
|
|
|
if (jb_or_newer && length > 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Use Android keystore [%s]", buf);
|
|
if (set_network(ifname, id, "engine", "1") < 0)
|
|
return -2;
|
|
if (set_network_quoted(ifname, id, "engine_id", "keystore") < 0)
|
|
return -2;
|
|
snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
|
|
if (set_network_quoted(ifname, id, "key_id", buf) < 0)
|
|
return -2;
|
|
snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
|
|
if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
|
|
return -2;
|
|
return 1;
|
|
} else if (length > 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Use Android keystore [%s]", buf);
|
|
snprintf(buf, sizeof(buf), "keystore://USRPKEY_%s", val);
|
|
if (set_network_quoted(ifname, id, "private_key", buf) < 0)
|
|
return -2;
|
|
snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
|
|
if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
|
|
return -2;
|
|
return 1;
|
|
}
|
|
#endif /* ANDROID */
|
|
|
|
snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
|
|
#ifdef __linux__
|
|
if (!file_exists(buf)) {
|
|
char msg[300];
|
|
snprintf(msg, sizeof(msg), "ErrorCode,clientCertificate file "
|
|
"(%s) not found", buf);
|
|
send_resp(dut, conn, SIGMA_ERROR, msg);
|
|
return -3;
|
|
}
|
|
#endif /* __linux__ */
|
|
if (set_network_quoted(ifname, id, "private_key", buf) < 0)
|
|
return -2;
|
|
if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
|
|
return -2;
|
|
|
|
if (set_network_quoted(ifname, id, "private_key_passwd", "wifi") < 0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_eapttls(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
int id;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, 1, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "TTLS") < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to set TTLS method");
|
|
return 0;
|
|
}
|
|
|
|
if (set_network_quoted(ifname, id, "phase2", "auth=MSCHAPV2") < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to set MSCHAPv2 for TTLS Phase 2");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_eapsim(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
int id;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "SIM") < 0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_peap(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname, *val;
|
|
int id;
|
|
char buf[100];
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, 1, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "PEAP") < 0)
|
|
return -2;
|
|
|
|
val = get_param(cmd, "innerEAP");
|
|
if (val) {
|
|
if (strcasecmp(val, "MSCHAPv2") == 0) {
|
|
if (set_network_quoted(ifname, id, "phase2",
|
|
"auth=MSCHAPV2") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "GTC") == 0) {
|
|
if (set_network_quoted(ifname, id, "phase2",
|
|
"auth=GTC") < 0)
|
|
return -2;
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "peapVersion");
|
|
if (val) {
|
|
int ver = atoi(val);
|
|
if (ver < 0 || ver > 1)
|
|
return -1;
|
|
snprintf(buf, sizeof(buf), "peapver=%d", ver);
|
|
if (set_network_quoted(ifname, id, "phase1", buf) < 0)
|
|
return -2;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_eapfast(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname, *val;
|
|
int id;
|
|
char buf[100];
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, 1, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "FAST") < 0)
|
|
return -2;
|
|
|
|
val = get_param(cmd, "innerEAP");
|
|
if (val) {
|
|
if (strcasecmp(val, "MSCHAPV2") == 0) {
|
|
if (set_network_quoted(ifname, id, "phase2",
|
|
"auth=MSCHAPV2") < 0)
|
|
return -2;
|
|
} else if (strcasecmp(val, "GTC") == 0) {
|
|
if (set_network_quoted(ifname, id, "phase2",
|
|
"auth=GTC") < 0)
|
|
return -2;
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "validateServer");
|
|
if (val) {
|
|
/* TODO */
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Ignored EAP-FAST "
|
|
"validateServer=%s", val);
|
|
}
|
|
|
|
val = get_param(cmd, "pacFile");
|
|
if (val) {
|
|
snprintf(buf, sizeof(buf), "blob://%s", val);
|
|
if (set_network_quoted(ifname, id, "pac_file", buf) < 0)
|
|
return -2;
|
|
}
|
|
|
|
if (set_network_quoted(ifname, id, "phase1", "fast_provisioning=2") <
|
|
0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_eapaka(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
int id;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "AKA") < 0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_eapakaprime(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
int id;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "eap", "AKA'") < 0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int sta_set_open(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *ifname;
|
|
int id;
|
|
|
|
if (strcmp(intf, get_main_ifname()) == 0)
|
|
ifname = get_station_ifname();
|
|
else
|
|
ifname = intf;
|
|
|
|
id = add_network_common(dut, conn, ifname, cmd);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
|
|
return -2;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_security(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *type = get_param(cmd, "Type");
|
|
|
|
if (type == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing Type argument");
|
|
return 0;
|
|
}
|
|
|
|
if (strcasecmp(type, "OPEN") == 0)
|
|
return sta_set_open(dut, conn, cmd);
|
|
if (strcasecmp(type, "PSK") == 0)
|
|
return cmd_sta_set_psk(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPTLS") == 0)
|
|
return cmd_sta_set_eaptls(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPTTLS") == 0)
|
|
return cmd_sta_set_eapttls(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPPEAP") == 0)
|
|
return cmd_sta_set_peap(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPSIM") == 0)
|
|
return cmd_sta_set_eapsim(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPFAST") == 0)
|
|
return cmd_sta_set_eapfast(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPAKA") == 0)
|
|
return cmd_sta_set_eapaka(dut, conn, cmd);
|
|
if (strcasecmp(type, "EAPAKAPRIME") == 0)
|
|
return cmd_sta_set_eapakaprime(dut, conn, cmd);
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported Type value");
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ath6kl_client_uapsd(struct sigma_dut *dut, const char *intf, int uapsd)
|
|
{
|
|
#ifdef __linux__
|
|
/* special handling for ath6kl */
|
|
char path[128], fname[128], *pos;
|
|
ssize_t res;
|
|
FILE *f;
|
|
|
|
snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", intf);
|
|
res = readlink(path, path, sizeof(path));
|
|
if (res < 0)
|
|
return 0; /* not ath6kl */
|
|
|
|
if (res >= (int) sizeof(path))
|
|
res = sizeof(path) - 1;
|
|
path[res] = '\0';
|
|
pos = strrchr(path, '/');
|
|
if (pos == NULL)
|
|
pos = path;
|
|
else
|
|
pos++;
|
|
snprintf(fname, sizeof(fname),
|
|
"/sys/kernel/debug/ieee80211/%s/ath6kl/"
|
|
"create_qos", pos);
|
|
if (!file_exists(fname))
|
|
return 0; /* not ath6kl */
|
|
|
|
if (uapsd) {
|
|
f = fopen(fname, "w");
|
|
if (f == NULL)
|
|
return -1;
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl create_qos");
|
|
fprintf(f, "4 2 2 1 2 9999999 9999999 9999999 7777777 0 4 "
|
|
"45000 200 56789000 56789000 5678900 0 0 9999999 "
|
|
"20000 0\n");
|
|
fclose(f);
|
|
} else {
|
|
snprintf(fname, sizeof(fname),
|
|
"/sys/kernel/debug/ieee80211/%s/ath6kl/"
|
|
"delete_qos", pos);
|
|
|
|
f = fopen(fname, "w");
|
|
if (f == NULL)
|
|
return -1;
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl delete_qos");
|
|
fprintf(f, "2 4\n");
|
|
fclose(f);
|
|
}
|
|
#endif /* __linux__ */
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_uapsd(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
/* const char *ssid = get_param(cmd, "ssid"); */
|
|
const char *val;
|
|
int max_sp_len = 4;
|
|
int ac_be = 1, ac_bk = 1, ac_vi = 1, ac_vo = 1;
|
|
char buf[100];
|
|
int ret1, ret2;
|
|
|
|
val = get_param(cmd, "maxSPLength");
|
|
if (val) {
|
|
max_sp_len = atoi(val);
|
|
if (max_sp_len != 0 && max_sp_len != 1 && max_sp_len != 2 &&
|
|
max_sp_len != 4)
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "acBE");
|
|
if (val)
|
|
ac_be = atoi(val);
|
|
|
|
val = get_param(cmd, "acBK");
|
|
if (val)
|
|
ac_bk = atoi(val);
|
|
|
|
val = get_param(cmd, "acVI");
|
|
if (val)
|
|
ac_vi = atoi(val);
|
|
|
|
val = get_param(cmd, "acVO");
|
|
if (val)
|
|
ac_vo = atoi(val);
|
|
|
|
dut->client_uapsd = ac_be || ac_bk || ac_vi || ac_vo;
|
|
|
|
snprintf(buf, sizeof(buf), "P2P_SET client_apsd %d,%d,%d,%d;%d",
|
|
ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
|
|
ret1 = wpa_command(intf, buf);
|
|
|
|
snprintf(buf, sizeof(buf), "SET uapsd %d,%d,%d,%d;%d",
|
|
ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
|
|
ret2 = wpa_command(intf, buf);
|
|
|
|
if (ret1 && ret2) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to set client mode "
|
|
"UAPSD parameters.");
|
|
return -2;
|
|
}
|
|
|
|
if (ath6kl_client_uapsd(dut, intf, dut->client_uapsd) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set ath6kl QoS parameters");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_wmm(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
char buf[1000];
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *grp = get_param(cmd, "Group");
|
|
const char *act = get_param(cmd, "Action");
|
|
const char *tid = get_param(cmd, "Tid");
|
|
const char *dir = get_param(cmd, "Direction");
|
|
const char *psb = get_param(cmd, "Psb");
|
|
const char *up = get_param(cmd, "Up");
|
|
const char *fixed = get_param(cmd, "Fixed");
|
|
const char *size = get_param(cmd, "Size");
|
|
const char *msize = get_param(cmd, "Maxsize");
|
|
const char *minsi = get_param(cmd, "Min_srvc_intrvl");
|
|
const char *maxsi = get_param(cmd, "Max_srvc_intrvl");
|
|
const char *inact = get_param(cmd, "Inactivity");
|
|
const char *sus = get_param(cmd, "Suspension");
|
|
const char *mindr = get_param(cmd, "Mindatarate");
|
|
const char *meandr = get_param(cmd, "Meandatarate");
|
|
const char *peakdr = get_param(cmd, "Peakdatarate");
|
|
const char *phyrate = get_param(cmd, "Phyrate");
|
|
const char *burstsize = get_param(cmd, "Burstsize");
|
|
const char *sba = get_param(cmd, "Sba");
|
|
int direction;
|
|
int handle;
|
|
float sba_fv;
|
|
int fixed_int;
|
|
int psb_ts;
|
|
|
|
if (intf == NULL || grp == NULL || act == NULL )
|
|
return -1;
|
|
|
|
if (strcasecmp(act, "addts") == 0) {
|
|
if (tid == NULL || dir == NULL || psb == NULL ||
|
|
up == NULL || fixed == NULL || size == NULL)
|
|
return -1;
|
|
|
|
/*
|
|
* Note: Sigma CAPI spec lists uplink, downlink, and bidi as the
|
|
* possible values, but WMM-AC and V-E test scripts use "UP,
|
|
* "DOWN", and "BIDI".
|
|
*/
|
|
if (strcasecmp(dir, "uplink") == 0 ||
|
|
strcasecmp(dir, "up") == 0) {
|
|
direction = 0;
|
|
} else if (strcasecmp(dir, "downlink") == 0 ||
|
|
strcasecmp(dir, "down") == 0) {
|
|
direction = 1;
|
|
} else if (strcasecmp(dir, "bidi") == 0) {
|
|
direction = 2;
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Direction %s not supported", dir);
|
|
return -1;
|
|
}
|
|
|
|
if (strcasecmp(psb, "legacy") == 0) {
|
|
psb_ts = 0;
|
|
} else if (strcasecmp(psb, "uapsd") == 0) {
|
|
psb_ts = 1;
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"PSB %s not supported", psb);
|
|
return -1;
|
|
}
|
|
|
|
if (atoi(tid) < 0 || atoi(tid) > 7) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"TID %s not supported", tid);
|
|
return -1;
|
|
}
|
|
|
|
if (strcasecmp(fixed, "true") == 0) {
|
|
fixed_int = 1;
|
|
} else {
|
|
fixed_int = 0;
|
|
}
|
|
|
|
sba_fv = atof(sba);
|
|
|
|
dut->dialog_token++;
|
|
handle = 7000 + dut->dialog_token;
|
|
|
|
/*
|
|
* size: convert to hex
|
|
* maxsi: convert to hex
|
|
* mindr: convert to hex
|
|
* meandr: convert to hex
|
|
* peakdr: convert to hex
|
|
* burstsize: convert to hex
|
|
* phyrate: convert to hex
|
|
* sba: convert to hex with modification
|
|
* minsi: convert to integer
|
|
* sus: convert to integer
|
|
* inact: convert to integer
|
|
* maxsi: convert to integer
|
|
*/
|
|
|
|
/*
|
|
* The Nominal MSDU Size field is 2 octets long and contains an
|
|
* unsigned integer that specifies the nominal size, in octets,
|
|
* of MSDUs belonging to the traffic under this traffic
|
|
* specification and is defined in Figure 16. If the Fixed
|
|
* subfield is set to 1, then the size of the MSDU is fixed and
|
|
* is indicated by the Size Subfield. If the Fixed subfield is
|
|
* set to 0, then the size of the MSDU might not be fixed and
|
|
* the Size indicates the nominal MSDU size.
|
|
*
|
|
* The Surplus Bandwidth Allowance Factor field is 2 octets long
|
|
* and specifies the excess allocation of time (and bandwidth)
|
|
* over and above the stated rates required to transport an MSDU
|
|
* belonging to the traffic in this TSPEC. This field is
|
|
* represented as an unsigned binary number with an implicit
|
|
* binary point after the leftmost 3 bits. For example, an SBA
|
|
* of 1.75 is represented as 0x3800. This field is included to
|
|
* account for retransmissions. As such, the value of this field
|
|
* must be greater than unity.
|
|
*/
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
"iwpriv %s addTspec %d %s %d %d %s 0x%X"
|
|
" 0x%X 0x%X 0x%X"
|
|
" 0x%X 0x%X 0x%X"
|
|
" 0x%X %d %d %d %d"
|
|
" %d %d",
|
|
intf, handle, tid, direction, psb_ts, up,
|
|
(unsigned int) ((fixed_int << 15) | atoi(size)),
|
|
msize ? atoi(msize) : 0,
|
|
mindr ? atoi(mindr) : 0,
|
|
meandr ? atoi(meandr) : 0,
|
|
peakdr ? atoi(peakdr) : 0,
|
|
burstsize ? atoi(burstsize) : 0,
|
|
phyrate ? atoi(phyrate) : 0,
|
|
sba ? ((unsigned int) (((int) sba_fv << 13) |
|
|
(int)((sba_fv - (int) sba_fv) *
|
|
8192))) : 0,
|
|
minsi ? atoi(minsi) : 0,
|
|
sus ? atoi(sus) : 0,
|
|
0, 0,
|
|
inact ? atoi(inact) : 0,
|
|
maxsi ? atoi(maxsi) : 0);
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv addtspec request failed");
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to execute addTspec command");
|
|
return 0;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"iwpriv addtspec request send");
|
|
|
|
/* Mapping handle to a TID */
|
|
dut->tid_to_handle[atoi(tid)] = handle;
|
|
} else if (strcasecmp(act, "delts") == 0) {
|
|
if (tid == NULL)
|
|
return -1;
|
|
|
|
if (atoi(tid) < 0 || atoi(tid) > 7) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"TID %s not supported", tid);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unsupported TID");
|
|
return 0;
|
|
}
|
|
|
|
handle = dut->tid_to_handle[atoi(tid)];
|
|
|
|
if (handle < 7000 || handle > 7255) {
|
|
/* Invalid handle ie no mapping for that TID */
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"handle-> %d not found", handle);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s delTspec %d",
|
|
intf, handle);
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv deltspec request failed");
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to execute delTspec command");
|
|
return 0;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"iwpriv deltspec request send");
|
|
|
|
dut->tid_to_handle[atoi(tid)] = 0;
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Action type %s not supported", act);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unsupported Action");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_associate(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
/* const char *intf = get_param(cmd, "Interface"); */
|
|
const char *ssid = get_param(cmd, "ssid");
|
|
const char *wps_param = get_param(cmd, "WPS");
|
|
const char *bssid = get_param(cmd, "bssid");
|
|
int wps = 0;
|
|
char buf[100];
|
|
|
|
if (ssid == NULL)
|
|
return -1;
|
|
|
|
if (wps_param &&
|
|
(strcmp(wps_param, "1") == 0 || strcasecmp(wps_param, "On") == 0))
|
|
wps = 1;
|
|
|
|
if (wps) {
|
|
if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS "
|
|
"parameters not yet set");
|
|
return 0;
|
|
}
|
|
if (dut->wps_method == WFA_CS_WPS_PBC) {
|
|
if (wpa_command(get_station_ifname(), "WPS_PBC") < 0)
|
|
return -2;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "WPS_PIN any %s",
|
|
dut->wps_pin);
|
|
if (wpa_command(get_station_ifname(), buf) < 0)
|
|
return -2;
|
|
}
|
|
} else {
|
|
if (strcmp(ssid, dut->infra_ssid) != 0) {
|
|
printf("No network parameters known for network "
|
|
"(ssid='%s')", ssid);
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
|
|
"No network parameters known for network");
|
|
return 0;
|
|
}
|
|
|
|
if (bssid &&
|
|
set_network(get_station_ifname(), dut->infra_network_id,
|
|
"bssid", bssid) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
|
|
"Invalid bssid argument");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "SELECT_NETWORK %d",
|
|
dut->infra_network_id);
|
|
if (wpa_command(get_station_ifname(), buf) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to select "
|
|
"network id %d on %s",
|
|
dut->infra_network_id,
|
|
get_station_ifname());
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int run_hs20_osu(struct sigma_dut *dut, const char *params)
|
|
{
|
|
char buf[500], cmd[200];
|
|
int res;
|
|
|
|
/* Use hs20-osu-client file at the current dir, if found; otherwise use
|
|
* default path */
|
|
res = snprintf(cmd, sizeof(cmd),
|
|
"%s -w \"%s\" -r hs20-osu-client.res %s%s -dddKt -f Logs/hs20-osu-client.txt",
|
|
file_exists("./hs20-osu-client") ?
|
|
"./hs20-osu-client" : "hs20-osu-client",
|
|
sigma_wpas_ctrl,
|
|
dut->summary_log ? "-s " : "",
|
|
dut->summary_log ? dut->summary_log : "");
|
|
if (res < 0 || res >= (int) sizeof(cmd))
|
|
return -1;
|
|
|
|
res = snprintf(buf, sizeof(buf), "%s %s", cmd, params);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to run: %s", buf);
|
|
return -1;
|
|
}
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Completed hs20-osu-client operation");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int download_ppsmo(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *intf,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *name, *path, *val;
|
|
char url[500], buf[600], fbuf[100];
|
|
char *fqdn = NULL;
|
|
|
|
name = get_param(cmd, "FileName");
|
|
path = get_param(cmd, "FilePath");
|
|
if (name == NULL || path == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(path, "VendorSpecific") == 0) {
|
|
snprintf(url, sizeof(url), "PPS/%s", name);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured PPS MO "
|
|
"from the device (%s)", url);
|
|
if (!file_exists(url)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
|
|
"PPS MO file does not exist");
|
|
return 0;
|
|
}
|
|
snprintf(buf, sizeof(buf), "cp %s pps-tnds.xml", url);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to copy PPS MO");
|
|
return 0;
|
|
}
|
|
} else if (strncasecmp(path, "http:", 5) != 0 &&
|
|
strncasecmp(path, "https:", 6) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
|
|
"Unsupported FilePath value");
|
|
return 0;
|
|
} else {
|
|
snprintf(url, sizeof(url), "%s/%s", path, name);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Downloading PPS MO from %s",
|
|
url);
|
|
snprintf(buf, sizeof(buf), "wget -T 10 -t 3 -O pps-tnds.xml '%s'", url);
|
|
remove("pps-tnds.xml");
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to download PPS MO");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (run_hs20_osu(dut, "from_tnds pps-tnds.xml pps.xml") < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to parse downloaded PPSMO");
|
|
return 0;
|
|
}
|
|
unlink("pps-tnds.xml");
|
|
|
|
val = get_param(cmd, "managementTreeURI");
|
|
if (val) {
|
|
const char *pos, *end;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "managementTreeURI: %s",
|
|
val);
|
|
if (strncmp(val, "./Wi-Fi/", 8) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Invalid managementTreeURI prefix");
|
|
return 0;
|
|
}
|
|
pos = val + 8;
|
|
end = strchr(pos, '/');
|
|
if (end == NULL ||
|
|
strcmp(end, "/PerProviderSubscription") != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Invalid managementTreeURI postfix");
|
|
return 0;
|
|
}
|
|
if (end - pos >= (int) sizeof(fbuf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Too long FQDN in managementTreeURI");
|
|
return 0;
|
|
}
|
|
memcpy(fbuf, pos, end - pos);
|
|
fbuf[end - pos] = '\0';
|
|
fqdn = fbuf;
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"FQDN from managementTreeURI: %s", fqdn);
|
|
} else if (run_hs20_osu(dut, "get_fqdn pps.xml") == 0) {
|
|
FILE *f = fopen("pps-fqdn", "r");
|
|
if (f) {
|
|
if (fgets(fbuf, sizeof(fbuf), f)) {
|
|
fbuf[sizeof(fbuf) - 1] = '\0';
|
|
fqdn = fbuf;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Use FQDN %s", fqdn);
|
|
}
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
if (fqdn == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,No FQDN specified");
|
|
return 0;
|
|
}
|
|
|
|
mkdir("SP", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
snprintf(buf, sizeof(buf), "SP/%s", fqdn);
|
|
mkdir(buf, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
|
|
snprintf(buf, sizeof(buf), "SP/%s/pps.xml", fqdn);
|
|
if (rename("pps.xml", buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Could not move PPS MO");
|
|
return 0;
|
|
}
|
|
|
|
if (strcasecmp(path, "VendorSpecific") == 0) {
|
|
snprintf(buf, sizeof(buf), "cp Certs/ca.pem SP/%s/ca.pem",
|
|
fqdn);
|
|
if (system(buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to copy OSU CA cert");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
"cp Certs/aaa-ca.pem SP/%s/aaa-ca.pem",
|
|
fqdn);
|
|
if (system(buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to copy AAA CA cert");
|
|
return 0;
|
|
}
|
|
} else {
|
|
snprintf(buf, sizeof(buf),
|
|
"dl_osu_ca SP/%s/pps.xml SP/%s/ca.pem",
|
|
fqdn, fqdn);
|
|
if (run_hs20_osu(dut, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to download OSU CA cert");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
"dl_aaa_ca SP/%s/pps.xml SP/%s/aaa-ca.pem",
|
|
fqdn, fqdn);
|
|
if (run_hs20_osu(dut, buf) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to download AAA CA cert");
|
|
}
|
|
}
|
|
|
|
if (file_exists("next-client-cert.pem")) {
|
|
snprintf(buf, sizeof(buf), "SP/%s/client-cert.pem", fqdn);
|
|
if (rename("next-client-cert.pem", buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Could not move client certificate");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (file_exists("next-client-key.pem")) {
|
|
snprintf(buf, sizeof(buf), "SP/%s/client-key.pem", fqdn);
|
|
if (rename("next-client-key.pem", buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Could not move client key");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "set_pps SP/%s/pps.xml", fqdn);
|
|
if (run_hs20_osu(dut, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to configure credential from "
|
|
"PPSMO");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int download_cert(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *intf,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *name, *path;
|
|
char url[500], buf[600];
|
|
|
|
name = get_param(cmd, "FileName");
|
|
path = get_param(cmd, "FilePath");
|
|
if (name == NULL || path == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(path, "VendorSpecific") == 0) {
|
|
snprintf(url, sizeof(url), "Certs/%s-cert.pem", name);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
|
|
"certificate from the device (%s)", url);
|
|
if (!file_exists(url)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
|
|
"certificate file does not exist");
|
|
return 0;
|
|
}
|
|
snprintf(buf, sizeof(buf), "cp %s next-client-cert.pem", url);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to copy client "
|
|
"certificate");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(url, sizeof(url), "Certs/%s-key.pem", name);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
|
|
"private key from the device (%s)", url);
|
|
if (!file_exists(url)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
|
|
"private key file does not exist");
|
|
return 0;
|
|
}
|
|
snprintf(buf, sizeof(buf), "cp %s next-client-key.pem", url);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to copy client key");
|
|
return 0;
|
|
}
|
|
} else if (strncasecmp(path, "http:", 5) != 0 &&
|
|
strncasecmp(path, "https:", 6) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
|
|
"Unsupported FilePath value");
|
|
return 0;
|
|
} else {
|
|
snprintf(url, sizeof(url), "%s/%s.pem", path, name);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Downloading client "
|
|
"certificate/key from %s", url);
|
|
snprintf(buf, sizeof(buf),
|
|
"wget -T 10 -t 3 -O next-client-cert.pem '%s'", url);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to download client "
|
|
"certificate");
|
|
return 0;
|
|
}
|
|
|
|
if (system("cp next-client-cert.pem next-client-key.pem") != 0)
|
|
{
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to copy client key");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_preset_testparameters_hs2_r2(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *intf,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
|
|
val = get_param(cmd, "FileType");
|
|
if (val && strcasecmp(val, "PPSMO") == 0)
|
|
return download_ppsmo(dut, conn, intf, cmd);
|
|
if (val && strcasecmp(val, "CERT") == 0)
|
|
return download_cert(dut, conn, intf, cmd);
|
|
if (val) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported FileType");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static void ath_sta_set_noack(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
int counter = 0;
|
|
char token[50];
|
|
char *result;
|
|
char buf[100];
|
|
char *saveptr;
|
|
|
|
strncpy(token, val, sizeof(token));
|
|
token[sizeof(token) - 1] = '\0';
|
|
result = strtok_r(token, ":", &saveptr);
|
|
while (result) {
|
|
if (strcmp(result, "disable") == 0) {
|
|
snprintf(buf, sizeof(buf),
|
|
"iwpriv %s noackpolicy %d 1 0",
|
|
intf, counter);
|
|
} else {
|
|
snprintf(buf, sizeof(buf),
|
|
"iwpriv %s noackpolicy %d 1 1",
|
|
intf, counter);
|
|
}
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv noackpolicy failed");
|
|
}
|
|
result = strtok_r(NULL, ":", &saveptr);
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
|
|
static void ath_sta_set_rts(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[100];
|
|
|
|
snprintf(buf, sizeof(buf), "iwconfig %s rts %s", intf, val);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "iwconfig RTS failed");
|
|
}
|
|
}
|
|
|
|
|
|
static void ath_sta_set_wmm(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[100];
|
|
|
|
if (strcasecmp(val, "off") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s wmm 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to turn off WMM");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void ath_sta_set_sgi(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[100];
|
|
int sgi20;
|
|
|
|
sgi20 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi20);
|
|
if (system(buf) != 0)
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv shortgi failed");
|
|
}
|
|
|
|
|
|
static void ath_sta_set_11nrates(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[100];
|
|
int rate_code;
|
|
|
|
/* Disable Tx Beam forming when using a fixed rate */
|
|
ath_disable_txbf(dut, intf);
|
|
|
|
rate_code = 0x80 + atoi(val);
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0x%x",
|
|
intf, rate_code);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv set11NRates failed");
|
|
}
|
|
|
|
/* Channel width gets messed up, fix this */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d", intf, dut->chwidth);
|
|
if (system(buf) != 0)
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv chwidth failed");
|
|
}
|
|
|
|
|
|
static void ath_sta_set_amsdu(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[60];
|
|
|
|
if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)
|
|
snprintf(buf, sizeof(buf), "iwpriv %s amsdu 2", intf);
|
|
else
|
|
snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
|
|
|
|
if (system(buf) != 0)
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv amsdu failed");
|
|
}
|
|
|
|
|
|
static int iwpriv_sta_set_ampdu(struct sigma_dut *dut, const char *intf,
|
|
int ampdu)
|
|
{
|
|
char buf[60];
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s ampdu %d", intf, ampdu);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv ampdu failed");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void ath_sta_set_stbc(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[60];
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc %s", intf, val);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv tx_stbc failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc %s", intf, val);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv rx_stbc failed");
|
|
}
|
|
}
|
|
|
|
|
|
static int wcn_sta_set_cts_width(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[60];
|
|
|
|
if (strcmp(val, "80") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
|
|
} else if (strcmp(val, "40") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 2", intf);
|
|
} else if (strcmp(val, "20") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 1", intf);
|
|
} else if (strcasecmp(val, "Auto") == 0) {
|
|
buf[0] = '\0';
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"WIDTH/CTS_WIDTH value not supported");
|
|
return -1;
|
|
}
|
|
|
|
if (buf[0] != '\0' && system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set WIDTH/CTS_WIDTH");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ath_set_width(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
const char *intf, const char *val)
|
|
{
|
|
char buf[60];
|
|
|
|
if (strcasecmp(val, "Auto") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
|
|
dut->chwidth = 0;
|
|
} else if (strcasecmp(val, "20") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
|
|
dut->chwidth = 0;
|
|
} else if (strcasecmp(val, "40") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 1", intf);
|
|
dut->chwidth = 1;
|
|
} else if (strcasecmp(val, "80") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
|
|
dut->chwidth = 2;
|
|
} else if (strcasecmp(val, "160") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 3", intf);
|
|
dut->chwidth = 3;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,WIDTH not supported");
|
|
return -1;
|
|
}
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv chwidth failed");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int wcn_sta_set_sp_stream(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[60];
|
|
|
|
if (strcmp(val, "1SS") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s nss 1", intf);
|
|
} else if (strcmp(val, "2SS") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s nss 2", intf);
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"SP_STREAM value not supported");
|
|
return -1;
|
|
}
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set SP_STREAM");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_preset_testparameters(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
|
|
val = get_param(cmd, "Program");
|
|
if (val && strcasecmp(val, "HS2-R2") == 0) {
|
|
if (intf == NULL)
|
|
return -1;
|
|
return cmd_sta_preset_testparameters_hs2_r2(dut, conn, intf,
|
|
cmd);
|
|
}
|
|
|
|
#ifdef ANDROID_NAN
|
|
if (val && strcasecmp(val, "NAN") == 0)
|
|
return nan_cmd_sta_preset_testparameters(dut, conn, cmd);
|
|
#endif /* ANDROID_NAN */
|
|
|
|
#if 0
|
|
val = get_param(cmd, "Supplicant");
|
|
if (val && strcasecmp(val, "Default") != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Only default(Vendor) supplicant "
|
|
"supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
val = get_param(cmd, "RTS");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_rts(dut, intf, val);
|
|
break;
|
|
default:
|
|
#if 0
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Setting RTS not supported");
|
|
return 0;
|
|
#else
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Setting RTS not supported");
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
val = get_param(cmd, "FRGMNT");
|
|
if (val) {
|
|
/* TODO */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Setting FRGMNT not supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
val = get_param(cmd, "Preamble");
|
|
if (val) {
|
|
/* TODO: Long/Short */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Setting Preamble not supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
val = get_param(cmd, "Mode");
|
|
if (val) {
|
|
if (strcmp(val, "11b") == 0 ||
|
|
strcmp(val, "11g") == 0 ||
|
|
strcmp(val, "11a") == 0 ||
|
|
strcmp(val, "11n") == 0 ||
|
|
strcmp(val, "11ng") == 0 ||
|
|
strcmp(val, "11nl") == 0 ||
|
|
strcmp(val, "11nl(nabg)") == 0 ||
|
|
strcmp(val, "AC") == 0 ||
|
|
strcmp(val, "11AC") == 0 ||
|
|
strcmp(val, "11ac") == 0 ||
|
|
strcmp(val, "11na") == 0 ||
|
|
strcmp(val, "11an") == 0) {
|
|
/* STA supports all modes by default */
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Setting Mode not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "wmm");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_wmm(dut, intf, val);
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Setting wmm not supported");
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "Powersave");
|
|
if (val) {
|
|
if (strcmp(val, "0") == 0 || strcasecmp(val, "off") == 0) {
|
|
if (wpa_command(get_station_ifname(),
|
|
"P2P_SET ps 0") < 0)
|
|
return -2;
|
|
/* Make sure test modes are disabled */
|
|
wpa_command(get_station_ifname(), "P2P_SET ps 98");
|
|
wpa_command(get_station_ifname(), "P2P_SET ps 96");
|
|
} else if (strcmp(val, "1") == 0 ||
|
|
strcasecmp(val, "PSPoll") == 0 ||
|
|
strcasecmp(val, "on") == 0) {
|
|
/* Disable default power save mode */
|
|
wpa_command(get_station_ifname(), "P2P_SET ps 0");
|
|
/* Enable PS-Poll test mode */
|
|
if (wpa_command(get_station_ifname(),
|
|
"P2P_SET ps 97") < 0 ||
|
|
wpa_command(get_station_ifname(),
|
|
"P2P_SET ps 99") < 0)
|
|
return -2;
|
|
} else if (strcmp(val, "2") == 0 ||
|
|
strcasecmp(val, "Fast") == 0) {
|
|
/* TODO */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Powersave=Fast not supported");
|
|
return 0;
|
|
} else if (strcmp(val, "3") == 0 ||
|
|
strcasecmp(val, "PSNonPoll") == 0) {
|
|
/* Make sure test modes are disabled */
|
|
wpa_command(get_station_ifname(), "P2P_SET ps 98");
|
|
wpa_command(get_station_ifname(), "P2P_SET ps 96");
|
|
|
|
/* Enable default power save mode */
|
|
if (wpa_command(get_station_ifname(),
|
|
"P2P_SET ps 1") < 0)
|
|
return -2;
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "NoAck");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_noack(dut, intf, val);
|
|
break;
|
|
default:
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Setting NoAck not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "IgnoreChswitchProhibit");
|
|
if (val) {
|
|
/* TODO: Enabled/disabled */
|
|
if (strcasecmp(val, "Enabled") == 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Enabling IgnoreChswitchProhibit "
|
|
"not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "TDLS");
|
|
if (val) {
|
|
if (strcasecmp(val, "Disabled") == 0) {
|
|
if (wpa_command(intf, "SET tdls_disabled 1")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to disable TDLS");
|
|
return 0;
|
|
}
|
|
} else if (strcasecmp(val, "Enabled") == 0) {
|
|
if (wpa_command(intf, "SET tdls_disabled 0")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to enable TDLS");
|
|
return 0;
|
|
}
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported TDLS value");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "TDLSmode");
|
|
if (val) {
|
|
if (strcasecmp(val, "Default") == 0) {
|
|
wpa_command(intf, "SET tdls_testing 0");
|
|
} else if (strcasecmp(val, "APProhibit") == 0) {
|
|
if (wpa_command(intf, "SET tdls_testing 0x400")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to enable ignore "
|
|
"APProhibit TDLS mode");
|
|
return 0;
|
|
}
|
|
} else if (strcasecmp(val, "HiLoMac") == 0) {
|
|
/* STA should respond with TDLS setup req for a TDLS
|
|
* setup req */
|
|
if (wpa_command(intf, "SET tdls_testing 0x80")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to enable HiLoMac "
|
|
"TDLS mode");
|
|
return 0;
|
|
}
|
|
} else if (strcasecmp(val, "WeakSecurity") == 0) {
|
|
/*
|
|
* Since all security modes are enabled by default when
|
|
* Sigma control is used, there is no need to do
|
|
* anything here.
|
|
*/
|
|
} else if (strcasecmp(val, "ExistLink") == 0) {
|
|
/*
|
|
* Since we allow new TDLS Setup Request even if there
|
|
* is an existing link, nothing needs to be done for
|
|
* this.
|
|
*/
|
|
} else {
|
|
/* TODO:
|
|
* ExistLink: STA should send TDLS setup req even if
|
|
* direct link already exists
|
|
*/
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported TDLSmode value");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "FakePubKey");
|
|
if (val && atoi(val) && wpa_command(intf, "SET wps_corrupt_pkhash 1")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to enable FakePubKey");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static const char * ath_get_radio_name(const char *radio_name)
|
|
{
|
|
if (radio_name == NULL)
|
|
return "wifi0";
|
|
if (strcmp(radio_name, "wifi1") == 0)
|
|
return "wifi1";
|
|
if (strcmp(radio_name, "wifi2") == 0)
|
|
return "wifi2";
|
|
return "wifi0";
|
|
}
|
|
|
|
|
|
static void ath_sta_set_txsp_stream(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[60];
|
|
unsigned int vht_mcsmap = 0;
|
|
int txchainmask = 0;
|
|
const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
|
|
|
|
if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
|
|
if (dut->testbed_flag_txsp == 1) {
|
|
vht_mcsmap = 0xfffc;
|
|
dut->testbed_flag_txsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xfffe;
|
|
}
|
|
txchainmask = 1;
|
|
} else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
|
|
if (dut->testbed_flag_txsp == 1) {
|
|
vht_mcsmap = 0xfff0;
|
|
dut->testbed_flag_txsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xfffa;
|
|
}
|
|
txchainmask = 3;
|
|
} else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
|
|
if (dut->testbed_flag_txsp == 1) {
|
|
vht_mcsmap = 0xffc0;
|
|
dut->testbed_flag_txsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xffea;
|
|
}
|
|
txchainmask = 7;
|
|
} else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
|
|
if (dut->testbed_flag_txsp == 1) {
|
|
vht_mcsmap = 0xff00;
|
|
dut->testbed_flag_txsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xffaa;
|
|
}
|
|
txchainmask = 15;
|
|
} else {
|
|
if (dut->testbed_flag_txsp == 1) {
|
|
vht_mcsmap = 0xffc0;
|
|
dut->testbed_flag_txsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xffea;
|
|
}
|
|
}
|
|
|
|
if (txchainmask) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
|
|
basedev, txchainmask);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv txchainmask failed");
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
|
|
intf, vht_mcsmap);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s vht_mcsmap 0x%04x failed",
|
|
intf, vht_mcsmap);
|
|
}
|
|
}
|
|
|
|
|
|
static void ath_sta_set_rxsp_stream(struct sigma_dut *dut, const char *intf,
|
|
const char *val)
|
|
{
|
|
char buf[60];
|
|
unsigned int vht_mcsmap = 0;
|
|
int rxchainmask = 0;
|
|
const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
|
|
|
|
if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
|
|
if (dut->testbed_flag_rxsp == 1) {
|
|
vht_mcsmap = 0xfffc;
|
|
dut->testbed_flag_rxsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xfffe;
|
|
}
|
|
rxchainmask = 1;
|
|
} else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
|
|
if (dut->testbed_flag_rxsp == 1) {
|
|
vht_mcsmap = 0xfff0;
|
|
dut->testbed_flag_rxsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xfffa;
|
|
}
|
|
rxchainmask = 3;
|
|
} else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
|
|
if (dut->testbed_flag_rxsp == 1) {
|
|
vht_mcsmap = 0xffc0;
|
|
dut->testbed_flag_rxsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xffea;
|
|
}
|
|
rxchainmask = 7;
|
|
} else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
|
|
if (dut->testbed_flag_rxsp == 1) {
|
|
vht_mcsmap = 0xff00;
|
|
dut->testbed_flag_rxsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xffaa;
|
|
}
|
|
rxchainmask = 15;
|
|
} else {
|
|
if (dut->testbed_flag_rxsp == 1) {
|
|
vht_mcsmap = 0xffc0;
|
|
dut->testbed_flag_rxsp = 0;
|
|
} else {
|
|
vht_mcsmap = 0xffea;
|
|
}
|
|
}
|
|
|
|
if (rxchainmask) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
|
|
basedev, rxchainmask);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv rxchainmask failed");
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
|
|
intf, vht_mcsmap);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s vht_mcsmap 0x%04x",
|
|
intf, vht_mcsmap);
|
|
}
|
|
}
|
|
|
|
|
|
void ath_set_zero_crc(struct sigma_dut *dut, const char *val)
|
|
{
|
|
if (strcasecmp(val, "enable") == 0) {
|
|
if (system("athdiag --set --address=0x2a204 --and=0xbfffffff")
|
|
!= 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Disable BB_VHTSIGB_CRC_CALC failed");
|
|
}
|
|
|
|
if (system("athdiag --set --address=0x2a204 --or=0x80000000")
|
|
!= 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Enable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
|
|
}
|
|
} else {
|
|
if (system("athdiag --set --address=0x2a204 --and=0x7fffffff")
|
|
!= 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Disable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
|
|
}
|
|
|
|
if (system("athdiag --set --address=0x2a204 --or=0x40000000")
|
|
!= 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Enable BB_VHTSIGB_CRC_CALC failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_wireless_common(const char *intf, struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
int ampdu = -1;
|
|
char buf[30];
|
|
|
|
val = get_param(cmd, "40_INTOLERANT");
|
|
if (val) {
|
|
if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
|
|
/* TODO: iwpriv ht40intol through wpa_supplicant */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,40_INTOLERANT not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "ADDBA_REJECT");
|
|
if (val) {
|
|
if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
|
|
/* reject any ADDBA with status "decline" */
|
|
ampdu = 0;
|
|
} else {
|
|
/* accept ADDBA */
|
|
ampdu = 1;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "AMPDU");
|
|
if (val) {
|
|
if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
|
|
/* enable AMPDU Aggregation */
|
|
if (ampdu == 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Mismatch in "
|
|
"addba_reject/ampdu - "
|
|
"not supported");
|
|
return 0;
|
|
}
|
|
ampdu = 1;
|
|
} else {
|
|
/* disable AMPDU Aggregation */
|
|
if (ampdu == 1) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Mismatch in "
|
|
"addba_reject/ampdu - "
|
|
"not supported");
|
|
return 0;
|
|
}
|
|
ampdu = 0;
|
|
}
|
|
}
|
|
|
|
if (ampdu >= 0) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "%s A-MPDU aggregation",
|
|
ampdu ? "Enabling" : "Disabling");
|
|
snprintf(buf, sizeof(buf), "SET ampdu %d", ampdu);
|
|
if (wpa_command(intf, buf) < 0 &&
|
|
iwpriv_sta_set_ampdu(dut, intf, ampdu) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,set aggr failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "AMSDU");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_amsdu(dut, intf, val);
|
|
break;
|
|
default:
|
|
if (strcmp(val, "1") == 0 ||
|
|
strcasecmp(val, "Enable") == 0) {
|
|
/* Enable AMSDU Aggregation */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,AMSDU aggregation not supported");
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "STBC_RX");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_stbc(dut, intf, val);
|
|
break;
|
|
default:
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,STBC_RX not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "WIDTH");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_WCN:
|
|
if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set WIDTH");
|
|
return 0;
|
|
}
|
|
break;
|
|
case DRIVER_ATHEROS:
|
|
if (ath_set_width(dut, conn, intf, val) < 0)
|
|
return 0;
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Setting WIDTH not supported");
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "SMPS");
|
|
if (val) {
|
|
/* TODO: Dynamic/0, Static/1, No Limit/2 */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,SMPS not supported");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "TXSP_STREAM");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_WCN:
|
|
if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set TXSP_STREAM");
|
|
return 0;
|
|
}
|
|
break;
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_txsp_stream(dut, intf, val);
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Setting TXSP_STREAM not supported");
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "RXSP_STREAM");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_WCN:
|
|
if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set RXSP_STREAM");
|
|
return 0;
|
|
}
|
|
break;
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_rxsp_stream(dut, intf, val);
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Setting RXSP_STREAM not supported");
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "DYN_BW_SGNL");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_WCN:
|
|
snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set cts_cbw in DYN_BW_SGNL");
|
|
return 0;
|
|
}
|
|
break;
|
|
case DRIVER_ATHEROS:
|
|
novap_reset(dut, intf);
|
|
ath_config_dyn_bw_sig(dut, intf, val);
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set DYN_BW_SGNL");
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "RTS_FORCE");
|
|
if (val) {
|
|
novap_reset(dut, intf);
|
|
if (strcasecmp(val, "Enable") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwconfig %s rts 64", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set RTS_FORCE 64");
|
|
}
|
|
snprintf(buf, sizeof(buf),
|
|
"wifitool %s beeliner_fw_test 100 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"wifitool beeliner_fw_test 100 1 failed");
|
|
}
|
|
} else if (strcasecmp(val, "Disable") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwconfig %s rts 2347",
|
|
intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set RTS_FORCE 2347");
|
|
}
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,RTS_FORCE value not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "CTS_WIDTH");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_WCN:
|
|
if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set CTS_WIDTH");
|
|
return 0;
|
|
}
|
|
break;
|
|
case DRIVER_ATHEROS:
|
|
ath_set_cts_width(dut, intf, val);
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Setting CTS_WIDTH not supported");
|
|
break;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "BW_SGNL");
|
|
if (val) {
|
|
if (strcasecmp(val, "Enable") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1",
|
|
intf);
|
|
} else if (strcasecmp(val, "Disable") == 0) {
|
|
/* TODO: Disable */
|
|
buf[0] = '\0';
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,BW_SGNL value not supported");
|
|
return 0;
|
|
}
|
|
|
|
if (buf[0] != '\0' && system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set BW_SGNL");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "Band");
|
|
if (val) {
|
|
if (strcmp(val, "2.4") == 0 || strcmp(val, "5") == 0) {
|
|
/* STA supports all bands by default */
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported Band");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "zero_crc");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_set_zero_crc(dut, val);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int sta_set_60g_common(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
char buf[100];
|
|
|
|
val = get_param(cmd, "MSDUSize");
|
|
if (val) {
|
|
int mtu;
|
|
|
|
dut->amsdu_size = atoi(val);
|
|
if (dut->amsdu_size > IEEE80211_MAX_DATA_LEN_DMG ||
|
|
dut->amsdu_size < IEEE80211_SNAP_LEN_DMG) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"MSDUSize %d is above max %d or below min %d",
|
|
dut->amsdu_size,
|
|
IEEE80211_MAX_DATA_LEN_DMG,
|
|
IEEE80211_SNAP_LEN_DMG);
|
|
dut->amsdu_size = 0;
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
mtu = dut->amsdu_size - IEEE80211_SNAP_LEN_DMG;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Setting amsdu_size to %d", mtu);
|
|
snprintf(buf, sizeof(buf), "ifconfig %s mtu %d",
|
|
get_station_ifname(), mtu);
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set %s",
|
|
buf);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "BAckRcvBuf");
|
|
if (val) {
|
|
dut->back_rcv_buf = atoi(val);
|
|
if (dut->back_rcv_buf == 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to convert %s or value is 0",
|
|
val);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Setting BAckRcvBuf to %s", val);
|
|
}
|
|
|
|
return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
|
|
static int sta_pcp_start(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
int net_id;
|
|
char *ifname;
|
|
const char *val;
|
|
char buf[100];
|
|
|
|
dut->mode = SIGMA_MODE_STATION;
|
|
ifname = get_main_ifname();
|
|
if (wpa_command(ifname, "PING") != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Supplicant not running");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
wpa_command(ifname, "FLUSH");
|
|
net_id = add_network_common(dut, conn, ifname, cmd);
|
|
if (net_id < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add network");
|
|
return net_id;
|
|
}
|
|
|
|
/* TODO: mode=2 for the AP; in the future, replace for mode PCP */
|
|
if (set_network(ifname, net_id, "mode", "2") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant network mode");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Supplicant set network with mode 2");
|
|
|
|
val = get_param(cmd, "Security");
|
|
if (val && strcasecmp(val, "OPEN") == 0) {
|
|
dut->ap_key_mgmt = AP_OPEN;
|
|
if (set_network(ifname, net_id, "key_mgmt", "NONE") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant to %s security",
|
|
val);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
} else if (val && strcasecmp(val, "WPA2-PSK") == 0) {
|
|
dut->ap_key_mgmt = AP_WPA2_PSK;
|
|
if (set_network(ifname, net_id, "key_mgmt", "WPA-PSK") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant to %s security",
|
|
val);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
if (set_network(ifname, net_id, "proto", "RSN") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant to proto RSN");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
} else if (val) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Requested Security %s is not supported on 60GHz",
|
|
val);
|
|
return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
val = get_param(cmd, "Encrypt");
|
|
if (val && strcasecmp(val, "AES-GCMP") == 0) {
|
|
if (set_network(ifname, net_id, "pairwise", "GCMP") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant to pairwise GCMP");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
if (set_network(ifname, net_id, "group", "GCMP") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant to group GCMP");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
} else if (val) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Requested Encrypt %s is not supported on 60 GHz",
|
|
val);
|
|
return SIGMA_DUT_INVALID_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
val = get_param(cmd, "PSK");
|
|
if (val && set_network_quoted(ifname, net_id, "psk", val) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set psk %s",
|
|
val);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
/* Convert 60G channel to freq */
|
|
switch (dut->ap_channel) {
|
|
case 1:
|
|
val = "58320";
|
|
break;
|
|
case 2:
|
|
val = "60480";
|
|
break;
|
|
case 3:
|
|
val = "62640";
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to configure channel %d. Not supported",
|
|
dut->ap_channel);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
if (set_network(ifname, net_id, "frequency", val) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to set supplicant network frequency");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Supplicant set network with frequency");
|
|
|
|
snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", net_id);
|
|
if (wpa_command(ifname, buf) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Failed to select network id %d on %s",
|
|
net_id, ifname);
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Selected network");
|
|
|
|
return SIGMA_DUT_SUCCESS_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
|
|
static int sta_set_60g_pcp(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
|
|
if (dut->dev_role != DEVROLE_PCP) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,Invalid DevRole");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "SSID");
|
|
if (val) {
|
|
if (strlen(val) > sizeof(dut->ap_ssid) - 1) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,Invalid SSID");
|
|
return -1;
|
|
}
|
|
|
|
strncpy(dut->ap_ssid, val, sizeof(dut->ap_ssid));
|
|
}
|
|
|
|
val = get_param(cmd, "CHANNEL");
|
|
if (val) {
|
|
const char *pos;
|
|
|
|
dut->ap_channel = atoi(val);
|
|
pos = strchr(val, ';');
|
|
if (pos) {
|
|
pos++;
|
|
dut->ap_channel_1 = atoi(pos);
|
|
}
|
|
}
|
|
|
|
switch (dut->ap_channel) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Channel %d is not supported", dut->ap_channel);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"Requested channel is not supported");
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "BCNINT");
|
|
if (val)
|
|
dut->ap_bcnint = atoi(val);
|
|
|
|
|
|
val = get_param(cmd, "ExtSchIE");
|
|
if (val) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,ExtSchIE is not supported yet");
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "AllocType");
|
|
if (val) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,AllocType is not supported yet");
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "PercentBI");
|
|
if (val) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,PercentBI is not supported yet");
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "CBAPOnly");
|
|
if (val) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,CBAPOnly is not supported yet");
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "AMPDU");
|
|
if (val) {
|
|
if (strcasecmp(val, "Enable") == 0)
|
|
dut->ap_ampdu = 1;
|
|
else if (strcasecmp(val, "Disable") == 0)
|
|
dut->ap_ampdu = 2;
|
|
else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,AMPDU value is not Enable nor Disabled");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "AMSDU");
|
|
if (val) {
|
|
if (strcasecmp(val, "Enable") == 0)
|
|
dut->ap_amsdu = 1;
|
|
else if (strcasecmp(val, "Disable") == 0)
|
|
dut->ap_amsdu = 2;
|
|
}
|
|
|
|
val = get_param(cmd, "NumMSDU");
|
|
if (val) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode, NumMSDU is not supported yet");
|
|
return -1;
|
|
}
|
|
|
|
val = get_param(cmd, "ABFTLRang");
|
|
if (val) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Ignoring ABFTLRang parameter since FW default is greater than 1");
|
|
}
|
|
|
|
if (sta_pcp_start(dut, conn, cmd) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode, Can't start PCP role");
|
|
return -1;
|
|
}
|
|
|
|
return sta_set_60g_common(dut, conn, cmd);
|
|
}
|
|
|
|
|
|
static int sta_set_60g_sta(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val = get_param(cmd, "DiscoveryMode");
|
|
|
|
if (dut->dev_role != DEVROLE_STA) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,Invalid DevRole");
|
|
return 0;
|
|
}
|
|
|
|
if (val) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Discovery: %s", val);
|
|
/* Ignore Discovery mode till Driver expose API. */
|
|
#if 0
|
|
if (strcasecmp(val, "1") == 0) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,DiscoveryMode 1 not supported");
|
|
return 0;
|
|
}
|
|
|
|
if (strcasecmp(val, "0") == 0) {
|
|
/* OK */
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,DiscoveryMode not supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (start_sta_mode(dut) != 0)
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
return sta_set_60g_common(dut, conn, cmd);
|
|
}
|
|
|
|
|
|
static int cmd_sta_disconnect(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
disconnect_station(dut);
|
|
/* Try to ignore old scan results to avoid HS 2.0R2 test case failures
|
|
* due to cached results. */
|
|
wpa_command(intf, "SET ignore_old_scan_res 1");
|
|
wpa_command(intf, "BSS_FLUSH");
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_reassoc(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *bssid = get_param(cmd, "bssid");
|
|
const char *val = get_param(cmd, "CHANNEL");
|
|
struct wpa_ctrl *ctrl;
|
|
char buf[100];
|
|
int res;
|
|
int chan = 0;
|
|
|
|
if (bssid == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing bssid "
|
|
"argument");
|
|
return 0;
|
|
}
|
|
|
|
if (val)
|
|
chan = atoi(val);
|
|
|
|
if (wifi_chip_type != DRIVER_WCN && wifi_chip_type != DRIVER_AR6003) {
|
|
/* The current network may be from sta_associate or
|
|
* sta_hs2_associate
|
|
*/
|
|
if (set_network(intf, dut->infra_network_id, "bssid", bssid) <
|
|
0 ||
|
|
set_network(intf, 0, "bssid", bssid) < 0)
|
|
return -2;
|
|
}
|
|
|
|
ctrl = open_wpa_mon(intf);
|
|
if (ctrl == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
|
|
"wpa_supplicant monitor connection");
|
|
return -1;
|
|
}
|
|
|
|
if (wifi_chip_type == DRIVER_WCN) {
|
|
#ifdef ANDROID
|
|
if (set_network(intf, dut->infra_network_id, "bssid", "any")
|
|
< 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
|
|
"bssid to any during FASTREASSOC");
|
|
return -2;
|
|
}
|
|
res = snprintf(buf, sizeof(buf), "DRIVER FASTREASSOC %s %d",
|
|
bssid, chan);
|
|
if (res > 0 && res < (int) sizeof(buf))
|
|
res = wpa_command(intf, buf);
|
|
|
|
if (res < 0 || res >= (int) sizeof(buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to run DRIVER FASTREASSOC");
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
return 0;
|
|
}
|
|
#else /* ANDROID */
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Reassoc using iwpriv - skip chan=%d info",
|
|
chan);
|
|
snprintf(buf, sizeof(buf), "iwpriv %s reassoc", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "%s failed", buf);
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
return 0;
|
|
}
|
|
#endif /* ANDROID */
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"sta_reassoc: Run %s successful", buf);
|
|
} else if (wpa_command(intf, "REASSOCIATE")) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
|
|
"request reassociation");
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
return 0;
|
|
}
|
|
|
|
res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
|
|
buf, sizeof(buf));
|
|
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
|
|
if (res < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static void hs2_clear_credentials(const char *intf)
|
|
{
|
|
wpa_command(intf, "REMOVE_CRED all");
|
|
}
|
|
|
|
|
|
static int sta_get_parameter_60g(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
char buf[MAX_CMD_LEN];
|
|
char bss_list[MAX_CMD_LEN];
|
|
const char *parameter = get_param(cmd, "Parameter");
|
|
|
|
if (parameter == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(parameter, "DiscoveredDevList") == 0) {
|
|
char *bss_line;
|
|
char *bss_id = NULL;
|
|
const char *ifname = get_param(cmd, "Interface");
|
|
char *saveptr;
|
|
|
|
if (ifname == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"For get DiscoveredDevList need Interface name.");
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Use "BSS RANGE=ALL MASK=0x2" which provides a list
|
|
* of BSSIDs in "bssid=<BSSID>\n"
|
|
*/
|
|
if (wpa_command_resp(ifname, "BSS RANGE=ALL MASK=0x2",
|
|
bss_list,
|
|
sizeof(bss_list)) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to get bss list");
|
|
return -1;
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"bss list for ifname:%s is:%s",
|
|
ifname, bss_list);
|
|
|
|
snprintf(buf, sizeof(buf), "DeviceList");
|
|
bss_line = strtok_r(bss_list, "\n", &saveptr);
|
|
while (bss_line) {
|
|
if (sscanf(bss_line, "bssid=%ms", &bss_id) > 0 &&
|
|
bss_id) {
|
|
int len;
|
|
|
|
len = snprintf(buf + strlen(buf),
|
|
sizeof(buf) - strlen(buf),
|
|
",%s", bss_id);
|
|
free(bss_id);
|
|
bss_id = NULL;
|
|
if (len < 0) {
|
|
sigma_dut_print(dut,
|
|
DUT_MSG_ERROR,
|
|
"Failed to read BSSID");
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to read BSS ID");
|
|
return 0;
|
|
}
|
|
|
|
if ((size_t) len >= sizeof(buf) - strlen(buf)) {
|
|
sigma_dut_print(dut,
|
|
DUT_MSG_ERROR,
|
|
"Response buf too small for list");
|
|
send_resp(dut, conn,
|
|
SIGMA_ERROR,
|
|
"ErrorCode,Response buf too small for list");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bss_line = strtok_r(NULL, "\n", &saveptr);
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "DiscoveredDevList is %s",
|
|
buf);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, buf);
|
|
return 0;
|
|
}
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *program = get_param(cmd, "Program");
|
|
|
|
if (program == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(program, "P2PNFC") == 0)
|
|
return p2p_cmd_sta_get_parameter(dut, conn, cmd);
|
|
|
|
if (strcasecmp(program, "60ghz") == 0)
|
|
return sta_get_parameter_60g(dut, conn, cmd);
|
|
|
|
#ifdef ANDROID_NAN
|
|
if (strcasecmp(program, "NAN") == 0)
|
|
return nan_cmd_sta_exec_action(dut, conn, cmd);
|
|
#endif /* ANDROID_NAN */
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void sta_reset_default_ath(struct sigma_dut *dut, const char *intf,
|
|
const char *type)
|
|
{
|
|
char buf[100];
|
|
|
|
if (dut->program == PROGRAM_VHT) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s chwidth failed", intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s mode 11ACVHT80", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s mode 11ACVHT80 failed",
|
|
intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs -1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s vhtmcs -1 failed", intf);
|
|
}
|
|
}
|
|
|
|
if (dut->program == PROGRAM_HT) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s chwidth failed", intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s mode 11naht40", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s mode 11naht40 failed",
|
|
intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv set11NRates failed");
|
|
}
|
|
}
|
|
|
|
if (dut->program == PROGRAM_VHT || dut->program == PROGRAM_HT) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s powersave 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"disabling powersave failed");
|
|
}
|
|
|
|
/* Reset CTS width */
|
|
snprintf(buf, sizeof(buf), "wifitool %s beeliner_fw_test 54 0",
|
|
intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"wifitool %s beeliner_fw_test 54 0 failed",
|
|
intf);
|
|
}
|
|
|
|
/* Enable Dynamic Bandwidth signalling by default */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s cwmenable 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s cwmenable 1 failed", intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwconfig %s rts 2347", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv rts failed");
|
|
}
|
|
}
|
|
|
|
if (type && strcasecmp(type, "Testbed") == 0) {
|
|
dut->testbed_flag_txsp = 1;
|
|
dut->testbed_flag_rxsp = 1;
|
|
/* STA has to set spatial stream to 2 per Appendix H */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0xfff0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vht_mcsmap failed");
|
|
}
|
|
|
|
/* Disable LDPC per Appendix H */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s ldpc 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s ldpc 0 failed", intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv amsdu failed");
|
|
}
|
|
|
|
/* TODO: Disable STBC 2x1 transmit and receive */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Disable tx_stbc 0 failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Disable rx_stbc 0 failed");
|
|
}
|
|
|
|
/* STA has to disable Short GI per Appendix H */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s shortgi 0", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s shortgi 0 failed", intf);
|
|
}
|
|
}
|
|
|
|
if (type && strcasecmp(type, "DUT") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s nss 3", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s nss 3 failed", intf);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s shortgi 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv %s shortgi 1 failed", intf);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static int cmd_sta_reset_default(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd);
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *type;
|
|
|
|
dut->program = sigma_program_to_enum(get_param(cmd, "prog"));
|
|
dut->device_type = STA_unknown;
|
|
type = get_param(cmd, "type");
|
|
if (type && strcasecmp(type, "Testbed") == 0)
|
|
dut->device_type = STA_testbed;
|
|
if (type && strcasecmp(type, "DUT") == 0)
|
|
dut->device_type = STA_dut;
|
|
|
|
if (dut->program == PROGRAM_TDLS) {
|
|
/* Clear TDLS testing mode */
|
|
wpa_command(intf, "SET tdls_disabled 0");
|
|
wpa_command(intf, "SET tdls_testing 0");
|
|
dut->no_tpk_expiration = 0;
|
|
}
|
|
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
sta_reset_default_ath(dut, intf, type);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
#ifdef ANDROID_NAN
|
|
if (dut->program == PROGRAM_NAN)
|
|
nan_cmd_sta_reset_default(dut, conn, cmd);
|
|
#endif /* ANDROID_NAN */
|
|
|
|
if (dut->program == PROGRAM_HS2_R2) {
|
|
unlink("SP/wi-fi.org/pps.xml");
|
|
if (system("rm -r SP/*") != 0) {
|
|
}
|
|
unlink("next-client-cert.pem");
|
|
unlink("next-client-key.pem");
|
|
}
|
|
|
|
if (dut->program == PROGRAM_60GHZ) {
|
|
const char *dev_role = get_param(cmd, "DevRole");
|
|
|
|
if (!dev_role) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Missing DevRole argument");
|
|
return 0;
|
|
}
|
|
|
|
if (strcasecmp(dev_role, "STA") == 0)
|
|
dut->dev_role = DEVROLE_STA;
|
|
else if (strcasecmp(dev_role, "PCP") == 0)
|
|
dut->dev_role = DEVROLE_PCP;
|
|
else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unknown DevRole");
|
|
return 0;
|
|
}
|
|
|
|
if (dut->device_type == STA_unknown) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Device type is not STA testbed or DUT");
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unknown device type");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
wpa_command(intf, "WPS_ER_STOP");
|
|
wpa_command(intf, "FLUSH");
|
|
wpa_command(intf, "SET radio_disabled 0");
|
|
|
|
if (dut->tmp_mac_addr && dut->set_macaddr) {
|
|
dut->tmp_mac_addr = 0;
|
|
if (system(dut->set_macaddr) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to clear "
|
|
"temporary MAC address");
|
|
}
|
|
}
|
|
|
|
set_ps(intf, dut, 0);
|
|
|
|
if (dut->program == PROGRAM_HS2 || dut->program == PROGRAM_HS2_R2) {
|
|
wpa_command(intf, "SET interworking 1");
|
|
wpa_command(intf, "SET hs20 1");
|
|
}
|
|
|
|
if (dut->program == PROGRAM_HS2_R2) {
|
|
wpa_command(intf, "SET pmf 1");
|
|
} else {
|
|
wpa_command(intf, "SET pmf 0");
|
|
}
|
|
|
|
hs2_clear_credentials(intf);
|
|
wpa_command(intf, "SET hessid 00:00:00:00:00:00");
|
|
wpa_command(intf, "SET access_network_type 15");
|
|
|
|
static_ip_file(0, NULL, NULL, NULL);
|
|
kill_dhcp_client(dut, intf);
|
|
clear_ip_addr(dut, intf);
|
|
|
|
dut->er_oper_performed = 0;
|
|
dut->er_oper_bssid[0] = '\0';
|
|
|
|
if (dut->program != PROGRAM_VHT)
|
|
return cmd_sta_p2p_reset(dut, conn, cmd);
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *program = get_param(cmd, "Program");
|
|
|
|
if (program == NULL)
|
|
return -1;
|
|
#ifdef ANDROID_NAN
|
|
if (strcasecmp(program, "NAN") == 0)
|
|
return nan_cmd_sta_get_events(dut, conn, cmd);
|
|
#endif /* ANDROID_NAN */
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *program = get_param(cmd, "Prog");
|
|
|
|
if (program == NULL)
|
|
return -1;
|
|
#ifdef ANDROID_NAN
|
|
if (strcasecmp(program, "NAN") == 0)
|
|
return nan_cmd_sta_exec_action(dut, conn, cmd);
|
|
#endif /* ANDROID_NAN */
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_11n(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val, *mcs32, *rate;
|
|
|
|
val = get_param(cmd, "GREENFIELD");
|
|
if (val) {
|
|
if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
|
|
/* Enable GD */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,GF not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "SGI20");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_sgi(dut, intf, val);
|
|
break;
|
|
default:
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,SGI20 not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
mcs32 = get_param(cmd, "MCS32"); /* HT Duplicate Mode Enable/Disable */
|
|
rate = get_param(cmd, "MCS_FIXEDRATE"); /* Fixed MCS rate (0..31) */
|
|
if (mcs32 && rate) {
|
|
/* TODO */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,MCS32,MCS_FIXEDRATE not supported");
|
|
return 0;
|
|
} else if (mcs32 && !rate) {
|
|
/* TODO */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,MCS32 not supported");
|
|
return 0;
|
|
} else if (!mcs32 && rate) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
novap_reset(dut, intf);
|
|
ath_sta_set_11nrates(dut, intf, rate);
|
|
break;
|
|
default:
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,MCS32_FIXEDRATE not supported");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_wireless_vht(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
char buf[30];
|
|
int tkip = -1;
|
|
int wep = -1;
|
|
|
|
val = get_param(cmd, "SGI80");
|
|
if (val) {
|
|
int sgi80;
|
|
|
|
sgi80 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
|
|
snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d", intf, sgi80);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv shortgi failed");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "TxBF");
|
|
if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfee 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vhtsubfee failed");
|
|
}
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtsubfer 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vhtsubfer failed");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "MU_TxBF");
|
|
if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
ath_sta_set_txsp_stream(dut, intf, "1SS");
|
|
ath_sta_set_rxsp_stream(dut, intf, "1SS");
|
|
case DRIVER_WCN:
|
|
if (wcn_sta_set_sp_stream(dut, intf, "1SS") < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set RX/TXSP_STREAM");
|
|
return 0;
|
|
}
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Setting SP_STREAM not supported");
|
|
break;
|
|
}
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfee 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vhtmubfee failed");
|
|
}
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtmubfer 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vhtmubfer failed");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "LDPC");
|
|
if (val) {
|
|
int ldpc;
|
|
|
|
ldpc = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
|
|
snprintf(buf, sizeof(buf), "iwpriv %s ldpc %d", intf, ldpc);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv ldpc failed");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "opt_md_notif_ie");
|
|
if (val) {
|
|
char *result = NULL;
|
|
char delim[] = ";";
|
|
char token[30];
|
|
int value, config_val = 0;
|
|
char *saveptr;
|
|
|
|
strncpy(token, val, sizeof(token));
|
|
token[sizeof(token) - 1] = '\0';
|
|
result = strtok_r(token, delim, &saveptr);
|
|
|
|
/* Extract the NSS information */
|
|
if (result) {
|
|
value = atoi(result);
|
|
switch (value) {
|
|
case 1:
|
|
config_val = 1;
|
|
break;
|
|
case 2:
|
|
config_val = 3;
|
|
break;
|
|
case 3:
|
|
config_val = 7;
|
|
break;
|
|
case 4:
|
|
config_val = 15;
|
|
break;
|
|
default:
|
|
config_val = 3;
|
|
break;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s rxchainmask %d",
|
|
intf, config_val);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv rxchainmask failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s txchainmask %d",
|
|
intf, config_val);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv txchainmask failed");
|
|
}
|
|
}
|
|
|
|
/* Extract the channel width information */
|
|
result = strtok_r(NULL, delim, &saveptr);
|
|
if (result) {
|
|
value = atoi(result);
|
|
switch (value) {
|
|
case 20:
|
|
config_val = 0;
|
|
break;
|
|
case 40:
|
|
config_val = 1;
|
|
break;
|
|
case 80:
|
|
config_val = 2;
|
|
break;
|
|
case 160:
|
|
config_val = 3;
|
|
break;
|
|
default:
|
|
config_val = 2;
|
|
break;
|
|
}
|
|
|
|
dut->chwidth = config_val;
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
|
|
intf, config_val);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv chwidth failed");
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv opmode_notify failed");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "nss_mcs_cap");
|
|
if (val) {
|
|
int nss, mcs;
|
|
char token[20];
|
|
char *result = NULL;
|
|
unsigned int vht_mcsmap = 0;
|
|
char *saveptr;
|
|
|
|
strncpy(token, val, sizeof(token));
|
|
token[sizeof(token) - 1] = '\0';
|
|
result = strtok_r(token, ";", &saveptr);
|
|
if (!result) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VHT NSS not specified");
|
|
return 0;
|
|
}
|
|
nss = atoi(result);
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s nss %d", intf, nss);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv nss failed");
|
|
}
|
|
|
|
result = strtok_r(NULL, ";", &saveptr);
|
|
if (result == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VHTMCS NOT SPECIFIED!");
|
|
return 0;
|
|
}
|
|
result = strtok_r(result, "-", &saveptr);
|
|
result = strtok_r(NULL, "-", &saveptr);
|
|
if (!result) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VHT MCS not specified");
|
|
return 0;
|
|
}
|
|
mcs = atoi(result);
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d", intf, mcs);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv mcs failed");
|
|
}
|
|
|
|
switch (nss) {
|
|
case 1:
|
|
switch (mcs) {
|
|
case 7:
|
|
vht_mcsmap = 0xfffc;
|
|
break;
|
|
case 8:
|
|
vht_mcsmap = 0xfffd;
|
|
break;
|
|
case 9:
|
|
vht_mcsmap = 0xfffe;
|
|
break;
|
|
default:
|
|
vht_mcsmap = 0xfffe;
|
|
break;
|
|
}
|
|
break;
|
|
case 2:
|
|
switch (mcs) {
|
|
case 7:
|
|
vht_mcsmap = 0xfff0;
|
|
break;
|
|
case 8:
|
|
vht_mcsmap = 0xfff5;
|
|
break;
|
|
case 9:
|
|
vht_mcsmap = 0xfffa;
|
|
break;
|
|
default:
|
|
vht_mcsmap = 0xfffa;
|
|
break;
|
|
}
|
|
break;
|
|
case 3:
|
|
switch (mcs) {
|
|
case 7:
|
|
vht_mcsmap = 0xffc0;
|
|
break;
|
|
case 8:
|
|
vht_mcsmap = 0xffd5;
|
|
break;
|
|
case 9:
|
|
vht_mcsmap = 0xffea;
|
|
break;
|
|
default:
|
|
vht_mcsmap = 0xffea;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
vht_mcsmap = 0xffea;
|
|
break;
|
|
}
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vht_mcsmap 0x%04x",
|
|
intf, vht_mcsmap);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vht_mcsmap failed");
|
|
}
|
|
}
|
|
|
|
/* UNSUPPORTED: val = get_param(cmd, "Tx_lgi_rate"); */
|
|
|
|
val = get_param(cmd, "Vht_tkip");
|
|
if (val)
|
|
tkip = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
|
|
|
|
val = get_param(cmd, "Vht_wep");
|
|
if (val)
|
|
wep = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
|
|
|
|
if (tkip != -1 || wep != -1) {
|
|
if ((tkip == 1 && wep != 0) || (wep == 1 && tkip != 0)) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 1",
|
|
intf);
|
|
} else if ((tkip == 0 && wep != 1) || (wep == 0 && tkip != 1)) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s htweptkip 0",
|
|
intf);
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"ErrorCode,mixed mode of VHT TKIP/WEP not supported");
|
|
return 0;
|
|
}
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv htweptkip failed");
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "txBandwidth");
|
|
if (val) {
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
if (ath_set_width(dut, conn, intf, val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set txBandwidth");
|
|
return 0;
|
|
}
|
|
break;
|
|
default:
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Setting txBandwidth not supported");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
|
|
}
|
|
|
|
|
|
static int sta_set_wireless_60g(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *dev_role = get_param(cmd, "DevRole");
|
|
|
|
if (!dev_role) {
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,DevRole not specified");
|
|
return 0;
|
|
}
|
|
|
|
if (strcasecmp(dev_role, "PCP") == 0)
|
|
return sta_set_60g_pcp(dut, conn, cmd);
|
|
if (strcasecmp(dev_role, "STA") == 0)
|
|
return sta_set_60g_sta(dut, conn, cmd);
|
|
send_resp(dut, conn, SIGMA_INVALID,
|
|
"ErrorCode,DevRole not supported");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_wireless(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
|
|
val = get_param(cmd, "Program");
|
|
if (val) {
|
|
if (strcasecmp(val, "11n") == 0)
|
|
return cmd_sta_set_11n(dut, conn, cmd);
|
|
if (strcasecmp(val, "VHT") == 0)
|
|
return cmd_sta_set_wireless_vht(dut, conn, cmd);
|
|
if (strcasecmp(val, "60ghz") == 0)
|
|
return sta_set_wireless_60g(dut, conn, cmd);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Program value not supported");
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Program argument not available");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void ath_sta_inject_frame(struct sigma_dut *dut, const char *intf,
|
|
int tid)
|
|
{
|
|
char buf[100];
|
|
int tid_to_dscp [] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 };
|
|
|
|
/*
|
|
* Two ways to ensure that addba request with a
|
|
* non zero TID could be sent out. EV 117296
|
|
*/
|
|
snprintf(buf, sizeof(buf),
|
|
"ping -c 8 -Q %d `arp -a | grep wlan0 | awk '{print $2}' | tr -d '()'`",
|
|
tid);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Ping did not send out");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
"iwconfig %s | grep Access | awk '{print $6}' > %s",
|
|
intf, VI_QOS_TMP_FILE);
|
|
if (system(buf) != 0)
|
|
return;
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
"ifconfig %s | grep HWaddr | cut -b 39-56 >> %s",
|
|
intf, VI_QOS_TMP_FILE);
|
|
if (system(buf) != 0)
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "HWaddr matching failed");
|
|
|
|
snprintf(buf,sizeof(buf), "sed -n '3,$p' %s >> %s",
|
|
VI_QOS_REFFILE, VI_QOS_TMP_FILE);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VI_QOS_TEMP_FILE generation error failed");
|
|
}
|
|
snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
|
|
tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VI_QOS_FILE generation failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
|
|
tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VI_QOS_FILE generation failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "ethinject %s %s", intf, VI_QOS_FILE);
|
|
if (system(buf) != 0) {
|
|
}
|
|
}
|
|
|
|
|
|
static int ath_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
int tid = 0;
|
|
char buf[100];
|
|
|
|
val = get_param(cmd, "TID");
|
|
if (val) {
|
|
tid = atoi(val);
|
|
if (tid)
|
|
ath_sta_inject_frame(dut, intf, tid);
|
|
}
|
|
|
|
/* Command sequence for ADDBA request on Peregrine based devices */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s setaddbaoper 1", intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv setaddbaoper failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "wifitool %s senddelba 1 %d 1 4", intf, tid);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"wifitool senddelba failed");
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "wifitool %s sendaddba 1 %d 64", intf, tid);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"wifitool sendaddba failed");
|
|
}
|
|
|
|
/* UNSUPPORTED: val = get_param(cmd, "Dest_mac"); */
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int send_addba_60g(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
int tid = 0;
|
|
char buf[100];
|
|
|
|
val = get_param(cmd, "TID");
|
|
if (val) {
|
|
tid = atoi(val);
|
|
if (tid != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Ignore TID %d for send_addba use TID 0 for 60g since only 0 required on TX",
|
|
tid);
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "Dest_mac");
|
|
if (!val) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Currently not supporting addba for 60G without Dest_mac");
|
|
return SIGMA_DUT_ERROR_CALLER_SEND_STATUS;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "wil6210_addba_req.py %s %d",
|
|
val, dut->back_rcv_buf);
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
|
|
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to send addba");
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
return ath_sta_send_addba(dut, conn, cmd);
|
|
case DRIVER_WIL6210:
|
|
return send_addba_60g(dut, conn, cmd);
|
|
default:
|
|
/*
|
|
* There is no driver specific implementation for other drivers.
|
|
* Ignore the command and report COMPLETE since the following
|
|
* throughput test operation will end up sending ADDBA anyway.
|
|
*/
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
int inject_eth_frame(int s, const void *data, size_t len,
|
|
unsigned short ethtype, char *dst, char *src)
|
|
{
|
|
struct iovec iov[4] = {
|
|
{
|
|
.iov_base = dst,
|
|
.iov_len = ETH_ALEN,
|
|
},
|
|
{
|
|
.iov_base = src,
|
|
.iov_len = ETH_ALEN,
|
|
},
|
|
{
|
|
.iov_base = ðtype,
|
|
.iov_len = sizeof(unsigned short),
|
|
},
|
|
{
|
|
.iov_base = (void *) data,
|
|
.iov_len = len,
|
|
}
|
|
};
|
|
struct msghdr msg = {
|
|
.msg_name = NULL,
|
|
.msg_namelen = 0,
|
|
.msg_iov = iov,
|
|
.msg_iovlen = 4,
|
|
.msg_control = NULL,
|
|
.msg_controllen = 0,
|
|
.msg_flags = 0,
|
|
};
|
|
|
|
return sendmsg(s, &msg, 0);
|
|
}
|
|
|
|
#if defined(__linux__) || defined(__QNXNTO__)
|
|
|
|
int inject_frame(int s, const void *data, size_t len, int encrypt)
|
|
{
|
|
#define IEEE80211_RADIOTAP_F_WEP 0x04
|
|
#define IEEE80211_RADIOTAP_F_FRAG 0x08
|
|
unsigned char rtap_hdr[] = {
|
|
0x00, 0x00, /* radiotap version */
|
|
0x0e, 0x00, /* radiotap length */
|
|
0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
|
|
IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
|
|
0x00, /* padding */
|
|
0x00, 0x00, /* RX and TX flags to indicate that */
|
|
0x00, 0x00, /* this is the injected frame directly */
|
|
};
|
|
struct iovec iov[2] = {
|
|
{
|
|
.iov_base = &rtap_hdr,
|
|
.iov_len = sizeof(rtap_hdr),
|
|
},
|
|
{
|
|
.iov_base = (void *) data,
|
|
.iov_len = len,
|
|
}
|
|
};
|
|
struct msghdr msg = {
|
|
.msg_name = NULL,
|
|
.msg_namelen = 0,
|
|
.msg_iov = iov,
|
|
.msg_iovlen = 2,
|
|
.msg_control = NULL,
|
|
.msg_controllen = 0,
|
|
.msg_flags = 0,
|
|
};
|
|
|
|
if (encrypt)
|
|
rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
|
|
|
|
return sendmsg(s, &msg, 0);
|
|
}
|
|
|
|
|
|
int open_monitor(const char *ifname)
|
|
{
|
|
#ifdef __QNXNTO__
|
|
struct sockaddr_dl ll;
|
|
int s;
|
|
|
|
memset(&ll, 0, sizeof(ll));
|
|
ll.sdl_family = AF_LINK;
|
|
ll.sdl_index = if_nametoindex(ifname);
|
|
if (ll.sdl_index == 0) {
|
|
perror("if_nametoindex");
|
|
return -1;
|
|
}
|
|
s = socket(PF_INET, SOCK_RAW, 0);
|
|
#else /* __QNXNTO__ */
|
|
struct sockaddr_ll ll;
|
|
int s;
|
|
|
|
memset(&ll, 0, sizeof(ll));
|
|
ll.sll_family = AF_PACKET;
|
|
ll.sll_ifindex = if_nametoindex(ifname);
|
|
if (ll.sll_ifindex == 0) {
|
|
perror("if_nametoindex");
|
|
return -1;
|
|
}
|
|
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
|
#endif /* __QNXNTO__ */
|
|
if (s < 0) {
|
|
perror("socket[PF_PACKET,SOCK_RAW]");
|
|
return -1;
|
|
}
|
|
|
|
if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
|
|
perror("monitor socket bind");
|
|
close(s);
|
|
return -1;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
static int hex2num(char c)
|
|
{
|
|
if (c >= '0' && c <= '9')
|
|
return c - '0';
|
|
if (c >= 'a' && c <= 'f')
|
|
return c - 'a' + 10;
|
|
if (c >= 'A' && c <= 'F')
|
|
return c - 'A' + 10;
|
|
return -1;
|
|
}
|
|
|
|
|
|
int hwaddr_aton(const char *txt, unsigned char *addr)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
int a, b;
|
|
|
|
a = hex2num(*txt++);
|
|
if (a < 0)
|
|
return -1;
|
|
b = hex2num(*txt++);
|
|
if (b < 0)
|
|
return -1;
|
|
*addr++ = (a << 4) | b;
|
|
if (i < 5 && *txt++ != ':')
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* defined(__linux__) || defined(__QNXNTO__) */
|
|
|
|
enum send_frame_type {
|
|
DISASSOC, DEAUTH, SAQUERY, AUTH, ASSOCREQ, REASSOCREQ, DLS_REQ
|
|
};
|
|
enum send_frame_protection {
|
|
CORRECT_KEY, INCORRECT_KEY, UNPROTECTED
|
|
};
|
|
|
|
|
|
static int sta_inject_frame(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
enum send_frame_type frame,
|
|
enum send_frame_protection protected,
|
|
const char *dest)
|
|
{
|
|
#ifdef __linux__
|
|
unsigned char buf[1000], *pos;
|
|
int s, res;
|
|
char bssid[20], addr[20];
|
|
char result[32], ssid[100];
|
|
size_t ssid_len;
|
|
|
|
if (get_wpa_status(get_station_ifname(), "wpa_state", result,
|
|
sizeof(result)) < 0 ||
|
|
strncmp(result, "COMPLETED", 9) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Not connected");
|
|
return 0;
|
|
}
|
|
|
|
if (get_wpa_status(get_station_ifname(), "bssid", bssid, sizeof(bssid))
|
|
< 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
|
|
"current BSSID");
|
|
return 0;
|
|
}
|
|
|
|
if (get_wpa_status(get_station_ifname(), "address", addr, sizeof(addr))
|
|
< 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
|
|
"own MAC address");
|
|
return 0;
|
|
}
|
|
|
|
if (get_wpa_status(get_station_ifname(), "ssid", ssid, sizeof(ssid))
|
|
< 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
|
|
"current SSID");
|
|
return 0;
|
|
}
|
|
ssid_len = strlen(ssid);
|
|
|
|
pos = buf;
|
|
|
|
/* Frame Control */
|
|
switch (frame) {
|
|
case DISASSOC:
|
|
*pos++ = 0xa0;
|
|
break;
|
|
case DEAUTH:
|
|
*pos++ = 0xc0;
|
|
break;
|
|
case SAQUERY:
|
|
*pos++ = 0xd0;
|
|
break;
|
|
case AUTH:
|
|
*pos++ = 0xb0;
|
|
break;
|
|
case ASSOCREQ:
|
|
*pos++ = 0x00;
|
|
break;
|
|
case REASSOCREQ:
|
|
*pos++ = 0x20;
|
|
break;
|
|
case DLS_REQ:
|
|
*pos++ = 0xd0;
|
|
break;
|
|
}
|
|
|
|
if (protected == INCORRECT_KEY)
|
|
*pos++ = 0x40; /* Set Protected field to 1 */
|
|
else
|
|
*pos++ = 0x00;
|
|
|
|
/* Duration */
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x00;
|
|
|
|
/* addr1 = DA (current AP) */
|
|
hwaddr_aton(bssid, pos);
|
|
pos += 6;
|
|
/* addr2 = SA (own address) */
|
|
hwaddr_aton(addr, pos);
|
|
pos += 6;
|
|
/* addr3 = BSSID (current AP) */
|
|
hwaddr_aton(bssid, pos);
|
|
pos += 6;
|
|
|
|
/* Seq# (to be filled by driver/mac80211) */
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x00;
|
|
|
|
if (protected == INCORRECT_KEY) {
|
|
/* CCMP parameters */
|
|
memcpy(pos, "\x61\x01\x00\x20\x00\x10\x00\x00", 8);
|
|
pos += 8;
|
|
}
|
|
|
|
if (protected == INCORRECT_KEY) {
|
|
switch (frame) {
|
|
case DEAUTH:
|
|
/* Reason code (encrypted) */
|
|
memcpy(pos, "\xa7\x39", 2);
|
|
pos += 2;
|
|
break;
|
|
case DISASSOC:
|
|
/* Reason code (encrypted) */
|
|
memcpy(pos, "\xa7\x39", 2);
|
|
pos += 2;
|
|
break;
|
|
case SAQUERY:
|
|
/* Category|Action|TransID (encrypted) */
|
|
memcpy(pos, "\x6f\xbd\xe9\x4d", 4);
|
|
pos += 4;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
/* CCMP MIC */
|
|
memcpy(pos, "\xc8\xd8\x3b\x06\x5d\xb7\x25\x68", 8);
|
|
pos += 8;
|
|
} else {
|
|
switch (frame) {
|
|
case DEAUTH:
|
|
/* reason code = 8 */
|
|
*pos++ = 0x08;
|
|
*pos++ = 0x00;
|
|
break;
|
|
case DISASSOC:
|
|
/* reason code = 8 */
|
|
*pos++ = 0x08;
|
|
*pos++ = 0x00;
|
|
break;
|
|
case SAQUERY:
|
|
/* Category - SA Query */
|
|
*pos++ = 0x08;
|
|
/* SA query Action - Request */
|
|
*pos++ = 0x00;
|
|
/* Transaction ID */
|
|
*pos++ = 0x12;
|
|
*pos++ = 0x34;
|
|
break;
|
|
case AUTH:
|
|
/* Auth Alg (Open) */
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x00;
|
|
/* Seq# */
|
|
*pos++ = 0x01;
|
|
*pos++ = 0x00;
|
|
/* Status code */
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x00;
|
|
break;
|
|
case ASSOCREQ:
|
|
/* Capability Information */
|
|
*pos++ = 0x31;
|
|
*pos++ = 0x04;
|
|
/* Listen Interval */
|
|
*pos++ = 0x0a;
|
|
*pos++ = 0x00;
|
|
/* SSID */
|
|
*pos++ = 0x00;
|
|
*pos++ = ssid_len;
|
|
memcpy(pos, ssid, ssid_len);
|
|
pos += ssid_len;
|
|
/* Supported Rates */
|
|
memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
|
|
10);
|
|
pos += 10;
|
|
/* Extended Supported Rates */
|
|
memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
|
|
pos += 6;
|
|
/* RSN */
|
|
memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
|
|
"\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
|
|
"\x00\x00\x00\x00\x0f\xac\x06", 28);
|
|
pos += 28;
|
|
break;
|
|
case REASSOCREQ:
|
|
/* Capability Information */
|
|
*pos++ = 0x31;
|
|
*pos++ = 0x04;
|
|
/* Listen Interval */
|
|
*pos++ = 0x0a;
|
|
*pos++ = 0x00;
|
|
/* Current AP */
|
|
hwaddr_aton(bssid, pos);
|
|
pos += 6;
|
|
/* SSID */
|
|
*pos++ = 0x00;
|
|
*pos++ = ssid_len;
|
|
memcpy(pos, ssid, ssid_len);
|
|
pos += ssid_len;
|
|
/* Supported Rates */
|
|
memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
|
|
10);
|
|
pos += 10;
|
|
/* Extended Supported Rates */
|
|
memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
|
|
pos += 6;
|
|
/* RSN */
|
|
memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
|
|
"\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
|
|
"\x00\x00\x00\x00\x0f\xac\x06", 28);
|
|
pos += 28;
|
|
break;
|
|
case DLS_REQ:
|
|
/* Category - DLS */
|
|
*pos++ = 0x02;
|
|
/* DLS Action - Request */
|
|
*pos++ = 0x00;
|
|
/* Destination MACAddress */
|
|
if (dest)
|
|
hwaddr_aton(dest, pos);
|
|
else
|
|
memset(pos, 0, 6);
|
|
pos += 6;
|
|
/* Source MACAddress */
|
|
hwaddr_aton(addr, pos);
|
|
pos += 6;
|
|
/* Capability Information */
|
|
*pos++ = 0x10; /* Privacy */
|
|
*pos++ = 0x06; /* QoS */
|
|
/* DLS Timeout Value */
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x01;
|
|
/* Supported rates */
|
|
*pos++ = 0x01;
|
|
*pos++ = 0x08;
|
|
*pos++ = 0x0c; /* 6 Mbps */
|
|
*pos++ = 0x12; /* 9 Mbps */
|
|
*pos++ = 0x18; /* 12 Mbps */
|
|
*pos++ = 0x24; /* 18 Mbps */
|
|
*pos++ = 0x30; /* 24 Mbps */
|
|
*pos++ = 0x48; /* 36 Mbps */
|
|
*pos++ = 0x60; /* 48 Mbps */
|
|
*pos++ = 0x6c; /* 54 Mbps */
|
|
/* TODO: Extended Supported Rates */
|
|
/* TODO: HT Capabilities */
|
|
break;
|
|
}
|
|
}
|
|
|
|
s = open_monitor("sigmadut");
|
|
if (s < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
|
|
"monitor socket");
|
|
return 0;
|
|
}
|
|
|
|
res = inject_frame(s, buf, pos - buf, protected == CORRECT_KEY);
|
|
if (res < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
|
|
"inject frame");
|
|
return 0;
|
|
}
|
|
if (res < pos - buf) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Only partial "
|
|
"frame sent");
|
|
return 0;
|
|
}
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
#else /* __linux__ */
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,sta_send_frame not "
|
|
"yet supported");
|
|
return 0;
|
|
#endif /* __linux__ */
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_tdls(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *sta, *val;
|
|
unsigned char addr[ETH_ALEN];
|
|
char buf[100];
|
|
|
|
sta = get_param(cmd, "peer");
|
|
if (sta == NULL)
|
|
sta = get_param(cmd, "station");
|
|
if (sta == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing peer address");
|
|
return 0;
|
|
}
|
|
if (hwaddr_aton(sta, addr) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Invalid peer address");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "type");
|
|
if (val == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(val, "DISCOVERY") == 0) {
|
|
snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", sta);
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to send TDLS discovery");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
if (strcasecmp(val, "SETUP") == 0) {
|
|
int status = 0, timeout = 0;
|
|
|
|
val = get_param(cmd, "Status");
|
|
if (val)
|
|
status = atoi(val);
|
|
|
|
val = get_param(cmd, "Timeout");
|
|
if (val)
|
|
timeout = atoi(val);
|
|
|
|
if (status != 0 && status != 37) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported status value");
|
|
return 0;
|
|
}
|
|
|
|
if (timeout != 0 && timeout != 301) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported timeout value");
|
|
return 0;
|
|
}
|
|
|
|
if (status && timeout) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported timeout+status "
|
|
"combination");
|
|
return 0;
|
|
}
|
|
|
|
if (status == 37 &&
|
|
wpa_command(intf, "SET tdls_testing 0x200")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to enable "
|
|
"decline setup response test mode");
|
|
return 0;
|
|
}
|
|
|
|
if (timeout == 301) {
|
|
int res;
|
|
if (dut->no_tpk_expiration)
|
|
res = wpa_command(intf,
|
|
"SET tdls_testing 0x108");
|
|
else
|
|
res = wpa_command(intf,
|
|
"SET tdls_testing 0x8");
|
|
if (res) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set short TPK "
|
|
"lifetime");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "TDLS_SETUP %s", sta);
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to send TDLS setup");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
if (strcasecmp(val, "TEARDOWN") == 0) {
|
|
snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", sta);
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to send TDLS teardown");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported TDLS frame");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int sta_ap_known(const char *ifname, const char *bssid)
|
|
{
|
|
char buf[4096];
|
|
|
|
snprintf(buf, sizeof(buf), "BSS %s", bssid);
|
|
if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
|
|
return 0;
|
|
if (strncmp(buf, "id=", 3) != 0)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int sta_scan_ap(struct sigma_dut *dut, const char *ifname,
|
|
const char *bssid)
|
|
{
|
|
int res;
|
|
struct wpa_ctrl *ctrl;
|
|
char buf[256];
|
|
|
|
if (sta_ap_known(ifname, bssid))
|
|
return 0;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"AP not in BSS table - start scan");
|
|
|
|
ctrl = open_wpa_mon(ifname);
|
|
if (ctrl == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
|
|
"wpa_supplicant monitor connection");
|
|
return -1;
|
|
}
|
|
|
|
if (wpa_command(ifname, "SCAN") < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to start scan");
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
return -1;
|
|
}
|
|
|
|
res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
|
|
buf, sizeof(buf));
|
|
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
|
|
if (res < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
|
|
return -1;
|
|
}
|
|
|
|
if (sta_ap_known(ifname, bssid))
|
|
return 0;
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "AP not in BSS table");
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2_neighadv(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *intf)
|
|
{
|
|
char buf[200];
|
|
|
|
snprintf(buf, sizeof(buf), "ndsend 2001:DB8::1 %s", intf);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to run "
|
|
"ndsend");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2_neighsolreq(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *intf)
|
|
{
|
|
char buf[200];
|
|
const char *ip = get_param(cmd, "SenderIP");
|
|
|
|
snprintf(buf, sizeof(buf), "ndisc6 -nm %s %s -r 4", ip, intf);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) == 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Neighbor Solicitation got a response "
|
|
"for %s@%s", ip, intf);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2_arpprobe(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *ifname)
|
|
{
|
|
char buf[200];
|
|
const char *ip = get_param(cmd, "SenderIP");
|
|
|
|
if (ip == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing SenderIP parameter");
|
|
return 0;
|
|
}
|
|
snprintf(buf, sizeof(buf), "arping -I %s -D %s -c 4", ifname, ip);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "arping DAD got a response "
|
|
"for %s@%s", ip, ifname);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2_arpannounce(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *ifname)
|
|
{
|
|
char buf[200];
|
|
char ip[16];
|
|
int s;
|
|
|
|
s = socket(PF_INET, SOCK_DGRAM, 0);
|
|
if (s >= 0) {
|
|
struct ifreq ifr;
|
|
struct sockaddr_in saddr;
|
|
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
|
|
"%s IP address: %s",
|
|
ifname, strerror(errno));
|
|
return -1;
|
|
} else {
|
|
memcpy(&saddr, &ifr.ifr_addr,
|
|
sizeof(struct sockaddr_in));
|
|
strncpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
|
|
}
|
|
close(s);
|
|
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "arping -I %s -s %s %s -c 4", ifname, ip,
|
|
ip);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2_arpreply(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *ifname)
|
|
{
|
|
char buf[200], addr[20];
|
|
char dst[ETH_ALEN], src[ETH_ALEN];
|
|
short ethtype = htons(ETH_P_ARP);
|
|
char *pos;
|
|
int s, res;
|
|
const char *val;
|
|
struct sockaddr_in taddr;
|
|
|
|
val = get_param(cmd, "dest");
|
|
if (val)
|
|
hwaddr_aton(val, (unsigned char *) dst);
|
|
|
|
val = get_param(cmd, "DestIP");
|
|
if (val)
|
|
inet_aton(val, &taddr.sin_addr);
|
|
|
|
if (get_wpa_status(get_station_ifname(), "address", addr,
|
|
sizeof(addr)) < 0)
|
|
return -2;
|
|
hwaddr_aton(addr, (unsigned char *) src);
|
|
|
|
pos = buf;
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x01;
|
|
*pos++ = 0x08;
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x06;
|
|
*pos++ = 0x04;
|
|
*pos++ = 0x00;
|
|
*pos++ = 0x02;
|
|
memcpy(pos, src, ETH_ALEN);
|
|
pos += ETH_ALEN;
|
|
memcpy(pos, &taddr.sin_addr, 4);
|
|
pos += 4;
|
|
memcpy(pos, dst, ETH_ALEN);
|
|
pos += ETH_ALEN;
|
|
memcpy(pos, &taddr.sin_addr, 4);
|
|
pos += 4;
|
|
|
|
s = open_monitor(get_station_ifname());
|
|
if (s < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
|
|
"monitor socket");
|
|
return 0;
|
|
}
|
|
|
|
res = inject_eth_frame(s, buf, pos - buf, ethtype, dst, src);
|
|
if (res < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
|
|
"inject frame");
|
|
return 0;
|
|
}
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2_dls_req(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *intf, const char *dest)
|
|
{
|
|
char buf[100];
|
|
|
|
if (if_nametoindex("sigmadut") == 0) {
|
|
snprintf(buf, sizeof(buf),
|
|
"iw dev %s interface add sigmadut type monitor",
|
|
get_station_ifname());
|
|
if (system(buf) != 0 ||
|
|
if_nametoindex("sigmadut") == 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
|
|
"monitor interface with '%s'", buf);
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
if (system("ifconfig sigmadut up") != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
|
|
"monitor interface up");
|
|
return -2;
|
|
}
|
|
|
|
return sta_inject_frame(dut, conn, DLS_REQ, UNPROTECTED, dest);
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_hs2(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *dest = get_param(cmd, "Dest");
|
|
const char *type = get_param(cmd, "FrameName");
|
|
const char *val;
|
|
char buf[200], *pos, *end;
|
|
int count, count2;
|
|
|
|
if (type == NULL)
|
|
type = get_param(cmd, "Type");
|
|
|
|
if (intf == NULL || dest == NULL || type == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(type, "NeighAdv") == 0)
|
|
return cmd_sta_send_frame_hs2_neighadv(dut, conn, cmd, intf);
|
|
|
|
if (strcasecmp(type, "NeighSolicitReq") == 0)
|
|
return cmd_sta_send_frame_hs2_neighsolreq(dut, conn, cmd, intf);
|
|
|
|
if (strcasecmp(type, "ARPProbe") == 0)
|
|
return cmd_sta_send_frame_hs2_arpprobe(dut, conn, cmd, intf);
|
|
|
|
if (strcasecmp(type, "ARPAnnounce") == 0)
|
|
return cmd_sta_send_frame_hs2_arpannounce(dut, conn, cmd, intf);
|
|
|
|
if (strcasecmp(type, "ARPReply") == 0)
|
|
return cmd_sta_send_frame_hs2_arpreply(dut, conn, cmd, intf);
|
|
|
|
if (strcasecmp(type, "DLS-request") == 0 ||
|
|
strcasecmp(type, "DLSrequest") == 0)
|
|
return cmd_sta_send_frame_hs2_dls_req(dut, conn, cmd, intf,
|
|
dest);
|
|
|
|
if (strcasecmp(type, "ANQPQuery") != 0 &&
|
|
strcasecmp(type, "Query") != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported HS 2.0 send frame type");
|
|
return 0;
|
|
}
|
|
|
|
if (sta_scan_ap(dut, intf, dest) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find "
|
|
"the requested AP");
|
|
return 0;
|
|
}
|
|
|
|
pos = buf;
|
|
end = buf + sizeof(buf);
|
|
count = 0;
|
|
pos += snprintf(pos, end - pos, "ANQP_GET %s ", dest);
|
|
|
|
val = get_param(cmd, "ANQP_CAP_LIST");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s257", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "VENUE_NAME");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s258", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "NETWORK_AUTH_TYPE");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s260", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "ROAMING_CONS");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s261", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "IP_ADDR_TYPE_AVAILABILITY");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s262", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "NAI_REALM_LIST");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s263", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "3GPP_INFO");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s264", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
val = get_param(cmd, "DOMAIN_LIST");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s268", count > 0 ? "," : "");
|
|
count++;
|
|
}
|
|
|
|
if (count && wpa_command(intf, buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,ANQP_GET failed");
|
|
return 0;
|
|
}
|
|
|
|
pos = buf;
|
|
end = buf + sizeof(buf);
|
|
count2 = 0;
|
|
pos += snprintf(pos, end - pos, "HS20_ANQP_GET %s ", dest);
|
|
|
|
val = get_param(cmd, "HS_CAP_LIST");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s2", count2 > 0 ? "," : "");
|
|
count2++;
|
|
}
|
|
|
|
val = get_param(cmd, "OPER_NAME");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s3", count2 > 0 ? "," : "");
|
|
count2++;
|
|
}
|
|
|
|
val = get_param(cmd, "WAN_METRICS");
|
|
if (!val)
|
|
val = get_param(cmd, "WAN_MAT");
|
|
if (!val)
|
|
val = get_param(cmd, "WAN_MET");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s4", count2 > 0 ? "," : "");
|
|
count2++;
|
|
}
|
|
|
|
val = get_param(cmd, "CONNECTION_CAPABILITY");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s5", count2 > 0 ? "," : "");
|
|
count2++;
|
|
}
|
|
|
|
val = get_param(cmd, "OP_CLASS");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s7", count2 > 0 ? "," : "");
|
|
count2++;
|
|
}
|
|
|
|
val = get_param(cmd, "OSU_PROVIDER_LIST");
|
|
if (val && atoi(val)) {
|
|
pos += snprintf(pos, end - pos, "%s8", count2 > 0 ? "," : "");
|
|
count2++;
|
|
}
|
|
|
|
if (count && count2) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before sending out "
|
|
"second query");
|
|
sleep(1);
|
|
}
|
|
|
|
if (count2 && wpa_command(intf, buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,HS20_ANQP_GET "
|
|
"failed");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "NAI_HOME_REALM_LIST");
|
|
if (val) {
|
|
if (count || count2) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
|
|
"sending out second query");
|
|
sleep(1);
|
|
}
|
|
|
|
if (strcmp(val, "1") == 0)
|
|
val = "mail.example.com";
|
|
snprintf(buf, end - pos,
|
|
"HS20_GET_NAI_HOME_REALM_LIST %s realm=%s",
|
|
dest, val);
|
|
if (wpa_command(intf, buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,HS20_GET_NAI_HOME_REALM_LIST "
|
|
"failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "ICON_REQUEST");
|
|
if (val) {
|
|
if (count || count2) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
|
|
"sending out second query");
|
|
sleep(1);
|
|
}
|
|
|
|
snprintf(buf, end - pos,
|
|
"HS20_ICON_REQUEST %s %s", dest, val);
|
|
if (wpa_command(intf, buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,HS20_ICON_REQUEST failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int ath_sta_send_frame_vht(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
char *ifname;
|
|
char buf[100];
|
|
int chwidth, nss;
|
|
|
|
val = get_param(cmd, "framename");
|
|
if (!val)
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "framename is %s", val);
|
|
|
|
/* Command sequence to generate Op mode notification */
|
|
if (val && strcasecmp(val, "Op_md_notif_frm") == 0) {
|
|
ifname = get_station_ifname();
|
|
|
|
/* Disable STBC */
|
|
snprintf(buf, sizeof(buf),
|
|
"iwpriv %s tx_stbc 0", ifname);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv tx_stbc 0 failed!");
|
|
}
|
|
|
|
/* Extract Channel width */
|
|
val = get_param(cmd, "Channel_width");
|
|
if (val) {
|
|
switch (atoi(val)) {
|
|
case 20:
|
|
chwidth = 0;
|
|
break;
|
|
case 40:
|
|
chwidth = 1;
|
|
break;
|
|
case 80:
|
|
chwidth = 2;
|
|
break;
|
|
case 160:
|
|
chwidth = 3;
|
|
break;
|
|
default:
|
|
chwidth = 2;
|
|
break;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
|
|
ifname, chwidth);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv chwidth failed!");
|
|
}
|
|
}
|
|
|
|
/* Extract NSS */
|
|
val = get_param(cmd, "NSS");
|
|
if (val) {
|
|
switch (atoi(val)) {
|
|
case 1:
|
|
nss = 1;
|
|
break;
|
|
case 2:
|
|
nss = 3;
|
|
break;
|
|
case 3:
|
|
nss = 7;
|
|
break;
|
|
default:
|
|
/* We do not support NSS > 3 */
|
|
nss = 3;
|
|
break;
|
|
}
|
|
snprintf(buf, sizeof(buf),
|
|
"iwpriv %s rxchainmask %d", ifname, nss);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv rxchainmask failed!");
|
|
}
|
|
}
|
|
|
|
/* Opmode notify */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s opmode_notify 1", ifname);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv opmode_notify failed!");
|
|
} else {
|
|
sigma_dut_print(dut, DUT_MSG_INFO,
|
|
"Sent out the notify frame!");
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_send_frame_vht(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
return ath_sta_send_frame_vht(dut, conn, cmd);
|
|
default:
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unsupported sta_set_frame(VHT) with the current driver");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int cmd_sta_send_frame(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
enum send_frame_type frame;
|
|
enum send_frame_protection protected;
|
|
char buf[100];
|
|
unsigned char addr[ETH_ALEN];
|
|
int res;
|
|
|
|
val = get_param(cmd, "program");
|
|
if (val == NULL)
|
|
val = get_param(cmd, "frame");
|
|
if (val && strcasecmp(val, "TDLS") == 0)
|
|
return cmd_sta_send_frame_tdls(dut, conn, cmd);
|
|
if (val && (strcasecmp(val, "HS2") == 0 ||
|
|
strcasecmp(val, "HS2-R2") == 0))
|
|
return cmd_sta_send_frame_hs2(dut, conn, cmd);
|
|
if (val && strcasecmp(val, "VHT") == 0)
|
|
return cmd_sta_send_frame_vht(dut, conn, cmd);
|
|
|
|
val = get_param(cmd, "TD_DISC");
|
|
if (val) {
|
|
if (hwaddr_aton(val, addr) < 0)
|
|
return -1;
|
|
snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", val);
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to send TDLS discovery");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
val = get_param(cmd, "TD_Setup");
|
|
if (val) {
|
|
if (hwaddr_aton(val, addr) < 0)
|
|
return -1;
|
|
snprintf(buf, sizeof(buf), "TDLS_SETUP %s", val);
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to start TDLS setup");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
val = get_param(cmd, "TD_TearDown");
|
|
if (val) {
|
|
if (hwaddr_aton(val, addr) < 0)
|
|
return -1;
|
|
snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", val);
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to tear down TDLS link");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
val = get_param(cmd, "TD_ChannelSwitch");
|
|
if (val) {
|
|
/* TODO */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,TD_ChannelSwitch not yet supported");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "TD_NF");
|
|
if (val) {
|
|
/* TODO */
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,TD_NF not yet supported");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "PMFFrameType");
|
|
if (val == NULL)
|
|
val = get_param(cmd, "FrameName");
|
|
if (val == NULL)
|
|
val = get_param(cmd, "Type");
|
|
if (val == NULL)
|
|
return -1;
|
|
if (strcasecmp(val, "disassoc") == 0)
|
|
frame = DISASSOC;
|
|
else if (strcasecmp(val, "deauth") == 0)
|
|
frame = DEAUTH;
|
|
else if (strcasecmp(val, "saquery") == 0)
|
|
frame = SAQUERY;
|
|
else if (strcasecmp(val, "auth") == 0)
|
|
frame = AUTH;
|
|
else if (strcasecmp(val, "assocreq") == 0)
|
|
frame = ASSOCREQ;
|
|
else if (strcasecmp(val, "reassocreq") == 0)
|
|
frame = REASSOCREQ;
|
|
else if (strcasecmp(val, "neigreq") == 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Got neighbor request");
|
|
|
|
val = get_param(cmd, "ssid");
|
|
if (val == NULL)
|
|
return -1;
|
|
|
|
res = send_neighbor_request(dut, intf, val);
|
|
if (res) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
|
|
"Failed to send neighbor report request");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
} else if (strcasecmp(val, "transmgmtquery") == 0) {
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG,
|
|
"Got Transition Management Query");
|
|
|
|
val = get_param(cmd, "ssid");
|
|
res = send_trans_mgmt_query(dut, intf, val);
|
|
if (res) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
|
|
"Failed to send Transition Management Query");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
|
|
"PMFFrameType");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "PMFProtected");
|
|
if (val == NULL)
|
|
val = get_param(cmd, "Protected");
|
|
if (val == NULL)
|
|
return -1;
|
|
if (strcasecmp(val, "Correct-key") == 0 ||
|
|
strcasecmp(val, "CorrectKey") == 0)
|
|
protected = CORRECT_KEY;
|
|
else if (strcasecmp(val, "IncorrectKey") == 0)
|
|
protected = INCORRECT_KEY;
|
|
else if (strcasecmp(val, "Unprotected") == 0)
|
|
protected = UNPROTECTED;
|
|
else {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
|
|
"PMFProtected");
|
|
return 0;
|
|
}
|
|
|
|
if (protected != UNPROTECTED &&
|
|
(frame == AUTH || frame == ASSOCREQ || frame == REASSOCREQ)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Impossible "
|
|
"PMFProtected for auth/assocreq/reassocreq");
|
|
return 0;
|
|
}
|
|
|
|
if (if_nametoindex("sigmadut") == 0) {
|
|
snprintf(buf, sizeof(buf),
|
|
"iw dev %s interface add sigmadut type monitor",
|
|
get_station_ifname());
|
|
if (system(buf) != 0 ||
|
|
if_nametoindex("sigmadut") == 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
|
|
"monitor interface with '%s'", buf);
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
if (system("ifconfig sigmadut up") != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
|
|
"monitor interface up");
|
|
return -2;
|
|
}
|
|
|
|
return sta_inject_frame(dut, conn, frame, protected, NULL);
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_parameter_hs2(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd,
|
|
const char *ifname)
|
|
{
|
|
char buf[200];
|
|
const char *val;
|
|
|
|
val = get_param(cmd, "ClearARP");
|
|
if (val && atoi(val) == 1) {
|
|
snprintf(buf, sizeof(buf), "ip neigh flush dev %s", ifname);
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to clear ARP cache");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int cmd_sta_set_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
|
|
if (intf == NULL)
|
|
return -1;
|
|
|
|
val = get_param(cmd, "program");
|
|
if (val && (strcasecmp(val, "HS2") == 0 ||
|
|
strcasecmp(val, "HS2-R2") == 0))
|
|
return cmd_sta_set_parameter_hs2(dut, conn, cmd, intf);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_macaddr(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *mac = get_param(cmd, "MAC");
|
|
|
|
if (intf == NULL || mac == NULL)
|
|
return -1;
|
|
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Change local MAC address for "
|
|
"interface %s to %s", intf, mac);
|
|
|
|
if (dut->set_macaddr) {
|
|
char buf[128];
|
|
int res;
|
|
if (strcasecmp(mac, "default") == 0) {
|
|
res = snprintf(buf, sizeof(buf), "%s",
|
|
dut->set_macaddr);
|
|
dut->tmp_mac_addr = 0;
|
|
} else {
|
|
res = snprintf(buf, sizeof(buf), "%s %s",
|
|
dut->set_macaddr, mac);
|
|
dut->tmp_mac_addr = 1;
|
|
}
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to set MAC "
|
|
"address");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
if (strcasecmp(mac, "default") == 0)
|
|
return 1;
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
|
|
"command");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int iwpriv_tdlsoffchnmode(struct sigma_dut *dut,
|
|
struct sigma_conn *conn, const char *intf,
|
|
int val)
|
|
{
|
|
char buf[200];
|
|
int res;
|
|
|
|
res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchnmode %d",
|
|
intf, val);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to configure offchannel mode");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
enum sec_ch_offset {
|
|
SEC_CH_NO,
|
|
SEC_CH_40ABOVE,
|
|
SEC_CH_40BELOW
|
|
};
|
|
|
|
|
|
static int off_chan_val(enum sec_ch_offset off)
|
|
{
|
|
switch (off) {
|
|
case SEC_CH_NO:
|
|
return 0;
|
|
case SEC_CH_40ABOVE:
|
|
return 40;
|
|
case SEC_CH_40BELOW:
|
|
return -40;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int iwpriv_set_offchan(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
const char *intf, int off_ch_num,
|
|
enum sec_ch_offset sec)
|
|
{
|
|
char buf[200];
|
|
int res;
|
|
|
|
res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchan %d",
|
|
intf, off_ch_num);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to set offchan");
|
|
return 0;
|
|
}
|
|
|
|
res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsecchnoffst %d",
|
|
intf, off_chan_val(sec));
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
if (system(buf) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to set sec chan offset");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int tdls_set_offchannel_offset(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *intf, int off_ch_num,
|
|
enum sec_ch_offset sec)
|
|
{
|
|
char buf[200];
|
|
int res;
|
|
|
|
res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNEL %d",
|
|
off_ch_num);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set offchan");
|
|
return 0;
|
|
}
|
|
res = snprintf(buf, sizeof(buf), "DRIVER TDLSSECONDARYCHANNELOFFSET %d",
|
|
off_chan_val(sec));
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to set sec chan offset");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int tdls_set_offchannel_mode(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *intf, int val)
|
|
{
|
|
char buf[200];
|
|
int res;
|
|
|
|
res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNELMODE %d",
|
|
val);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
|
|
|
|
if (wpa_command(intf, buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to configure offchannel mode");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_rfeature_tdls(const char *intf, struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
enum {
|
|
CHSM_NOT_SET,
|
|
CHSM_ENABLE,
|
|
CHSM_DISABLE,
|
|
CHSM_REJREQ,
|
|
CHSM_UNSOLRESP
|
|
} chsm = CHSM_NOT_SET;
|
|
int off_ch_num = -1;
|
|
enum sec_ch_offset sec_ch = SEC_CH_NO;
|
|
int res;
|
|
|
|
val = get_param(cmd, "Uapsd");
|
|
if (val) {
|
|
char buf[100];
|
|
if (strcasecmp(val, "Enable") == 0)
|
|
snprintf(buf, sizeof(buf), "SET ps 99");
|
|
else if (strcasecmp(val, "Disable") == 0)
|
|
snprintf(buf, sizeof(buf), "SET ps 98");
|
|
else {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
|
|
"Unsupported uapsd parameter value");
|
|
return 0;
|
|
}
|
|
if (wpa_command(intf, buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to change U-APSD "
|
|
"powersave mode");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "TPKTIMER");
|
|
if (val && strcasecmp(val, "DISABLE") == 0) {
|
|
if (wpa_command(intf, "SET tdls_testing 0x100")) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to enable no TPK "
|
|
"expiration test mode");
|
|
return 0;
|
|
}
|
|
dut->no_tpk_expiration = 1;
|
|
}
|
|
|
|
val = get_param(cmd, "ChSwitchMode");
|
|
if (val) {
|
|
if (strcasecmp(val, "Enable") == 0 ||
|
|
strcasecmp(val, "Initiate") == 0)
|
|
chsm = CHSM_ENABLE;
|
|
else if (strcasecmp(val, "Disable") == 0 ||
|
|
strcasecmp(val, "passive") == 0)
|
|
chsm = CHSM_DISABLE;
|
|
else if (strcasecmp(val, "RejReq") == 0)
|
|
chsm = CHSM_REJREQ;
|
|
else if (strcasecmp(val, "UnSolResp") == 0)
|
|
chsm = CHSM_UNSOLRESP;
|
|
else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unknown ChSwitchMode value");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "OffChNum");
|
|
if (val) {
|
|
off_ch_num = atoi(val);
|
|
if (off_ch_num == 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Invalid OffChNum");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "SecChOffset");
|
|
if (val) {
|
|
if (strcmp(val, "20") == 0)
|
|
sec_ch = SEC_CH_NO;
|
|
else if (strcasecmp(val, "40above") == 0)
|
|
sec_ch = SEC_CH_40ABOVE;
|
|
else if (strcasecmp(val, "40below") == 0)
|
|
sec_ch = SEC_CH_40BELOW;
|
|
else {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unknown SecChOffset value");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (chsm == CHSM_NOT_SET) {
|
|
/* no offchannel changes requested */
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp(intf, get_main_ifname()) != 0 &&
|
|
strcmp(intf, get_station_ifname()) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unknown interface");
|
|
return 0;
|
|
}
|
|
|
|
switch (chsm) {
|
|
case CHSM_NOT_SET:
|
|
break;
|
|
case CHSM_ENABLE:
|
|
if (off_ch_num < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing OffChNum argument");
|
|
return 0;
|
|
}
|
|
if (wifi_chip_type == DRIVER_WCN) {
|
|
res = tdls_set_offchannel_offset(dut, conn, intf,
|
|
off_ch_num, sec_ch);
|
|
} else {
|
|
res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
|
|
sec_ch);
|
|
}
|
|
if (res != 1)
|
|
return res;
|
|
if (wifi_chip_type == DRIVER_WCN)
|
|
res = tdls_set_offchannel_mode(dut, conn, intf, 1);
|
|
else
|
|
res = iwpriv_tdlsoffchnmode(dut, conn, intf, 1);
|
|
break;
|
|
case CHSM_DISABLE:
|
|
if (wifi_chip_type == DRIVER_WCN)
|
|
res = tdls_set_offchannel_mode(dut, conn, intf, 2);
|
|
else
|
|
res = iwpriv_tdlsoffchnmode(dut, conn, intf, 2);
|
|
break;
|
|
case CHSM_REJREQ:
|
|
if (wifi_chip_type == DRIVER_WCN)
|
|
res = tdls_set_offchannel_mode(dut, conn, intf, 3);
|
|
else
|
|
res = iwpriv_tdlsoffchnmode(dut, conn, intf, 3);
|
|
break;
|
|
case CHSM_UNSOLRESP:
|
|
if (off_ch_num < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing OffChNum argument");
|
|
return 0;
|
|
}
|
|
if (wifi_chip_type == DRIVER_WCN) {
|
|
res = tdls_set_offchannel_offset(dut, conn, intf,
|
|
off_ch_num, sec_ch);
|
|
} else {
|
|
res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
|
|
sec_ch);
|
|
}
|
|
if (res != 1)
|
|
return res;
|
|
if (wifi_chip_type == DRIVER_WCN)
|
|
res = tdls_set_offchannel_mode(dut, conn, intf, 4);
|
|
else
|
|
res = iwpriv_tdlsoffchnmode(dut, conn, intf, 4);
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
static int ath_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
char *token, *result;
|
|
|
|
novap_reset(dut, intf);
|
|
|
|
val = get_param(cmd, "nss_mcs_opt");
|
|
if (val) {
|
|
/* String (nss_operating_mode; mcs_operating_mode) */
|
|
int nss, mcs;
|
|
char buf[50];
|
|
char *saveptr;
|
|
|
|
token = strdup(val);
|
|
if (!token)
|
|
return 0;
|
|
result = strtok_r(token, ";", &saveptr);
|
|
if (!result) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VHT NSS not specified");
|
|
goto failed;
|
|
}
|
|
if (strcasecmp(result, "def") != 0) {
|
|
nss = atoi(result);
|
|
if (nss == 4)
|
|
ath_disable_txbf(dut, intf);
|
|
snprintf(buf, sizeof(buf), "iwpriv %s nss %d",
|
|
intf, nss);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv nss failed");
|
|
goto failed;
|
|
}
|
|
}
|
|
|
|
result = strtok_r(NULL, ";", &saveptr);
|
|
if (!result) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"VHT MCS not specified");
|
|
goto failed;
|
|
}
|
|
if (strcasecmp(result, "def") == 0) {
|
|
snprintf(buf, sizeof(buf), "iwpriv %s set11NRates 0",
|
|
intf);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv set11NRates failed");
|
|
goto failed;
|
|
}
|
|
|
|
} else {
|
|
mcs = atoi(result);
|
|
snprintf(buf, sizeof(buf), "iwpriv %s vhtmcs %d",
|
|
intf, mcs);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv vhtmcs failed");
|
|
goto failed;
|
|
}
|
|
}
|
|
/* Channel width gets messed up, fix this */
|
|
snprintf(buf, sizeof(buf), "iwpriv %s chwidth %d",
|
|
intf, dut->chwidth);
|
|
if (system(buf) != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"iwpriv chwidth failed");
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
failed:
|
|
free(token);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
switch (get_driver_type()) {
|
|
case DRIVER_ATHEROS:
|
|
return ath_sta_set_rfeature_vht(intf, dut, conn, cmd);
|
|
default:
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Unsupported sta_set_rfeature(VHT) with the current driver");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_rfeature(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *prog = get_param(cmd, "Prog");
|
|
|
|
if (intf == NULL || prog == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(prog, "TDLS") == 0)
|
|
return cmd_sta_set_rfeature_tdls(intf, dut, conn, cmd);
|
|
|
|
if (strcasecmp(prog, "VHT") == 0)
|
|
return cmd_sta_set_rfeature_vht(intf, dut, conn, cmd);
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported Prog");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_radio(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *mode = get_param(cmd, "Mode");
|
|
int res;
|
|
|
|
if (intf == NULL || mode == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(mode, "On") == 0)
|
|
res = wpa_command(intf, "SET radio_disabled 0");
|
|
else if (strcasecmp(mode, "Off") == 0)
|
|
res = wpa_command(intf, "SET radio_disabled 1");
|
|
else
|
|
return -1;
|
|
|
|
if (res) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
|
|
"radio mode");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_pwrsave(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *mode = get_param(cmd, "Mode");
|
|
int res;
|
|
|
|
if (intf == NULL || mode == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(mode, "On") == 0)
|
|
res = set_ps(intf, dut, 1);
|
|
else if (strcasecmp(mode, "Off") == 0)
|
|
res = set_ps(intf, dut, 0);
|
|
else
|
|
return -1;
|
|
|
|
if (res) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
|
|
"power save mode");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_bssid_pool(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val, *bssid;
|
|
int res;
|
|
char *buf;
|
|
size_t buf_len;
|
|
|
|
val = get_param(cmd, "BSSID_FILTER");
|
|
if (val == NULL)
|
|
return -1;
|
|
|
|
bssid = get_param(cmd, "BSSID_List");
|
|
if (atoi(val) == 0 || bssid == NULL) {
|
|
/* Disable BSSID filter */
|
|
if (wpa_command(intf, "SET bssid_filter ")) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed "
|
|
"to disable BSSID filter");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
buf_len = 100 + strlen(bssid);
|
|
buf = malloc(buf_len);
|
|
if (buf == NULL)
|
|
return -1;
|
|
|
|
snprintf(buf, buf_len, "SET bssid_filter %s", bssid);
|
|
res = wpa_command(intf, buf);
|
|
free(buf);
|
|
if (res) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to enable "
|
|
"BSSID filter");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_reset_parm(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
|
|
/* TODO: ARP */
|
|
|
|
val = get_param(cmd, "HS2_CACHE_PROFILE");
|
|
if (val && strcasecmp(val, "All") == 0)
|
|
hs2_clear_credentials(intf);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_get_key(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *key_type = get_param(cmd, "KeyType");
|
|
char buf[100], resp[200];
|
|
|
|
if (key_type == NULL)
|
|
return -1;
|
|
|
|
if (strcasecmp(key_type, "GTK") == 0) {
|
|
if (wpa_command_resp(intf, "GET gtk", buf, sizeof(buf)) < 0 ||
|
|
strncmp(buf, "FAIL", 4) == 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not fetch current GTK");
|
|
return 0;
|
|
}
|
|
snprintf(resp, sizeof(resp), "KeyValue,%s", buf);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, resp);
|
|
return 0;
|
|
} else {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
|
|
"KeyType");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int hs2_set_policy(struct sigma_dut *dut)
|
|
{
|
|
#ifdef ANDROID
|
|
system("ip rule del prio 23000");
|
|
if (system("ip rule add from all lookup main prio 23000") != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to run:ip rule add from all lookup main prio");
|
|
return -1;
|
|
}
|
|
if (system("ip route flush cache") != 0) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR,
|
|
"Failed to run ip route flush cache");
|
|
return -1;
|
|
}
|
|
return 1;
|
|
#else /* ANDROID */
|
|
return 0;
|
|
#endif /* ANDROID */
|
|
}
|
|
|
|
|
|
static int cmd_sta_hs2_associate(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val = get_param(cmd, "Ignore_blacklist");
|
|
struct wpa_ctrl *ctrl;
|
|
int res;
|
|
char bssid[20], ssid[40], resp[100], buf[100], blacklisted[100];
|
|
int tries = 0;
|
|
int ignore_blacklist = 0;
|
|
const char *events[] = {
|
|
"CTRL-EVENT-CONNECTED",
|
|
"INTERWORKING-BLACKLISTED",
|
|
"INTERWORKING-NO-MATCH",
|
|
NULL
|
|
};
|
|
|
|
start_sta_mode(dut);
|
|
|
|
blacklisted[0] = '\0';
|
|
if (val && atoi(val))
|
|
ignore_blacklist = 1;
|
|
|
|
try_again:
|
|
ctrl = open_wpa_mon(intf);
|
|
if (ctrl == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
|
|
"wpa_supplicant monitor connection");
|
|
return -2;
|
|
}
|
|
|
|
tries++;
|
|
if (wpa_command(intf, "INTERWORKING_SELECT auto")) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start "
|
|
"Interworking connection");
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
return 0;
|
|
}
|
|
|
|
buf[0] = '\0';
|
|
while (1) {
|
|
char *pos;
|
|
res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
|
|
pos = strstr(buf, "INTERWORKING-BLACKLISTED");
|
|
if (!pos)
|
|
break;
|
|
pos += 25;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Found blacklisted AP: %s",
|
|
pos);
|
|
if (!blacklisted[0])
|
|
memcpy(blacklisted, pos, strlen(pos) + 1);
|
|
}
|
|
|
|
if (ignore_blacklist && blacklisted[0]) {
|
|
char *end;
|
|
end = strchr(blacklisted, ' ');
|
|
if (end)
|
|
*end = '\0';
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Try to connect to a blacklisted network: %s",
|
|
blacklisted);
|
|
snprintf(buf, sizeof(buf), "INTERWORKING_CONNECT %s",
|
|
blacklisted);
|
|
if (wpa_command(intf, buf)) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start Interworking connection to blacklisted network");
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
return 0;
|
|
}
|
|
res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
|
|
buf, sizeof(buf));
|
|
}
|
|
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
|
|
if (res < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
|
|
"connect");
|
|
return 0;
|
|
}
|
|
|
|
if (strstr(buf, "INTERWORKING-NO-MATCH") ||
|
|
strstr(buf, "INTERWORKING-BLACKLISTED")) {
|
|
if (tries < 2) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "No match found - try again to verify no APs were missed in the scan");
|
|
goto try_again;
|
|
}
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,No network with "
|
|
"matching credentials found");
|
|
return 0;
|
|
}
|
|
|
|
if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
|
|
get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
|
|
"get current BSSID/SSID");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(resp, sizeof(resp), "SSID,%s,BSSID,%s", ssid, bssid);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, resp);
|
|
hs2_set_policy(dut);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int sta_add_credential_uname_pwd(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *ifname,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
int id;
|
|
|
|
id = add_cred(ifname);
|
|
if (id < 0)
|
|
return -2;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
|
|
|
|
val = get_param(cmd, "prefer");
|
|
if (val && atoi(val) > 0)
|
|
set_cred(ifname, id, "priority", "1");
|
|
|
|
val = get_param(cmd, "REALM");
|
|
if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"realm");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "HOME_FQDN");
|
|
if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"home_fqdn");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "Username");
|
|
if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"username");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "Password");
|
|
if (val && set_cred_quoted(ifname, id, "password", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"password");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "ROOT_CA");
|
|
if (val) {
|
|
char fname[200];
|
|
snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
|
|
#ifdef __linux__
|
|
if (!file_exists(fname)) {
|
|
char msg[300];
|
|
snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
|
|
"file (%s) not found", fname);
|
|
send_resp(dut, conn, SIGMA_ERROR, msg);
|
|
return 0;
|
|
}
|
|
#endif /* __linux__ */
|
|
if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set root CA");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int update_devdetail_imsi(struct sigma_dut *dut, const char *imsi)
|
|
{
|
|
FILE *in, *out;
|
|
char buf[500];
|
|
int found = 0;
|
|
|
|
in = fopen("devdetail.xml", "r");
|
|
if (in == NULL)
|
|
return -1;
|
|
out = fopen("devdetail.xml.tmp", "w");
|
|
if (out == NULL) {
|
|
fclose(in);
|
|
return -1;
|
|
}
|
|
|
|
while (fgets(buf, sizeof(buf), in)) {
|
|
char *pos = strstr(buf, "<IMSI>");
|
|
if (pos) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Updated DevDetail IMSI to %s",
|
|
imsi);
|
|
pos += 6;
|
|
*pos = '\0';
|
|
fprintf(out, "%s%s</IMSI>\n", buf, imsi);
|
|
found++;
|
|
} else {
|
|
fprintf(out, "%s", buf);
|
|
}
|
|
}
|
|
|
|
fclose(out);
|
|
fclose(in);
|
|
if (found)
|
|
rename("devdetail.xml.tmp", "devdetail.xml");
|
|
else
|
|
unlink("devdetail.xml.tmp");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int sta_add_credential_sim(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *ifname, struct sigma_cmd *cmd)
|
|
{
|
|
const char *val, *imsi = NULL;
|
|
int id;
|
|
char buf[200];
|
|
int res;
|
|
const char *pos;
|
|
size_t mnc_len;
|
|
char plmn_mcc[4];
|
|
char plmn_mnc[4];
|
|
|
|
id = add_cred(ifname);
|
|
if (id < 0)
|
|
return -2;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
|
|
|
|
val = get_param(cmd, "prefer");
|
|
if (val && atoi(val) > 0)
|
|
set_cred(ifname, id, "priority", "1");
|
|
|
|
val = get_param(cmd, "PLMN_MCC");
|
|
if (val == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Missing PLMN_MCC");
|
|
return 0;
|
|
}
|
|
if (strlen(val) != 3) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MCC");
|
|
return 0;
|
|
}
|
|
snprintf(plmn_mcc, sizeof(plmn_mcc), "%s", val);
|
|
|
|
val = get_param(cmd, "PLMN_MNC");
|
|
if (val == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Missing PLMN_MNC");
|
|
return 0;
|
|
}
|
|
if (strlen(val) != 2 && strlen(val) != 3) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MNC");
|
|
return 0;
|
|
}
|
|
snprintf(plmn_mnc, sizeof(plmn_mnc), "%s", val);
|
|
|
|
val = get_param(cmd, "IMSI");
|
|
if (val == NULL) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing SIM "
|
|
"IMSI");
|
|
return 0;
|
|
}
|
|
|
|
imsi = pos = val;
|
|
|
|
if (strncmp(plmn_mcc, pos, 3) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,MCC mismatch");
|
|
return 0;
|
|
}
|
|
pos += 3;
|
|
|
|
mnc_len = strlen(plmn_mnc);
|
|
if (mnc_len < 2) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC not set");
|
|
return 0;
|
|
}
|
|
|
|
if (strncmp(plmn_mnc, pos, mnc_len) != 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC mismatch");
|
|
return 0;
|
|
}
|
|
pos += mnc_len;
|
|
|
|
res = snprintf(buf, sizeof(buf), "%s%s-%s",plmn_mcc, plmn_mnc, pos);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
if (set_cred_quoted(ifname, id, "imsi", buf) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set IMSI");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "Password");
|
|
if (val && set_cred_quoted(ifname, id, "milenage", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set password");
|
|
return 0;
|
|
}
|
|
|
|
if (dut->program == PROGRAM_HS2_R2) {
|
|
/*
|
|
* Set provisioning_sp for the test cases where SIM/USIM
|
|
* provisioning is used.
|
|
*/
|
|
if (val && set_cred_quoted(ifname, id, "provisioning_sp",
|
|
"wi-fi.org") < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set provisioning_sp");
|
|
return 0;
|
|
}
|
|
|
|
update_devdetail_imsi(dut, imsi);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int sta_add_credential_cert(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
const char *ifname,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
int id;
|
|
|
|
id = add_cred(ifname);
|
|
if (id < 0)
|
|
return -2;
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
|
|
|
|
val = get_param(cmd, "prefer");
|
|
if (val && atoi(val) > 0)
|
|
set_cred(ifname, id, "priority", "1");
|
|
|
|
val = get_param(cmd, "REALM");
|
|
if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"realm");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "HOME_FQDN");
|
|
if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"home_fqdn");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "Username");
|
|
if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
|
|
"username");
|
|
return 0;
|
|
}
|
|
|
|
val = get_param(cmd, "clientCertificate");
|
|
if (val) {
|
|
char fname[200];
|
|
snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
|
|
#ifdef __linux__
|
|
if (!file_exists(fname)) {
|
|
char msg[300];
|
|
snprintf(msg, sizeof(msg),
|
|
"ErrorCode,clientCertificate "
|
|
"file (%s) not found", fname);
|
|
send_resp(dut, conn, SIGMA_ERROR, msg);
|
|
return 0;
|
|
}
|
|
#endif /* __linux__ */
|
|
if (set_cred_quoted(ifname, id, "client_cert", fname) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set client_cert");
|
|
return 0;
|
|
}
|
|
if (set_cred_quoted(ifname, id, "private_key", fname) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set private_key");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
val = get_param(cmd, "ROOT_CA");
|
|
if (val) {
|
|
char fname[200];
|
|
snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
|
|
#ifdef __linux__
|
|
if (!file_exists(fname)) {
|
|
char msg[300];
|
|
snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
|
|
"file (%s) not found", fname);
|
|
send_resp(dut, conn, SIGMA_ERROR, msg);
|
|
return 0;
|
|
}
|
|
#endif /* __linux__ */
|
|
if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
|
|
"not set root CA");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_add_credential(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *type;
|
|
|
|
start_sta_mode(dut);
|
|
|
|
type = get_param(cmd, "Type");
|
|
if (!type)
|
|
return -1;
|
|
|
|
if (strcasecmp(type, "uname_pwd") == 0)
|
|
return sta_add_credential_uname_pwd(dut, conn, intf, cmd);
|
|
|
|
if (strcasecmp(type, "sim") == 0)
|
|
return sta_add_credential_sim(dut, conn, intf, cmd);
|
|
|
|
if (strcasecmp(type, "cert") == 0)
|
|
return sta_add_credential_cert(dut, conn, intf, cmd);
|
|
|
|
send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported credential "
|
|
"type");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_scan(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *val;
|
|
char buf[100];
|
|
int res;
|
|
|
|
val = get_param(cmd, "HESSID");
|
|
if (val) {
|
|
res = snprintf(buf, sizeof(buf), "SET hessid %s", val);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
wpa_command(intf, buf);
|
|
}
|
|
|
|
val = get_param(cmd, "ACCS_NET_TYPE");
|
|
if (val) {
|
|
res = snprintf(buf, sizeof(buf), "SET access_network_type %s",
|
|
val);
|
|
if (res < 0 || res >= (int) sizeof(buf))
|
|
return -1;
|
|
wpa_command(intf, buf);
|
|
}
|
|
|
|
if (wpa_command(intf, "SCAN")) {
|
|
send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not start "
|
|
"scan");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_set_systime(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
#ifdef __linux__
|
|
struct timeval tv;
|
|
struct tm tm;
|
|
time_t t;
|
|
const char *val;
|
|
|
|
wpa_command(get_station_ifname(), "PMKSA_FLUSH");
|
|
|
|
memset(&tm, 0, sizeof(tm));
|
|
val = get_param(cmd, "seconds");
|
|
if (val)
|
|
tm.tm_sec = atoi(val);
|
|
val = get_param(cmd, "minutes");
|
|
if (val)
|
|
tm.tm_min = atoi(val);
|
|
val = get_param(cmd, "hours");
|
|
if (val)
|
|
tm.tm_hour = atoi(val);
|
|
val = get_param(cmd, "date");
|
|
if (val)
|
|
tm.tm_mday = atoi(val);
|
|
val = get_param(cmd, "month");
|
|
if (val)
|
|
tm.tm_mon = atoi(val) - 1;
|
|
val = get_param(cmd, "year");
|
|
if (val) {
|
|
int year = atoi(val);
|
|
#ifdef ANDROID
|
|
if (year > 2035)
|
|
year = 2035; /* years beyond 2035 not supported */
|
|
#endif /* ANDROID */
|
|
tm.tm_year = year - 1900;
|
|
}
|
|
t = mktime(&tm);
|
|
if (t == (time_t) -1) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Invalid date or time");
|
|
return 0;
|
|
}
|
|
|
|
memset(&tv, 0, sizeof(tv));
|
|
tv.tv_sec = t;
|
|
|
|
if (settimeofday(&tv, NULL) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "settimeofday failed: %s",
|
|
strerror(errno));
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"errorCode,Failed to set time");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
#endif /* __linux__ */
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int cmd_sta_osu(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *name, *val;
|
|
int prod_ess_assoc = 1;
|
|
char buf[200], bssid[100], ssid[100];
|
|
int res;
|
|
struct wpa_ctrl *ctrl;
|
|
|
|
name = get_param(cmd, "osuFriendlyName");
|
|
|
|
val = get_param(cmd, "ProdESSAssoc");
|
|
if (val)
|
|
prod_ess_assoc = atoi(val);
|
|
|
|
kill_dhcp_client(dut, intf);
|
|
if (start_dhcp_client(dut, intf) < 0)
|
|
return -2;
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger OSU");
|
|
mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
res = snprintf(buf, sizeof(buf),
|
|
"%s %s%s%s signup osu-ca.pem",
|
|
prod_ess_assoc ? "" : "-N",
|
|
name ? "-O'" : "", name ? name : "",
|
|
name ? "'" : "");
|
|
|
|
hs2_set_policy(dut);
|
|
if (run_hs20_osu(dut, buf) < 0) {
|
|
FILE *f;
|
|
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to complete OSU");
|
|
|
|
f = fopen("hs20-osu-client.res", "r");
|
|
if (f) {
|
|
char resp[400], res[300], *pos;
|
|
if (!fgets(res, sizeof(res), f))
|
|
res[0] = '\0';
|
|
pos = strchr(res, '\n');
|
|
if (pos)
|
|
*pos = '\0';
|
|
fclose(f);
|
|
sigma_dut_summary(dut, "hs20-osu-client provisioning failed: %s",
|
|
res);
|
|
snprintf(resp, sizeof(resp), "notify-send '%s'", res);
|
|
if (system(resp) != 0) {
|
|
}
|
|
snprintf(resp, sizeof(resp),
|
|
"SSID,,BSSID,,failureReason,%s", res);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, resp);
|
|
return 0;
|
|
}
|
|
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
|
|
return 0;
|
|
}
|
|
|
|
if (!prod_ess_assoc)
|
|
goto report;
|
|
|
|
ctrl = open_wpa_mon(intf);
|
|
if (ctrl == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
|
|
"wpa_supplicant monitor connection");
|
|
return -1;
|
|
}
|
|
|
|
res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
|
|
buf, sizeof(buf));
|
|
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
|
|
if (res < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to connect to "
|
|
"network after OSU");
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
|
|
return 0;
|
|
}
|
|
|
|
report:
|
|
if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
|
|
get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
|
|
sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get BSSID/SSID");
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "SSID,%s,BSSID,%s", ssid, bssid);
|
|
send_resp(dut, conn, SIGMA_COMPLETE, buf);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_policy_update(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
const char *val;
|
|
int timeout = 120;
|
|
|
|
val = get_param(cmd, "PolicyUpdate");
|
|
if (val == NULL || atoi(val) == 0)
|
|
return 1; /* No operation requested */
|
|
|
|
val = get_param(cmd, "Timeout");
|
|
if (val)
|
|
timeout = atoi(val);
|
|
|
|
if (timeout) {
|
|
/* TODO: time out the command and return
|
|
* PolicyUpdateStatus,TIMEOUT if needed. */
|
|
}
|
|
|
|
sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger policy update");
|
|
mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
if (run_hs20_osu(dut, "pol_upd fqdn=wi-fi.org") < 0) {
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,FAIL");
|
|
return 0;
|
|
}
|
|
|
|
send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,SUCCESS");
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int cmd_sta_er_config(struct sigma_dut *dut, struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
struct wpa_ctrl *ctrl;
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *bssid = get_param(cmd, "Bssid");
|
|
const char *ssid = get_param(cmd, "SSID");
|
|
const char *security = get_param(cmd, "Security");
|
|
const char *passphrase = get_param(cmd, "Passphrase");
|
|
const char *pin = get_param(cmd, "PIN");
|
|
char buf[1000];
|
|
char ssid_hex[200], passphrase_hex[200];
|
|
const char *keymgmt, *cipher;
|
|
|
|
if (intf == NULL)
|
|
intf = get_main_ifname();
|
|
|
|
if (!bssid) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing Bssid argument");
|
|
return 0;
|
|
}
|
|
|
|
if (!ssid) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing SSID argument");
|
|
return 0;
|
|
}
|
|
|
|
if (!security) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing Security argument");
|
|
return 0;
|
|
}
|
|
|
|
if (!passphrase) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing Passphrase argument");
|
|
return 0;
|
|
}
|
|
|
|
if (!pin) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing PIN argument");
|
|
return 0;
|
|
}
|
|
|
|
if (strlen(ssid) >= 2 * sizeof(ssid_hex) ||
|
|
strlen(passphrase) >= 2 * sizeof(passphrase_hex)) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Too long SSID/passphrase");
|
|
return 0;
|
|
}
|
|
|
|
ctrl = open_wpa_mon(intf);
|
|
if (ctrl == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
|
|
"wpa_supplicant monitor connection");
|
|
return -2;
|
|
}
|
|
|
|
if (strcasecmp(security, "wpa2-psk") == 0) {
|
|
keymgmt = "WPA2PSK";
|
|
cipher = "CCMP";
|
|
} else {
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Unsupported Security value");
|
|
return 0;
|
|
}
|
|
|
|
ascii2hexstr(ssid, ssid_hex);
|
|
ascii2hexstr(passphrase, passphrase_hex);
|
|
snprintf(buf, sizeof(buf), "WPS_REG %s %s %s %s %s %s",
|
|
bssid, pin, ssid_hex, keymgmt, cipher, passphrase_hex);
|
|
|
|
if (wpa_command(intf, buf) < 0) {
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to start registrar");
|
|
return 0;
|
|
}
|
|
|
|
snprintf(dut->er_oper_bssid, sizeof(dut->er_oper_bssid), "%s", bssid);
|
|
dut->er_oper_performed = 1;
|
|
|
|
return wps_connection_event(dut, conn, ctrl, intf, 0);
|
|
}
|
|
|
|
|
|
static int cmd_sta_wps_connect_pw_token(struct sigma_dut *dut,
|
|
struct sigma_conn *conn,
|
|
struct sigma_cmd *cmd)
|
|
{
|
|
struct wpa_ctrl *ctrl;
|
|
const char *intf = get_param(cmd, "Interface");
|
|
const char *bssid = get_param(cmd, "Bssid");
|
|
char buf[100];
|
|
|
|
if (!bssid) {
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Missing Bssid argument");
|
|
return 0;
|
|
}
|
|
|
|
ctrl = open_wpa_mon(intf);
|
|
if (ctrl == NULL) {
|
|
sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
|
|
"wpa_supplicant monitor connection");
|
|
return -2;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "WPS_NFC %s", bssid);
|
|
|
|
if (wpa_command(intf, buf) < 0) {
|
|
wpa_ctrl_detach(ctrl);
|
|
wpa_ctrl_close(ctrl);
|
|
send_resp(dut, conn, SIGMA_ERROR,
|
|
"ErrorCode,Failed to start registrar");
|
|
return 0;
|
|
}
|
|
|
|
return wps_connection_event(dut, conn, ctrl, intf, 0);
|
|
}
|
|
|
|
|
|
static int req_intf(struct sigma_cmd *cmd)
|
|
{
|
|
return get_param(cmd, "interface") == NULL ? -1 : 0;
|
|
}
|
|
|
|
|
|
void sta_register_cmds(void)
|
|
{
|
|
sigma_dut_reg_cmd("sta_get_ip_config", req_intf,
|
|
cmd_sta_get_ip_config);
|
|
sigma_dut_reg_cmd("sta_set_ip_config", req_intf,
|
|
cmd_sta_set_ip_config);
|
|
sigma_dut_reg_cmd("sta_get_info", req_intf, cmd_sta_get_info);
|
|
sigma_dut_reg_cmd("sta_get_mac_address", req_intf,
|
|
cmd_sta_get_mac_address);
|
|
sigma_dut_reg_cmd("sta_is_connected", req_intf, cmd_sta_is_connected);
|
|
sigma_dut_reg_cmd("sta_verify_ip_connection", req_intf,
|
|
cmd_sta_verify_ip_connection);
|
|
sigma_dut_reg_cmd("sta_get_bssid", req_intf, cmd_sta_get_bssid);
|
|
sigma_dut_reg_cmd("sta_set_encryption", req_intf,
|
|
cmd_sta_set_encryption);
|
|
sigma_dut_reg_cmd("sta_set_psk", req_intf, cmd_sta_set_psk);
|
|
sigma_dut_reg_cmd("sta_set_eaptls", req_intf, cmd_sta_set_eaptls);
|
|
sigma_dut_reg_cmd("sta_set_eapttls", req_intf, cmd_sta_set_eapttls);
|
|
sigma_dut_reg_cmd("sta_set_eapsim", req_intf, cmd_sta_set_eapsim);
|
|
sigma_dut_reg_cmd("sta_set_peap", req_intf, cmd_sta_set_peap);
|
|
sigma_dut_reg_cmd("sta_set_eapfast", req_intf, cmd_sta_set_eapfast);
|
|
sigma_dut_reg_cmd("sta_set_eapaka", req_intf, cmd_sta_set_eapaka);
|
|
sigma_dut_reg_cmd("sta_set_eapakaprime", req_intf,
|
|
cmd_sta_set_eapakaprime);
|
|
sigma_dut_reg_cmd("sta_set_security", req_intf, cmd_sta_set_security);
|
|
sigma_dut_reg_cmd("sta_set_uapsd", req_intf, cmd_sta_set_uapsd);
|
|
/* TODO: sta_set_ibss */
|
|
/* TODO: sta_set_mode */
|
|
sigma_dut_reg_cmd("sta_set_wmm", req_intf, cmd_sta_set_wmm);
|
|
sigma_dut_reg_cmd("sta_associate", req_intf, cmd_sta_associate);
|
|
/* TODO: sta_up_load */
|
|
sigma_dut_reg_cmd("sta_preset_testparameters", req_intf,
|
|
cmd_sta_preset_testparameters);
|
|
/* TODO: sta_set_system */
|
|
sigma_dut_reg_cmd("sta_set_11n", req_intf, cmd_sta_set_11n);
|
|
/* TODO: sta_set_rifs_test */
|
|
sigma_dut_reg_cmd("sta_set_wireless", req_intf, cmd_sta_set_wireless);
|
|
sigma_dut_reg_cmd("sta_send_addba", req_intf, cmd_sta_send_addba);
|
|
/* TODO: sta_send_coexist_mgmt */
|
|
sigma_dut_reg_cmd("sta_disconnect", req_intf, cmd_sta_disconnect);
|
|
sigma_dut_reg_cmd("sta_reassoc", req_intf, cmd_sta_reassoc);
|
|
sigma_dut_reg_cmd("sta_reassociate", req_intf, cmd_sta_reassoc);
|
|
sigma_dut_reg_cmd("sta_reset_default", req_intf,
|
|
cmd_sta_reset_default);
|
|
sigma_dut_reg_cmd("sta_send_frame", req_intf, cmd_sta_send_frame);
|
|
sigma_dut_reg_cmd("sta_set_macaddr", req_intf, cmd_sta_set_macaddr);
|
|
sigma_dut_reg_cmd("sta_set_rfeature", req_intf, cmd_sta_set_rfeature);
|
|
sigma_dut_reg_cmd("sta_set_radio", req_intf, cmd_sta_set_radio);
|
|
sigma_dut_reg_cmd("sta_set_pwrsave", req_intf, cmd_sta_set_pwrsave);
|
|
sigma_dut_reg_cmd("sta_bssid_pool", req_intf, cmd_sta_bssid_pool);
|
|
sigma_dut_reg_cmd("sta_reset_parm", req_intf, cmd_sta_reset_parm);
|
|
sigma_dut_reg_cmd("sta_get_key", req_intf, cmd_sta_get_key);
|
|
sigma_dut_reg_cmd("sta_hs2_associate", req_intf,
|
|
cmd_sta_hs2_associate);
|
|
sigma_dut_reg_cmd("sta_add_credential", req_intf,
|
|
cmd_sta_add_credential);
|
|
sigma_dut_reg_cmd("sta_scan", req_intf, cmd_sta_scan);
|
|
sigma_dut_reg_cmd("sta_set_systime", NULL, cmd_sta_set_systime);
|
|
sigma_dut_reg_cmd("sta_osu", req_intf, cmd_sta_osu);
|
|
sigma_dut_reg_cmd("sta_policy_update", req_intf, cmd_sta_policy_update);
|
|
sigma_dut_reg_cmd("sta_er_config", NULL, cmd_sta_er_config);
|
|
sigma_dut_reg_cmd("sta_wps_connect_pw_token", req_intf,
|
|
cmd_sta_wps_connect_pw_token);
|
|
sigma_dut_reg_cmd("sta_exec_action", req_intf, cmd_sta_exec_action);
|
|
sigma_dut_reg_cmd("sta_get_events", req_intf, cmd_sta_get_events);
|
|
sigma_dut_reg_cmd("sta_get_parameter", req_intf, cmd_sta_get_parameter);
|
|
}
|